Мониторинг Kotlin приложений: метрики и алерты продвинутого уровня

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Мониторинг Kotlin приложений: метрики и алерты продвинутого уровня

В современной разработке программного обеспечения мониторинг перестал быть опцией — это обязательный элемент production-инфраструктуры. Для Kotlin-приложений, работающих под высокой нагрузкой, недостаточно простого логирования. Требуется полноценная observability: сбор метрик, настройка алертов и визуализация данных в реальном времени. В этой статье мы разберем продвинутые техники мониторинга Kotlin-приложений с использованием стека Prometheus, Grafana и Micrometer.

1. Инструментарий: Micrometer и Prometheus

Лучший способ внедрить мониторинг в Kotlin-приложение — использовать библиотеку Micrometer. Она предоставляет фасад для различных систем мониторинга, включая Prometheus. Micrometer поддерживает как JVM-метрики, так и кастомные бизнес-показатели.

Подключим зависимости в 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")
}

Для Ktor-приложения настройка выглядит так:

import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.application.*
import io.ktor.server.metrics.micrometer.*
import io.micrometer.prometheus.PrometheusMeterRegistry
import io.micrometer.prometheus.PrometheusConfig

fun main() {
    val meterRegistry = PrometheusMeterRegistry(PrometheusConfig.DEFAULT)

    embeddedServer(Netty, port = 8080) {
        install(MicrometerMetrics) {
            registry = meterRegistry
            // Добавляем стандартные метрики JVM
            meterRegistry.config().commonTags("application", "my-kotlin-app")
        }
        routing {
            get("/metrics") {
                call.respond(meterRegistry.scrape())
            }
        }
    }.start(wait = true)
}

Этот код автоматически собирает метрики HTTP-запросов, пула потоков и JVM. Эндпоинт /metrics отдаёт данные в формате Prometheus.

2. Кастомные метрики: бизнес-показатели

Стандартных метрик часто недостаточно. Для продвинутого мониторинга нужно собирать бизнес-показатели: количество заказов, время обработки платежей, частоту ошибок валидации.

Пример создания кастомного счётчика и таймера:

import io.micrometer.core.instrument.Counter
import io.micrometer.core.instrument.MeterRegistry
import io.micrometer.core.instrument.Timer
import java.util.concurrent.TimeUnit

class OrderMetrics(private val registry: MeterRegistry) {
    private val orderCounter: Counter = Counter.builder("orders.created")
        .description("Total number of created orders")
        .register(registry)

    private val processTimer: Timer = Timer.builder("orders.processing.time")
        .description("Time to process an order")
        .publishPercentiles(0.5, 0.95, 0.99)
        .register(registry)

    fun recordOrderCreation() {
        orderCounter.increment()
    }

    fun measureProcessingTime(block: () -> Unit) {
        processTimer.record(block)
    }
}

Использование в сервисе:

class OrderService(private val metrics: OrderMetrics) {
    fun createOrder(order: Order): Order {
        metrics.recordOrderCreation()
        return metrics.measureProcessingTime {
            // бизнес-логика
            Thread.sleep(100) // симуляция
            order
        }
    }
}

Обратите внимание на перцентили: они позволяют отслеживать не только среднее время, но и "хвосты" (p99), что критично для SLA.

3. Настройка алертов в Prometheus

Сбор метрик бесполезен без системы оповещения. Алерты настраиваются в конфигурации Prometheus (файл alert.rules.yml).

Пример правил для Kotlin-приложения:

groups:
  - name: kotlin_app_alerts
    rules:
      - alert: HighErrorRate
        expr: rate(http_server_requests_seconds_count{status=~"5.."}[5m]) / rate(http_server_requests_seconds_count[5m]) > 0.05
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "High HTTP 5xx error rate ({{ $value | humanizePercentage }})"

      - alert: SlowResponses
        expr: histogram_quantile(0.95, rate(http_server_requests_seconds_bucket[5m])) > 2
        for: 1m
        labels:
          severity: warning
        annotations:
          summary: "P95 response time is {{ $value }} seconds"

      - alert: HighHeapUsage
        expr: jvm_memory_used_bytes{area="heap"} / jvm_memory_max_bytes{area="heap"} > 0.85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "JVM heap usage > 85%"

Эти правила срабатывают при превышении порогов: более 5% ошибок 5xx, p95 ответа дольше 2 секунд, заполнение кучи более 85%.

Для отправки уведомлений используется Alertmanager. Пример конфигурации для Telegram:

receivers:
  - name: 'telegram'
    telegram_configs:
      - bot_token: 'YOUR_BOT_TOKEN'
        chat_id: 123456789
        parse_mode: 'HTML'

route:
  receiver: 'telegram'
  group_by: ['alertname', 'severity']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h

4. Визуализация в Grafana: продвинутые дашборды

Grafana позволяет создавать сложные дашборды. Для Kotlin-приложения рекомендую включить следующие панели:

  • RPS и Latency — график запросов в секунду с разбивкой по статусам (2xx, 4xx, 5xx) и p50/p95/p99 latency.
  • JVM Metrics — heap usage, GC pauses, количество потоков, CPU usage.
  • Бизнес-метрики — кастомные счётчики и таймеры, например "заказы в минуту" или "время обработки платежа".
  • Алерты — статус активных алертов, история срабатываний.

Пример PromQL-запроса для панели "P95 latency":

histogram_quantile(0.95, 
  sum(rate(http_server_requests_seconds_bucket[5m])) by (le, uri)
)

Для отображения да

Блоги

Рекомендаций по книгам