Introdução
Logging não é apenas registrar eventos em um arquivo. Para aplicações Go que operam em ambientes de produção de alta carga, os logs são a principal fonte de informações de diagnóstico. Sem logging de qualidade, a busca por erros se torna um jogo de adivinhação, e o monitoramento do sistema se torna impossível.
Go oferece ao desenvolvedor ferramentas flexíveis: desde o pacote nativo log até poderosas bibliotecas de terceiros. Neste artigo, vamos analisar as melhores práticas de logging em Go, aprender a estruturar registros, escolher níveis e evitar erros típicos. O material será útil tanto para iniciantes quanto para desenvolvedores experientes que desejam organizar sua abordagem ao logging.
Biblioteca padrão log: recursos básicos e limitações
O pacote log da biblioteca padrão do Go é a maneira mais simples de começar a fazer logging. Ele fornece um logger pronto que escreve em os.Stderr.
Exemplo simples de uso
package main
import (
"log"
)
func main() {
log.Println("Aplicação iniciada")
log.Printf("Usuário %s fez login no sistema", "admin")
log.Fatal("Erro crítico: banco de dados indisponível")
}
A saída será assim:
2023/10/27 14:35:12 Aplicação iniciada
2023/10/27 14:35:12 Usuário admin fez login no sistema
2023/10/27 14:35:12 Erro crítico: banco de dados indisponível
Limitações do logger padrão
- Ausência de níveis de logging — não há separação entre Info, Warn, Error. Todas as mensagens são escritas em um único fluxo.
- Estrutura pobre — o registro é uma string simples, difícil de ser parseada automaticamente.
- Falta de contexto — não é fácil adicionar um identificador de requisição ou de usuário.
- Problemas de performance — o logger padrão bloqueia a goroutine durante a escrita, o que pode se tornar um gargalo.
Para utilitários pequenos ou protótipos, o log é suficiente. Mas para aplicações em produção, vale a pena considerar alternativas.
Logging estruturado: por que é importante?
Logging estruturado é uma abordagem onde cada mensagem representa um conjunto de pares "chave-valor" (geralmente no formato JSON). Isso permite:
- Parsear logs automaticamente em sistemas de coleta (ELK, Splunk, Grafana Loki).
- Filtrar registros por qualquer atributo (nível, serviço, ID da requisição).
- Criar dashboards e alertas com base em campos numéricos.
Bibliotecas populares para logging estruturado
- logrus — uma das primeiras e mais populares bibliotecas. Oferece níveis, formatação (JSON, texto), hooks para enviar logs para sistemas externos. No entanto, tem alto consumo de memória.
- zerolog — biblioteca focada em performance (zero allocation). Ideal para microsserviços e sistemas de alta carga.
- zap — da Uber. Muito rápido, com dois modos: SugaredLogger (conveniente) e Logger (velocidade máxima).
- slog — pacote padrão adicionado no Go 1.21. Fornece logging estruturado "nativo".
Exemplo usando slog (Go 1.21+)
package main
import (
"log/slog"
"os"
)
func main() {
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
logger.Info("Servidor iniciado", "port", 8080, "env", "production")
logger.Error("Erro ao conectar ao BD", "db", "postgres", "timeout", 5)
}
Saída em JSON:
{"time":"2023-10-27T14:40:00.123Z","level":"INFO","msg":"Servidor iniciado","port":8080,"env":"production"}
{"time":"2023-10-27T14:40:01.456Z","level":"ERROR","msg":"Erro ao conectar ao BD","db":"postgres","t