Wrapper de logging para Go com uma API única sobre zap, slog, zerolog e logrus, com suporte opcional a:
- campos estruturados
- caller (
arquivo,função,linha) - correlação com OpenTelemetry via
context.Context - export de logs OTLP
go get github.com/thiagozs/go-logbridgeO logger expõe a mesma interface para todos os engines:
type Logger interface {
Debug(ctx context.Context, msg string, args ...any)
Info(ctx context.Context, msg string, args ...any)
Infof(ctx context.Context, format string, args ...any)
Warn(ctx context.Context, msg string, args ...any)
Warnf(ctx context.Context, format string, args ...any)
Error(ctx context.Context, msg string, args ...any)
Errorf(ctx context.Context, format string, args ...any)
With(args ...any) Logger
}Criação:
log, err := logbridge.New(
logbridge.WithEngine(logbridge.Zap),
logbridge.WithLevel(logbridge.Debug),
logbridge.WithJSON(),
)
if err != nil {
panic(err)
}logbridge.Slog
logbridge.Zap
logbridge.Zerolog
logbridge.Logruspackage main
import (
"context"
"github.com/thiagozs/go-logbridge/logbridge"
)
func main() {
log, err := logbridge.New(
logbridge.WithEngine(logbridge.Zap), // motor utilizado
logbridge.WithLevel(logbridge.Info), // define o nivel do log
logbridge.WithJSON(), // formato json
logbridge.WithCallerSkip(1), // ajusta o número de frames que serão ignorados
)
if err != nil {
panic(err)
}
log.Info(context.Background(), "application started",
"service", "payments",
"version", "1.0.0",
)
}logbridge.WithEngine(logbridge.Zap)
logbridge.WithLevel(logbridge.Debug)
logbridge.WithJSON()
logbridge.WithCaller()
logbridge.WithServiceName("payments-api")WithOTEL() não cria spans. Ela apenas instrui o logger a extrair trace_id e span_id do context.Context.
log, err := logbridge.New(
logbridge.WithEngine(logbridge.Zap),
logbridge.WithOTEL(),
)Se o ctx tiver um span válido, os logs serão enriquecidos com:
trace_idspan_id
Você pode enviar logs diretamente para um collector OTLP:
log, err := logbridge.New(
logbridge.WithEngine(logbridge.Zap),
logbridge.WithJSON(),
logbridge.WithServiceName("payments-api"),
logbridge.WithOTLPLogs("localhost:4317"),
)Quando usar OTLP, finalize com Shutdown para forçar flush:
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := logbridge.Shutdown(shutdownCtx, log); err != nil {
panic(err)
}Se sua aplicação já inicializa OpenTelemetry Logs fora do wrapper, você pode reaproveitar o provider:
log, err := logbridge.New(
logbridge.WithEngine(logbridge.Zap),
logbridge.WithGlobalOTLP(),
)Ou passar explicitamente:
log, err := logbridge.New(
logbridge.WithEngine(logbridge.Zap),
logbridge.WithOTLP(provider),
)With(...) cria um logger filho com campos persistentes:
base := log.With(
"service", "payments",
"env", "prod",
)
requestLog := base.With(
"request_id", "req-123",
"customer_id", "cus-789",
)
requestLog.Info(ctx, "payment received")Se a mesma chave aparecer mais de uma vez, o valor mais recente sobrescreve o anterior.
Quando um campo recebe um error, o wrapper normaliza a saída.
Exemplo:
log.Error(ctx, "payment failed",
"error", err,
)Saída esperada:
error: primeira linha da mensagemerror_type: tipo concreto do erroerror_stack: stack multiline normalizado em arrayerror_chain: cadeia de unwrap, quando existir
Isso evita despejar blocos com \n\t dentro do payload.
Com WithCaller(), o logger adiciona:
caller_filecaller_funccaller_line
Exemplo:
{
"msg": "payment failed",
"caller_file": "main.go",
"caller_func": "main.main",
"caller_line": "33"
}O wrapper:
- extrai
trace_idespan_iddocontext.Context - envia logs OTLP quando configurado
O wrapper não:
- cria spans automaticamente
- substitui o bootstrap de tracing da sua aplicação
Se você quiser ver traces no Tempo, precisa criar spans reais com um TracerProvider e usar o ctx retornado por tracer.Start(...).
Exemplos disponíveis no repositório:
examples/zapexamples/slogexamples/zerologexamples/logrusexamples/global_otlp
examples/global_otlp mostra um fluxo real com:
- logs OTLP
- traces reais via OTLP
- correlação entre Loki e Tempo
Rodar a suíte normal:
go test ./...Rodar os testes de integração OTLP:
go test -tags=integration ./logbridge -vUse go-logbridge quando você quiser:
- trocar de engine sem mudar a API do seu código
- manter logging estruturado consistente
- enriquecer logs com trace/span via
context - exportar logs para OTLP sem acoplar a aplicação a um engine específico
Este projeto é distribuido sobre a licença MIT. Veja o arquivo LICENSE para mais detalhes.
2026, Thiago Zilli Sarmento ❤️