Ktor 2.3.12 Help

Micrometer metrics

The MicrometerMetrics plugin enables Micrometer metrics in your Ktor server application and allows you to choose the required monitoring system, such as Prometheus, JMX, Elastic, and so on. By default, Ktor exposes metrics for monitoring HTTP requests and a set of low-level metrics for monitoring the JVM. You can customize these metrics or create new ones.

Add dependencies

To enable MicrometerMetrics, you need to include the following artifacts in the build script:

  • Add the ktor-server-metrics-micrometer dependency:

    implementation("io.ktor:ktor-server-metrics-micrometer:$ktor_version")
    implementation "io.ktor:ktor-server-metrics-micrometer:$ktor_version"
    <dependency> <groupId>io.ktor</groupId> <artifactId>ktor-server-metrics-micrometer-jvm</artifactId> <version>${ktor_version}</version> </dependency>
  • Add a dependency required for a monitoring system. The example below shows how to add an artifact for Prometheus:

    implementation("io.micrometer:micrometer-registry-prometheus:$prometheus_version")
    implementation "io.micrometer:micrometer-registry-prometheus:$prometheus_version"
    <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> <version>${prometheus_version}</version> </dependency>

    You can replace $prometheus_version with the required version of the micrometer-registry-prometheus artifact, for example, 1.10.3.

Install MicrometerMetrics

To install the MicrometerMetrics plugin to the application, pass it to the install function in the specified module. The code snippets below show how to install MicrometerMetrics...

  • ... inside the embeddedServer function call.

  • ... inside the explicitly defined module, which is an extension function of the Application class.

import io.ktor.server.engine.* import io.ktor.server.netty.* import io.ktor.server.application.* import io.ktor.server.metrics.micrometer.* fun main() { embeddedServer(Netty, port = 8080) { install(MicrometerMetrics) // ... }.start(wait = true) }
import io.ktor.server.application.* import io.ktor.server.metrics.micrometer.* // ... fun Application.module() { install(MicrometerMetrics) // ... }

Exposed metrics

Ktor exposes the following metrics for monitoring HTTP requests:

  • ktor.http.server.requests.active: a gauge that counts the number of concurrent HTTP requests. This metric doesn't provide any tags.

  • ktor.http.server.requests: a timer for measuring the time of each request. This metric provides a set of tags for monitoring request data, including address for a requested URL, method for an HTTP method, route for a Ktor route handling requests, and so on.

You can customize the default ktor.http.server.requests prefix using the metricName configuration property.

In addition to HTTP metrics, Ktor exposes a set of metrics for monitoring the JVM.

Create a registry

After installing MicrometerMetrics, you need to create a registry for your monitoring system and assign it to the registry property. In the example below, the PrometheusMeterRegistry is created outside the install block to have the capability to reuse this registry in different route handlers:

fun Application.module() { val appMicrometerRegistry = PrometheusMeterRegistry(PrometheusConfig.DEFAULT) install(MicrometerMetrics) { registry = appMicrometerRegistry } }

Configure metrics

The MicrometerMetrics plugin provides various configuration options that can be accessed using MicrometerMetricsConfig.

Timers

To customize tags for each timer, you can use the timers function that is called for each request:

install(MicrometerMetrics) { // ... timers { call, exception -> tag("region", call.request.headers["regionId"]) } }

Distribution statistics

You configure distribution statistics using the distributionStatisticConfig property, for example:

install(MicrometerMetrics) { distributionStatisticConfig = DistributionStatisticConfig.Builder() .percentilesHistogram(true) .maximumExpectedValue(Duration.ofSeconds(20).toNanos().toDouble()) .serviceLevelObjectives( Duration.ofMillis(100).toNanos().toDouble(), Duration.ofMillis(500).toNanos().toDouble() ) .build() }

JVM and system metrics

In addition to HTTP metrics, Ktor exposes a set of metrics for monitoring the JVM. You can customize a list of these metrics using the meterBinders property, for example:

install(MicrometerMetrics) { meterBinders = listOf( JvmMemoryMetrics(), JvmGcMetrics(), ProcessorMetrics() ) }

You can also assign an empty list to disable these metrics completely.

Prometheus: expose a scrape endpoint

If you use Prometheus as a monitoring system, you need to expose an HTTP endpoint to the Prometheus scraper. In Ktor, you can do this in the following way:

  1. Create a dedicated route that accepts GET requests by the required address (/metrics in the example below).

  2. Use call.respond to send scraping data to Prometheus.

    fun Application.module() { val appMicrometerRegistry = PrometheusMeterRegistry(PrometheusConfig.DEFAULT) install(MicrometerMetrics) { registry = appMicrometerRegistry } routing { get("/metrics") { call.respond(appMicrometerRegistry.scrape()) } } }

    You can find the full example here: micrometer-metrics.

Last modified: 02 April 2024