Prometheus Metrics in Kotlin: A Complete Integration Guide
In modern development, monitoring and collecting metrics are critically important for maintaining application stability. Prometheus is a leading open-source monitoring system that allows you to collect, store, and analyze performance data. In this article, we will look at how to add Prometheus metrics to Kotlin applications using the Micrometer library and a configurable HTTP server.
Why Use Prometheus with Kotlin?
- Flexibility: Prometheus supports many metric types: counters, histograms, summaries, and gauges.
- Built-in Integration: Kotlin is fully compatible with the Java ecosystem, allowing you to use Micrometer — a popular tool for collecting metrics.
- Scalability: Prometheus easily scales for monitoring microservices and distributed systems.
Setting Up the Project with Gradle
To start, add dependencies to the build.gradle.kts file:
dependencies { implementation("io.micrometer:micrometer-core:1.12.0") implementation("io.micrometer:micrometer-registry-prometheus:1.12.0") // For HTTP server (using Ktor) implementation("io.ktor:ktor-server-netty:2.3.7") implementation("io.ktor:ktor-server-content-negotiation:2.3.7")}Creating a Prometheus Registry
The basis of metric collection is the PrometheusMeterRegistry. Create it in your application:
import io.micrometer.prometheus.PrometheusConfigimport io.micrometer.prometheus.PrometheusMeterRegistry
val registry = PrometheusMeterRegistry(PrometheusConfig.DEFAULT)Defining Metrics
Let's look at three main metric types:
- Counter — a counter that only increases (e.g., number of requests).
- Gauge — a current value (e.g., number of active users).
- Timer — the execution time of operations.
Example of creating metrics:
import io.micrometer.core.instrument.Counterimport io.micrometer.core.instrument.Gaugeimport io.micrometer.core.instrument.Timer
val requestCounter: Counter = Counter .builder("api.requests.total") .description("Total number of API requests") .register(registry)
val activeUsersGauge: Gauge = Gauge .builder("app.users.active") .description("Number of active users") .register(registry) { activeUsersCount }
val requestTimer: Timer = Timer .builder("api.requests.duration") .description("Request execution time") .register(registry)
var activeUsersCount = 0Exporting Metrics via HTTP
For Prometheus to collect metrics, they need to be exported in the /metrics format. Use Ktor to create an endpoint:
import io.ktor.server.engine.embeddedServerimport io.ktor.server.netty.Nettyimport io.ktor.server.routing.getimport io.ktor.server.routing.routingimport io.ktor.server.response.respondText
fun startMetricsServer(port: Int = 9090) { embeddedServer(Netty, port = port) { routing { get("/metrics") { val scrape = registry.scrape() call.respondText(scrape, contentType = io.ktor.http.ContentType.Text.Plain) } } }.start(wait = false)}Integration with Business Logic
Update metrics in your application code:
fun handleRequest() { requestTimer.record { // Simulate request processing Thread.sleep(100) requestCounter.increment() }}
fun userLoggedIn() { activeUsersCount++}
fun userLoggedOut() { act