common/reporter: exclude callers from logs.go files (if possible)

This commit is contained in:
Vincent Bernat
2025-11-05 07:38:55 +01:00
parent f811a8e942
commit f7c8b31791
4 changed files with 57 additions and 7 deletions

View File

@@ -0,0 +1,12 @@
// SPDX-FileCopyrightText: 2025 Free Mobile
// SPDX-License-Identifier: AGPL-3.0-only
//go:build !release
package logger
// IntermediateLogger logs the provided message with the provided logger. This
// is used as part of testing.
func IntermediateLogger(l Logger, msg string) {
l.Info().Msg(msg)
}

View File

@@ -39,16 +39,25 @@ type contextHook struct{}
// Run adds more context to an event, including "module" and "caller". // Run adds more context to an event, including "module" and "caller".
func (h contextHook) Run(e *zerolog.Event, _ zerolog.Level, _ string) { func (h contextHook) Run(e *zerolog.Event, _ zerolog.Level, _ string) {
callStack := stack.Callers() callStack := stack.Callers()
callStack = callStack[3:] // Trial and error, there is a test to check it works callStack = callStack[3:] // Trial and error, there is a test to check it works.
caller := callStack[0].SourceFile(true)
e.Str("caller", caller) // We want to get the first caller that is in our module and isn't preferably in logs.go.
var candidateCall stack.Call
var candidateModule string
for _, call := range callStack { for _, call := range callStack {
module := call.FunctionName() module := call.FunctionName()
if !strings.HasPrefix(module, stack.ModuleName) { if !strings.HasPrefix(module, stack.ModuleName) {
continue continue
} }
module = strings.SplitN(module, ".", 2)[0] candidateCall = call
e.Str("module", module) candidateModule = strings.SplitN(module, ".", 2)[0]
if strings.HasSuffix(call.FileName(), "/logs.go") {
continue
}
break break
} }
if candidateCall != stack.Call(0) {
e.Str("caller", candidateCall.SourceFile(true))
e.Str("module", candidateModule)
}
} }

View File

@@ -21,11 +21,29 @@ func ExampleNew() {
} }
// Initialize logger // Initialize logger
logger, err := logger.New(logger.DefaultConfiguration()) l, err := logger.New(logger.DefaultConfiguration())
if err != nil { if err != nil {
panic(err) panic(err)
} }
logger.Info().Int("example", 15).Msg("hello world") l.Info().Int("example", 15).Msg("hello world")
// Output: {"level":"info","example":15,"time":"2008-01-08T17:05:05Z","caller":"akvorado/common/reporter/logger/root_example_test.go:29","module":"akvorado/common/reporter/logger_test","message":"hello world"} // Output: {"level":"info","example":15,"time":"2008-01-08T17:05:05Z","caller":"akvorado/common/reporter/logger/root_example_test.go:29","module":"akvorado/common/reporter/logger_test","message":"hello world"}
} }
func ExampleIntermediateLogger() {
// This is not really an example but a test to show we skip callers in
// logs.go files.
log.Logger = zerolog.New(os.Stdout).With().Timestamp().Logger()
zerolog.TimestampFunc = func() time.Time {
return time.Date(2008, 1, 8, 17, 5, 5, 0, time.UTC)
}
// Initialize logger
l, err := logger.New(logger.DefaultConfiguration())
if err != nil {
panic(err)
}
logger.IntermediateLogger(l, "bye bye!")
// Output: {"level":"info","time":"2008-01-08T17:05:05Z","caller":"akvorado/common/reporter/logger/root_example_test.go:47","module":"akvorado/common/reporter/logger_test","message":"bye bye!"}
}

View File

@@ -53,6 +53,17 @@ func (pc Call) FunctionName() string {
return name return name
} }
// FileName returns the file name of the call point.
func (pc Call) FileName() string {
pcFix := uintptr(pc) - 1
fn := runtime.FuncForPC(pcFix)
if fn == nil {
return "(nofile)"
}
file, _ := fn.FileLine(pcFix)
return file
}
// SourceFile returns the source file and optionally line number of // SourceFile returns the source file and optionally line number of
// the call point. The source file is relative to the import point // the call point. The source file is relative to the import point
// (and includes it). // (and includes it).