From d648c2e42d303b501c07abea92d372bdf649c00d Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 11 Jan 2021 17:46:00 -0500 Subject: [PATCH] fix file-based filtering symbolization If file-filtered logging is enabled, V looks up its caller's source file path using runtime.Callers and runtime.FuncForPC. However, runtime.Callers returns return PCs, which aren't necessarily in the same source file as the call site. For example, if F calls V, and F's call to V is immediately followed by an inlined called to another function, say G, then symbolizing V's return PC will actually return G's file and line number, not F's. Fix this by subtracting 1 from the PC returned by runtime.Callers to back up from the return PC to the call PC. An arguably better fix would be to use runtime.CallersFrames, which abstracts away such details. Unfortunately, CallersFrames allocates (at least as of Go 1.15), so we avoid it here. --- klog.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/klog.go b/klog.go index 5b33973e5..60c88d3c3 100644 --- a/klog.go +++ b/klog.go @@ -1328,9 +1328,14 @@ func V(level Level) Verbose { if runtime.Callers(2, logging.pcs[:]) == 0 { return newVerbose(level, false) } - v, ok := logging.vmap[logging.pcs[0]] + // runtime.Callers returns "return PCs", but we want + // to look up the symbolic information for the call, + // so subtract 1 from the PC. runtime.CallersFrames + // would be cleaner, but allocates. + pc := logging.pcs[0] - 1 + v, ok := logging.vmap[pc] if !ok { - v = logging.setV(logging.pcs[0]) + v = logging.setV(pc) } return newVerbose(level, v >= level) }