Monitoring Kotlin Applications: Metrics and Alerts
In modern software development, monitoring has become an integral part of the production ecosystem. For Kotlin applications running on JVM, properly configured monitoring allows not only tracking system state in real time but also preventing incidents before they affect users. In this article, we will look at how to organize metric collection and configure alerts for Kotlin applications using modern tools such as Micrometer and Prometheus.
Why monitor Kotlin applications?
Kotlin, being a language running on top of JVM, inherits all monitoring capabilities of the Java ecosystem but adds its own features — coroutines, extension functions, and null-safety. Monitoring helps answer three key questions:
- What is happening right now? — current load, number of requests, memory usage.
- What happened before? — historical data for trend analysis and finding bottlenecks.
- What could go wrong? — predicting problems based on metrics.
Without monitoring, any application works "blindly," and even a minor memory leak can lead to downtime.
Key metrics for Kotlin applications
Before configuring tools, it is important to understand which metrics are critical for JVM applications in Kotlin.
JVM metrics
This is a basic set that shows the health of the virtual machine:
- Heap and non-heap memory usage
- Number of threads (active, daemon, blocked)
- GC (Garbage Collection) time and collection frequency
- CPU load
Business metrics
Reflect the application's own operation:
- Number of HTTP requests (RPS — requests per second)
- Response time (latency p50, p95, p99)
- Number of errors (4xx, 5xx)
- Queue depth (if using coroutines or message queues)
Coroutine metrics
Since Kotlin actively uses coroutines, it is useful to monitor:
- Number of active coroutines
- Coroutine execution time
- Number of cancelled coroutines
Monitoring tools: Micrometer + Prometheus
The standard stack for monitoring Kotlin applications includes Micrometer (a library for collecting metrics) and Prometheus (a storage and alerting system). Micrometer acts as a facade that supports many backends (Prometheus, Datadog, Graphite, etc.), but Prometheus is the most popular choice.
Adding dependencies
For Gradle (build.gradle.kts):
dependencies { implementation("io.micrometer:micrometer-core:1.12.0") implementation("io.micrometer:micrometer-registry-prometheus:1.12.0") implementation("io.ktor:ktor-server-metrics-micrometer:2.3.7")}Configuring metric collection in Ktor
Let's look at a configuration example for a web application on Ktor — a popular framework for Kotlin:
import io.micrometer.prometheus.PrometheusMeterRegistryimport io.micrometer.prometheus.PrometheusConfigimport io.ktor.server.engine.*import io.ktor.server.netty.*import io.ktor.server.routing.*import io.ktor.server.response.*import io.ktor.server.metrics.micrometer.*
fun main() { val meterRegistry = PrometheusMeterRegistry(PrometheusConfig.DEFAULT)
embeddedServer(Netty, port = 8080) { install(MicrometerMetrics) { registry = meterRegistry // Add standard tags meterRegistry.config().commonTags("application", "my-kotlin-app") }
routing { get("/metrics") { call.respond(meterRegistry.