Introdução: Por que o registro (logging) é importante para sua aplicação Kotlin
O registro (logging) não é apenas gravar mensagens no console. É a base da depuração, monitoramento e suporte de qualquer produto de software. Para desenvolvedores iniciantes em Kotlin, um registro correto pode ser a diferença entre horas de busca sem sentido por um bug e uma solução rápida para o problema. Neste artigo, abordaremos as melhores práticas de registro em aplicações Kotlin que ajudarão você a escrever código limpo, sustentável e eficiente.
Kotlin, como linguagem de programação moderna, não possui um mecanismo de registro embutido, mas se integra perfeitamente com bibliotecas Java populares. Veremos como configurar o SLF4J (Simple Logging Facade for Java) em conjunto com o Logback, além de como evitar erros comuns de iniciantes.
1. Escolha da biblioteca e configuração de registro em Kotlin
Por que SLF4J + Logback?
Para Kotlin, recomenda-se usar a combinação SLF4J (fachada) + Logback (implementação). Este é o padrão de facto no mundo Java/Kotlin. SLF4J fornece uma interface unificada, e Logback oferece uma implementação flexível e de alto desempenho.
Adicionando dependências (Gradle)
Adicione as seguintes linhas ao seu build.gradle.kts:
dependencies { implementation("ch.qos.logback:logback-classic:1.4.14") implementation("org.slf4j:slf4j-api:2.0.9")}Criando o logger
Em Kotlin, é comum usar um companion object para criar o logger:
import org.slf4j.LoggerFactory
class UserService { companion object { private val logger = LoggerFactory.getLogger(UserService::class.java) }
fun createUser(name: String) { logger.info("Criando usuário: {}", name) // lógica de negócio }}Dica: Evite usar java.util.logging ou println(). O primeiro está obsoleto, o segundo não permite configurar a saída de forma flexível.
2. Níveis de registro corretos: quando usar cada um
Um dos erros mais comuns de iniciantes é usar apenas logger.info() para tudo. Isso transforma os logs em "ruído". Siga estas regras:
- ERROR — erros críticos que exigem intervenção imediata (ex.: perda de conexão com o banco de dados).
- WARN — situações potencialmente perigosas que não quebram a aplicação imediatamente (ex.: formato de dados inválido).
- INFO — eventos importantes de negócio: inicialização do servidor, criação de usuário, execução de pedido.
- DEBUG — informações detalhadas para o desenvolvedor, que ajudam a depurar o código (valores de variáveis, parâmetros de entrada).
- TRACE — informações muito detalhadas, geralmente para rastreamento da execução de métodos.
Exemplo de uso correto
class PaymentProcessor { companion object { private val log = LoggerFactory.getLogger(PaymentProcessor::class.java) }
fun processPayment(amount: Double, userId: String) { log.info("Início do processamento do pagamento: usuário={}, valor={}", userId, amount) try { // lógica de negócio if (amount <= 0) { log.warn("Tentativa de processar valor negativo para o usuário {}", userId) return } log.debug("Validação de pagamento bem-sucedida para o usuário {}", userId) } catch (e: Exception) { log.error("Erro ao processar pagamento para o usuário {}: {}", userId, e.message, e) } }}3. Formatação e estrutura dos logs
Use mensagens parametrizadas
Nunca concatene strings com +:
// RUIMlog.info("User " + n