diff --git a/server/build.gradle b/server/build.gradle index 2de1ec780..c85002498 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -61,6 +61,9 @@ dependencies { implementation "io.ktor:ktor-html-builder:$ktor_version" implementation "io.ktor:ktor-jackson:$ktor_version" implementation "org.jetbrains:kotlin-css-jvm:1.0.0-pre.31-kotlin-1.2.41" + implementation "io.prometheus:simpleclient:0.9.0" + implementation "io.prometheus:simpleclient_httpserver:0.9.0" + implementation "io.prometheus:simpleclient_hotspot:0.9.0" testImplementation "io.ktor:ktor-server-tests:$ktor_version" testImplementation "org.mockito:mockito-core:2.+" } diff --git a/server/src/org/isoron/uhabits/sync/app/MetricsModule.kt b/server/src/org/isoron/uhabits/sync/app/MetricsModule.kt new file mode 100644 index 000000000..2661568c9 --- /dev/null +++ b/server/src/org/isoron/uhabits/sync/app/MetricsModule.kt @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016-2020 Alinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +package org.isoron.uhabits.sync.app + +import io.ktor.application.* +import io.ktor.http.* +import io.ktor.response.* +import io.ktor.routing.* +import io.prometheus.client.* +import io.prometheus.client.exporter.common.* +import io.prometheus.client.hotspot.* +import java.io.* + + +fun Routing.metrics(app: SyncApplication) { + // Register JVM metrics + DefaultExports.initialize() + + get("/metrics") { + val writer = StringWriter() + TextFormat.write004( + writer, + CollectorRegistry.defaultRegistry.filteredMetricFamilySamples(setOf()), + ) + call.respond(HttpStatusCode.OK, writer.toString()) + } +} diff --git a/server/src/org/isoron/uhabits/sync/app/SyncApplication.kt b/server/src/org/isoron/uhabits/sync/app/SyncApplication.kt index c07522e1f..ac44cceb9 100644 --- a/server/src/org/isoron/uhabits/sync/app/SyncApplication.kt +++ b/server/src/org/isoron/uhabits/sync/app/SyncApplication.kt @@ -47,6 +47,7 @@ class SyncApplication( registration(this@SyncApplication) storage(this@SyncApplication) links(this@SyncApplication) + metrics(this@SyncApplication) } } } diff --git a/server/src/org/isoron/uhabits/sync/server/RepositorySyncServer.kt b/server/src/org/isoron/uhabits/sync/server/RepositorySyncServer.kt index 4e20b4725..cb8c16e17 100644 --- a/server/src/org/isoron/uhabits/sync/server/RepositorySyncServer.kt +++ b/server/src/org/isoron/uhabits/sync/server/RepositorySyncServer.kt @@ -19,6 +19,7 @@ package org.isoron.uhabits.sync.server +import io.prometheus.client.* import org.isoron.uhabits.sync.* import org.isoron.uhabits.sync.links.* import org.isoron.uhabits.sync.repository.* @@ -32,13 +33,21 @@ class RepositorySyncServer( private val linkManager: LinkManager = LinkManager(), ) : AbstractSyncServer { + private val requestsCounter: Counter = Counter.build() + .name("requests_total") + .help("Total number of requests") + .labelNames("method") + .register() + override suspend fun register(): String { + requestsCounter.labels("register").inc() val key = generateKey() repo.put(key, SyncData(0, "")) return key } override suspend fun put(key: String, newData: SyncData) { + requestsCounter.labels("put").inc() if (!repo.contains(key)) { throw KeyNotFoundException() } @@ -50,6 +59,7 @@ class RepositorySyncServer( } override suspend fun getData(key: String): SyncData { + requestsCounter.labels("getData").inc() if (!repo.contains(key)) { throw KeyNotFoundException() } @@ -57,6 +67,7 @@ class RepositorySyncServer( } override suspend fun getDataVersion(key: String): Long { + requestsCounter.labels("getDataVersion").inc() if (!repo.contains(key)) { throw KeyNotFoundException() } @@ -64,10 +75,12 @@ class RepositorySyncServer( } override suspend fun registerLink(syncKey: String): Link { + requestsCounter.labels("registerLink").inc() return linkManager.register(syncKey) } override suspend fun getLink(id: String): Link { + requestsCounter.labels("getLink").inc() return linkManager.get(id) }