feat(logger): add WithOffset to decrease info/debug/trace verbosity

Signed-off-by: Adphi <philippe.adrien.nousse@gmail.com>
This commit is contained in:
2025-12-05 16:18:35 +01:00
parent 33a54500b4
commit 8e50da9205
6 changed files with 142 additions and 106 deletions

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@
.bin
/tmp
diff
.DS_Store

View File

@@ -32,7 +32,6 @@ require (
require (
cloud.google.com/go/compute/metadata v0.6.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bombsimon/logrusr/v4 v4.1.0 // indirect
github.com/bufbuild/protocompile v0.14.1 // indirect
@@ -88,6 +87,7 @@ require (
golang.org/x/sync v0.14.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.25.0 // indirect
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect
nhooyr.io/websocket v1.8.17 // indirect
)

View File

@@ -35,8 +35,6 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -621,6 +619,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb h1:whnFRlWMcXI9d+ZbWg+4sHnLp52d5yiIPUxMBSt4X9A=
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb/go.mod h1:rpwXGsirqLqN2L0JDJQlwOboGHmptD5ZD6T2VmcqhTw=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=

1
go.mod
View File

@@ -5,7 +5,6 @@ go 1.23.1
toolchain go1.24.3
require (
github.com/Microsoft/go-winio v0.6.2
github.com/alta/protopatch v0.5.3
github.com/bombsimon/logrusr/v4 v4.0.0
github.com/caitlinelfring/go-env-default v1.1.0

2
go.sum
View File

@@ -53,8 +53,6 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=

View File

@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
"os"
"path/filepath"
"runtime"
"strings"
@@ -46,7 +47,7 @@ func New() Logger {
return &logger{fl: logrus.New()}
}
func FromLogrus(fl logrus.Ext1FieldLogger) Logger {
func FromLogrus(fl LogrusLogger) Logger {
return &logger{fl: fl}
}
@@ -56,9 +57,10 @@ type Logger interface {
WithContext(ctx context.Context) Logger
WithReportCaller(b bool, depth ...uint) Logger
WithOffset(n int) Logger
WithField(key string, value interface{}) Logger
WithFields(kv ...interface{}) Logger
WithField(key string, value any) Logger
WithFields(kv ...any) Logger
WithError(err error) Logger
SetLevel(level Level) Logger
@@ -66,35 +68,35 @@ type Logger interface {
SetOutput(w io.Writer) Logger
Tracef(format string, args ...interface{})
Debugf(format string, args ...interface{})
Infof(format string, args ...interface{})
Printf(format string, args ...interface{})
Warnf(format string, args ...interface{})
Warningf(format string, args ...interface{})
Errorf(format string, args ...interface{})
Fatalf(format string, args ...interface{})
Panicf(format string, args ...interface{})
Tracef(format string, args ...any)
Debugf(format string, args ...any)
Infof(format string, args ...any)
Printf(format string, args ...any)
Warnf(format string, args ...any)
Warningf(format string, args ...any)
Errorf(format string, args ...any)
Fatalf(format string, args ...any)
Panicf(format string, args ...any)
Trace(args ...interface{})
Debug(args ...interface{})
Info(args ...interface{})
Print(args ...interface{})
Warn(args ...interface{})
Warning(args ...interface{})
Error(args ...interface{})
Fatal(args ...interface{})
Panic(args ...interface{})
Trace(args ...any)
Debug(args ...any)
Info(args ...any)
Print(args ...any)
Warn(args ...any)
Warning(args ...any)
Error(args ...any)
Fatal(args ...any)
Panic(args ...any)
Traceln(args ...interface{})
Debugln(args ...interface{})
Infoln(args ...interface{})
Println(args ...interface{})
Warnln(args ...interface{})
Warningln(args ...interface{})
Errorln(args ...interface{})
Fatalln(args ...interface{})
Panicln(args ...interface{})
Traceln(args ...any)
Debugln(args ...any)
Infoln(args ...any)
Println(args ...any)
Warnln(args ...any)
Warningln(args ...any)
Errorln(args ...any)
Fatalln(args ...any)
Panicln(args ...any)
Logr() logr.Logger
FieldLogger() logrus.FieldLogger
@@ -104,116 +106,120 @@ type Logger interface {
}
type logger struct {
fl logrus.Ext1FieldLogger
fl LogrusLogger
reportCaller *int
offset int
}
func (l *logger) Tracef(format string, args ...interface{}) {
l.withCaller().Tracef(format, args...)
func (l *logger) Tracef(format string, args ...any) {
l.logf(TraceLevel, format, args...)
}
func (l *logger) Debugf(format string, args ...interface{}) {
l.withCaller().Debugf(format, args...)
func (l *logger) Debugf(format string, args ...any) {
l.logf(DebugLevel, format, args...)
}
func (l *logger) Infof(format string, args ...interface{}) {
l.withCaller().Infof(format, args...)
func (l *logger) Infof(format string, args ...any) {
l.logf(InfoLevel, format, args...)
}
func (l *logger) Printf(format string, args ...interface{}) {
l.withCaller().Printf(format, args...)
func (l *logger) Printf(format string, args ...any) {
l.logf(InfoLevel, format, args...)
}
func (l *logger) Warnf(format string, args ...interface{}) {
l.withCaller().Warnf(format, args...)
func (l *logger) Warnf(format string, args ...any) {
l.logf(WarnLevel, format, args...)
}
func (l *logger) Warningf(format string, args ...interface{}) {
l.withCaller().Warningf(format, args...)
func (l *logger) Warningf(format string, args ...any) {
l.logf(WarnLevel, format, args...)
}
func (l *logger) Errorf(format string, args ...interface{}) {
l.withCaller().Errorf(format, args...)
func (l *logger) Errorf(format string, args ...any) {
l.logf(ErrorLevel, format, args...)
}
func (l *logger) Fatalf(format string, args ...interface{}) {
l.withCaller().Fatalf(format, args...)
func (l *logger) Fatalf(format string, args ...any) {
l.logf(FatalLevel, format, args...)
os.Exit(1)
}
func (l *logger) Panicf(format string, args ...interface{}) {
l.withCaller().Panicf(format, args...)
func (l *logger) Panicf(format string, args ...any) {
l.logf(PanicLevel, format, args...)
}
func (l *logger) Trace(args ...interface{}) {
l.withCaller().Trace(args...)
func (l *logger) Trace(args ...any) {
l.log(TraceLevel, args...)
}
func (l *logger) Debug(args ...interface{}) {
l.withCaller().Debug(args...)
func (l *logger) Debug(args ...any) {
l.log(DebugLevel, args...)
}
func (l *logger) Info(args ...interface{}) {
l.withCaller().Info(args...)
func (l *logger) Info(args ...any) {
l.log(InfoLevel, args...)
}
func (l *logger) Print(args ...interface{}) {
l.withCaller().Print(args...)
func (l *logger) Print(args ...any) {
l.log(InfoLevel, args...)
}
func (l *logger) Warn(args ...interface{}) {
l.withCaller().Warn(args...)
func (l *logger) Warn(args ...any) {
l.log(WarnLevel, args...)
}
func (l *logger) Warning(args ...interface{}) {
l.withCaller().Warning(args...)
func (l *logger) Warning(args ...any) {
l.log(WarnLevel, args...)
}
func (l *logger) Error(args ...interface{}) {
l.withCaller().Error(args...)
func (l *logger) Error(args ...any) {
l.log(ErrorLevel, args...)
}
func (l *logger) Fatal(args ...interface{}) {
l.withCaller().Fatal(args...)
func (l *logger) Fatal(args ...any) {
l.log(FatalLevel, args...)
os.Exit(1)
}
func (l *logger) Panic(args ...interface{}) {
l.withCaller().Panic(args...)
func (l *logger) Panic(args ...any) {
l.log(PanicLevel, args...)
}
func (l *logger) Traceln(args ...interface{}) {
l.withCaller().Traceln(args...)
func (l *logger) Traceln(args ...any) {
l.logln(TraceLevel, args...)
}
func (l *logger) Debugln(args ...interface{}) {
l.withCaller().Debugln(args...)
func (l *logger) Debugln(args ...any) {
l.logln(DebugLevel, args...)
}
func (l *logger) Infoln(args ...interface{}) {
l.withCaller().Infoln(args...)
func (l *logger) Infoln(args ...any) {
l.logln(InfoLevel, args...)
}
func (l *logger) Println(args ...interface{}) {
l.withCaller().Println(args...)
func (l *logger) Println(args ...any) {
l.logln(InfoLevel, args...)
}
func (l *logger) Warnln(args ...interface{}) {
l.withCaller().Warnln(args...)
func (l *logger) Warnln(args ...any) {
l.logln(WarnLevel, args...)
}
func (l *logger) Warningln(args ...interface{}) {
l.withCaller().Warningln(args...)
func (l *logger) Warningln(args ...any) {
l.logln(WarnLevel, args...)
}
func (l *logger) Errorln(args ...interface{}) {
l.withCaller().Errorln(args...)
func (l *logger) Errorln(args ...any) {
l.logln(ErrorLevel, args...)
}
func (l *logger) Fatalln(args ...interface{}) {
l.withCaller().Fatalln(args...)
func (l *logger) Fatalln(args ...any) {
l.logln(FatalLevel, args...)
os.Exit(1)
}
func (l *logger) Panicln(args ...interface{}) {
l.withCaller().Panicln(args...)
func (l *logger) Panicln(args ...any) {
l.logln(PanicLevel, args...)
}
func (l *logger) WriterLevel(level Level) *io.PipeWriter {
@@ -228,32 +234,32 @@ func (l *logger) SetLevel(level Level) Logger {
func (l *logger) WithContext(ctx context.Context) Logger {
switch t := l.fl.(type) {
case *logrus.Logger:
return &logger{fl: t.WithContext(ctx), reportCaller: l.reportCaller}
return &logger{fl: t.WithContext(ctx), reportCaller: l.reportCaller, offset: l.offset}
case *logrus.Entry:
return &logger{fl: t.WithContext(ctx), reportCaller: l.reportCaller}
return &logger{fl: t.WithContext(ctx), reportCaller: l.reportCaller, offset: l.offset}
}
panic(fmt.Sprintf("unexpected logger type %T", l.fl))
}
func (l *logger) WithField(key string, value interface{}) Logger {
return &logger{fl: l.fl.WithField(key, value), reportCaller: l.reportCaller}
func (l *logger) WithField(key string, value any) Logger {
return &logger{fl: l.fl.WithField(key, value), reportCaller: l.reportCaller, offset: l.offset}
}
func (l *logger) WithFields(kv ...interface{}) Logger {
log := &logger{fl: l.fl}
func (l *logger) WithFields(kv ...any) Logger {
log := &logger{fl: l.fl, reportCaller: l.reportCaller, offset: l.offset}
for i := 0; i < len(kv); i += 2 {
log = &logger{fl: log.fl.WithField(fmt.Sprintf("%v", kv[i]), kv[i+1]), reportCaller: l.reportCaller}
log = &logger{fl: log.fl.WithField(fmt.Sprintf("%v", kv[i]), kv[i+1]), reportCaller: l.reportCaller, offset: l.offset}
}
return log
}
func (l *logger) WithError(err error) Logger {
return &logger{fl: l.fl.WithError(err), reportCaller: l.reportCaller}
return &logger{fl: l.fl.WithError(err), reportCaller: l.reportCaller, offset: l.offset}
}
func (l *logger) WithReportCaller(b bool, depth ...uint) Logger {
if !b {
return &logger{fl: l.fl}
return &logger{fl: l.fl, reportCaller: nil, offset: l.offset}
}
var d int
if len(depth) > 0 {
@@ -261,11 +267,15 @@ func (l *logger) WithReportCaller(b bool, depth ...uint) Logger {
} else {
d = 0
}
return &logger{fl: l.fl, reportCaller: &d}
return &logger{fl: l.fl, reportCaller: &d, offset: l.offset}
}
func (l *logger) WithOffset(n int) Logger {
return &logger{fl: l.fl, reportCaller: l.reportCaller, offset: n}
}
func (l *logger) Logr() logr.Logger {
return logrusr.New(l.fl, logrusr.WithFormatter(func(i interface{}) interface{} {
return logrusr.New(l.fl, logrusr.WithFormatter(func(i any) any {
return fmt.Sprintf("%v", i)
}))
}
@@ -297,7 +307,7 @@ func (l *logger) Clone() Logger {
n.Out = t.Out
n.Formatter = t.Formatter
n.Hooks = t.Hooks
return &logger{fl: n, reportCaller: l.reportCaller}
return &logger{fl: n, reportCaller: l.reportCaller, offset: l.offset}
case *logrus.Entry:
t = t.Dup()
n.Level = t.Logger.Level
@@ -305,22 +315,41 @@ func (l *logger) Clone() Logger {
n.Formatter = t.Logger.Formatter
n.Hooks = t.Logger.Hooks
t.Logger = n
return &logger{fl: t, reportCaller: l.reportCaller}
return &logger{fl: t, reportCaller: l.reportCaller, offset: l.offset}
}
panic(fmt.Sprintf("unexpected logger type %T", l.fl))
}
func (l *logger) withCaller() logrus.Ext1FieldLogger {
func (l *logger) logf(level logrus.Level, format string, args ...any) {
l.withCaller().Logf(l.level(level), format, args...)
}
func (l *logger) log(level logrus.Level, args ...any) {
l.withCaller().Log(l.level(level), args...)
}
func (l *logger) logln(level logrus.Level, args ...any) {
l.withCaller().Logln(l.level(level), args...)
}
func (l *logger) withCaller() LogrusLogger {
if l.reportCaller == nil {
return l.fl
}
pcs := make([]uintptr, 1)
runtime.Callers(3+*l.reportCaller, pcs)
runtime.Callers(4+*l.reportCaller, pcs)
f, _ := runtime.CallersFrames(pcs).Next()
pkg := getPackageName(f.Function)
return l.fl.WithField("caller", fmt.Sprintf("%s/%s:%d", pkg, filepath.Base(f.File), f.Line)).WithField("func", f.Func.Name())
}
func (l *logger) level(lvl Level) logrus.Level {
if lvl > 3 {
return lvl + logrus.Level(l.offset)
}
return lvl
}
// getPackageName reduces a fully qualified function name to the package name
// There really ought to be a better way...
func getPackageName(f string) string {
@@ -336,3 +365,12 @@ func getPackageName(f string) string {
return f
}
type LogrusLogger interface {
logrus.FieldLogger
logrus.Ext1FieldLogger
Log(level logrus.Level, args ...any)
Logf(level logrus.Level, format string, args ...any)
Logln(level logrus.Level, args ...any)
}