Reputation: 59403
When using the log.Lshortfile
flag, the logger prefixes all log lines with the file name and line number of the logger function call, for example:
myfile.go:14: Hello, world!
If I wrap the log function like this, for instance:
func info(pattern string, args ...interface{}) {
myLogger.Printf(pattern + "\n", args...)
}
Every line emitted by this function is going to be prefixed with the line number of the Printf
call. That is as expected, but the desired behavior is for each line to be prefixed with the line number of the line where info
is called.
Is there any way around it?
Upvotes: 14
Views: 5823
Reputation: 418417
Methods of log.Logger
call the Logger.Output()
method to send the message to the appropriate output. Logger.Output()
allows you to pass the calldepth
(the number of frames to skip).
Unfortunately methods of log.Logger
contain the calldepth
"wired in", so you can't provide an offset to skip the wrapper function's frame.
But a much better alternative is to call this Logger.Output()
from your wrapper, so you don't have to bother with frames and lines yourself. Also note that you don't need to append a newline "\n"
, as the log.Logger
type already does that if the message to be logged does not end with a newline.
So a better and shorter alternative:
var myLogger = log.New(os.Stdout, "[my]", log.Lshortfile)
func info(pattern string, args ...interface{}) {
myLogger.Output(2, fmt.Sprintf(pattern, args...))
}
Testing it:
func main() {
log.SetFlags(log.Lshortfile)
log.Println("hello")
info("world")
}
Output (try it on the Go Playground):
main.go:11: hello
[my]main.go:12: world
As you can see, info()
prints the proper line number (+1 compared to the line number printed by log.Println()
in the previous line).
Upvotes: 19
Reputation: 59403
I was going to include this in the question as my current workaround, but I suppose it is a valid answer. I'm hoping somebody can tell me of a logger config option I've missed that lets me adjust the depth the logger uses when it calls runtime.Caller
.
A workaround is to remove the log.Lshortfile
flag and implement the behavior manually:
func info(format string, args ...interface{}) {
_, file, line, _ := runtime.Caller(1)
prefix := fmt.Sprintf("%v:%v: ", path.Base(file), line)
if logger != nil {
logger.Printf(prefix+format+"\n", args...)
}
}
Upvotes: 0