Logging em aplicações Kotlin: melhores práticas
Logging não é apenas registrar mensagens no console. Em aplicações Kotlin modernas (de Android a backend com Ktor ou Spring Boot), os logs se tornam a principal fonte de informação para depuração, monitoramento e auditoria. Logging configurado incorretamente pode levar à perda de dados críticos ou, inversamente, ao transbordamento do disco. Neste artigo, vamos analisar as melhores práticas de logging em Kotlin, considerar bibliotecas populares e mostrar exemplos de código.
1. Escolha da biblioteca de logging em Kotlin
Kotlin é totalmente compatível com o ecossistema Java, portanto você pode usar qualquer biblioteca Java para logging. No entanto, existem wrappers específicos do Kotlin que tornam o código mais idiomático.
- SLF4J (Simple Logging Facade for Java) — uma fachada que permite conectar diferentes implementações (Logback, Log4j2, java.util.logging). É o padrão de facto no mundo Java.
- Logback — a implementação mais popular do SLF4J. Rápida, flexível, com suporte a logging assíncrono.
- kotlin-logging — um wrapper leve sobre o SLF4J, usando recursos do Kotlin (inline functions, lambdas). Permite escrever código no estilo
logger.debug { "Mensagem" }.
Stack recomendado para um novo projeto: SLF4J + Logback + kotlin-logging. Exemplo de configuração em build.gradle.kts:
dependencies { implementation("ch.qos.logback:logback-classic:1.4.14") implementation("io.github.microutils:kotlin-logging-jvm:3.0.5")}2. Níveis de logging corretos
Usar o nível correto é a base de um bom logging. No SLF4J, existem 5 níveis (em ordem crescente de gravidade): TRACE, DEBUG, INFO, WARN, ERROR.
- TRACE — informação muito detalhada para depuração (entrada/saída de métodos, valores de variáveis). Ative apenas no ambiente de desenvolvimento.
- DEBUG — informação útil para o desenvolvedor (estado do sistema, cálculos intermediários).
- INFO — eventos importantes da operação da aplicação (inicialização, processamento de requisição, conexão ao banco de dados).
- WARN — situações potencialmente perigosas (erros não críticos, APIs obsoletas).
- ERROR — erros que exigem intervenção (exceções, falhas na lógica de negócios).
Exemplo de uso com kotlin-logging:
import mu.KotlinLogging
private val logger = KotlinLogging.logger {}
fun processOrder(orderId: String) { logger.info { "Início do processamento do pedido $orderId" } try { // lógica de negócios logger.debug { "Pedido $orderId: valor = $amount" } } catch (e: Exception) { logger.error(e) { "Erro ao processar o pedido $orderId" } }}Importante: Evite usar logger.info("String " + variavel) — isso cria a string mesmo se o nível não estiver ativado. Use lambdas: logger.info { "String $variavel" }.
3. Logging estruturado (Structured Logging)
Logs de texto são difíceis de analisar. É melhor usar formatos estruturados (JSON, Logstash), que permitem que máquinas analisem os dados facilmente. Isso é especialmente importante para arquitetura de microsserviços e sistemas centralizados de coleta de logs (ELK, Grafana Loki).
No Logback, para o formato JSON, usa-se a biblioteca logstash-logback-encoder:
// build.gradle.ktsimplementation("net.logstash.logback:logstash-logback-encoder:7.4")Configuração do logback.xml:
<configuration> <appender name="JSON" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="net.logstash.logback.encoder.LogstashEncoder"/> </appender>
<root leve