Files
Maxence MaireauxandGitHub edca639475 fix: roll up remaining backlog fixes (EN-1180-EN-1196) (#655)
* fix: roll up remaining backlog fixes (EN-1180-EN-1196)

* fix: preserve nil json marshal behavior

* docs: clarify implicit http status capture

* fix: align httpserver timeout and tracing paths

* fix: preserve debug request body read errors
2026-06-22 12:43:54 +00:00

188 lines
4.0 KiB
Go

package logging
import (
"context"
"io"
"os"
"github.com/sirupsen/logrus"
"github.com/uptrace/opentelemetry-go-extra/otellogrus"
)
type LogrusLogger struct {
entry interface {
Tracef(format string, args ...any)
Trace(args ...any)
Debugf(format string, args ...any)
Debug(args ...any)
Infof(format string, args ...any)
Info(args ...any)
Warnf(format string, args ...any)
Warn(args ...any)
Errorf(format string, args ...any)
Error(args ...any)
WithFields(fields logrus.Fields) *logrus.Entry
WithField(key string, value any) *logrus.Entry
WithContext(ctx context.Context) *logrus.Entry
Writer() *io.PipeWriter
}
logger *logrus.Logger
}
func (l *LogrusLogger) Writer() io.Writer {
return l.entry.Writer()
}
func (l *LogrusLogger) WithContext(ctx context.Context) Logger {
return &LogrusLogger{
entry: l.entry.WithContext(ctx),
logger: l.logger,
}
}
func (l *LogrusLogger) Trace(args ...any) {
l.entry.Trace(args...)
}
func (l *LogrusLogger) Tracef(fmt string, args ...any) {
l.entry.Tracef(fmt, args...)
}
func (l *LogrusLogger) Debug(args ...any) {
l.entry.Debug(args...)
}
func (l *LogrusLogger) Debugf(fmt string, args ...any) {
l.entry.Debugf(fmt, args...)
}
func (l *LogrusLogger) Infof(fmt string, args ...any) {
l.entry.Infof(fmt, args...)
}
func (l *LogrusLogger) Info(args ...any) {
l.entry.Info(args...)
}
func (l *LogrusLogger) Warnf(fmt string, args ...any) {
l.entry.Warnf(fmt, args...)
}
func (l *LogrusLogger) Warn(args ...any) {
l.entry.Warn(args...)
}
func (l *LogrusLogger) Errorf(fmt string, args ...any) {
l.entry.Errorf(fmt, args...)
}
func (l *LogrusLogger) Error(args ...any) {
l.entry.Error(args...)
}
func (l *LogrusLogger) WithFields(fields map[string]any) Logger {
return &LogrusLogger{
entry: l.entry.WithFields(fields),
logger: l.logger,
}
}
func (l *LogrusLogger) WithField(key string, value any) Logger {
return l.WithFields(map[string]any{
key: value,
})
}
func toLogrusLevel(level Level) logrus.Level {
switch level {
case TraceLevel:
return logrus.TraceLevel
case DebugLevel:
return logrus.DebugLevel
case InfoLevel:
return logrus.InfoLevel
case ErrorLevel:
return logrus.ErrorLevel
default:
return logrus.DebugLevel
}
}
func (l *LogrusLogger) Enabled(level Level) bool {
return l.logger.IsLevelEnabled(toLogrusLevel(level))
}
var _ Logger = &LogrusLogger{}
func NewLogrus(logger *logrus.Logger) *LogrusLogger {
return &LogrusLogger{
entry: logger,
logger: logger,
}
}
func Testing() *LogrusLogger {
logger := logrus.New()
logger.SetOutput(io.Discard)
if os.Getenv("DEBUG") == "true" {
logger.SetOutput(os.Stderr)
logger.SetLevel(logrus.DebugLevel)
}
textFormatter := new(logrus.TextFormatter)
textFormatter.TimestampFormat = "15-01-2018 15:04:05.000000"
textFormatter.FullTimestamp = true
logger.SetFormatter(textFormatter)
return NewLogrus(logger)
}
func NewDefaultLogger(
w io.Writer,
debug,
formatJSON bool,
otelTraces bool,
) *LogrusLogger {
level := InfoLevel
if debug {
level = DebugLevel
}
return NewDefaultLoggerWithLevel(w, level, formatJSON, otelTraces)
}
// NewDefaultLoggerWithLevel builds a LogrusLogger configured at the given level.
// Prefer this constructor over NewDefaultLogger when callers need Trace verbosity.
func NewDefaultLoggerWithLevel(
w io.Writer,
level Level,
formatJSON bool,
otelTraces bool,
) *LogrusLogger {
l := logrus.New()
l.SetOutput(w)
l.Level = toLogrusLevel(level)
var formatter logrus.Formatter
if formatJSON {
jsonFormatter := &logrus.JSONFormatter{}
formatter = jsonFormatter
} else {
textFormatter := new(logrus.TextFormatter)
textFormatter.FullTimestamp = true
formatter = textFormatter
}
l.SetFormatter(formatter)
SetHooks(l, otelTraces)
return NewLogrus(l)
}
func SetHooks(l *logrus.Logger, otelTraces bool) {
if !otelTraces {
return
}
hooks := make([]logrus.Hook, 0)
hooks = append(hooks, otellogrus.NewHook(otellogrus.WithLevels(
logrus.PanicLevel,
logrus.FatalLevel,
logrus.ErrorLevel,
logrus.WarnLevel,
)), NewTraceHook())
for _, hook := range hooks {
l.AddHook(hook)
}
}