Monitoramento de aplicações Kotlin: métricas e alertas de nível avançado
No desenvolvimento de software moderno, o monitoramento deixou de ser uma opção — é um elemento obrigatório da infraestrutura de produção. Para aplicações Kotlin que operam sob alta carga, a simples criação de logs não é suficiente. É necessária uma observability completa: coleta de métricas, configuração de alertas e visualização de dados em tempo real. Neste artigo, abordaremos técnicas avançadas de monitoramento de aplicações Kotlin usando o stack Prometheus, Grafana e Micrometer.
1. Ferramentas: Micrometer e Prometheus
A melhor maneira de implementar monitoramento em uma aplicação Kotlin é usar a biblioteca Micrometer. Ela fornece uma fachada para vários sistemas de monitoramento, incluindo o Prometheus. O Micrometer suporta tanto métricas da JVM quanto indicadores de negócio personalizados.
Vamos adicionar as dependências no 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")}Para uma aplicação Ktor, a configuração fica assim:
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.PrometheusMeterRegistryimport io.micrometer.prometheus.PrometheusConfig
fun main() { val meterRegistry = PrometheusMeterRegistry(PrometheusConfig.DEFAULT)
embeddedServer(Netty, port = 8080) { install(MicrometerMetrics) { registry = meterRegistry // Adiciona métricas padrão da JVM meterRegistry.config().commonTags("application", "my-kotlin-app") } routing { get("/metrics") { call.respond(meterRegistry.scrape()) } } }.start(wait = true)}Este código coleta automaticamente métricas de requisições HTTP, pool de threads e JVM. O endpoint /metrics fornece os dados no formato do Prometheus.
2. Métricas personalizadas: indicadores de negócio
Muitas vezes, as métricas padrão não são suficientes. Para um monitoramento avançado, é necessário coletar indicadores de negócio: número de pedidos, tempo de processamento de pagamentos, frequência de erros de validação.
Exemplo de criação de um contador e um timer personalizados:
import io.micrometer.core.instrument.Counterimport io.micrometer.core.instrument.MeterRegistryimport io.micrometer.core.instrument.Timerimport 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) }}Uso no serviço:
class OrderService(private val metrics: OrderMetrics) { fun createOrder(order: Order): Order { metrics.recordOrderCreation() return metrics.measureProcessingTime { // lógica de negócio Thread.sleep(100) // simulação order } }}Observe os percentis: eles permitem rastrear não apenas o tempo médio, mas também as "caudas" (p99), o que é crítico para SLAs.
3. Configuração de alertas no Prometheus
A coleta de métricas é inútil sem um sistema de notificação. Os alertas são configurados no arquivo de configuração do Prometheus (alert.rules.yml).
Exemplo de regras para Kotl