slog: interpret call depth consistently
Adopt the convention that a call depth of 1 means the caller of the
function with the calldepth arg.
Fix NewRecord, which documented this but didn't implement it correctly.
Change-Id: Ic62e0ed0d0408fdfed7233978021db2f82c888e7
Reviewed-on: https://go-review.googlesource.com/c/exp/+/459644
Run-TryBot: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/slog/logger.go b/slog/logger.go
index 3377001..08dc7ce 100644
--- a/slog/logger.go
+++ b/slog/logger.go
@@ -134,7 +134,7 @@
// into an Attr.
// - Otherwise, the argument is treated as a value with key "!BADKEY".
func (l *Logger) Log(level Level, msg string, args ...any) {
- l.LogDepth(0, level, msg, args...)
+ l.LogDepth(1, level, msg, args...)
}
func (l *Logger) logPC(err error, pc uintptr, level Level, msg string, args ...any) {
@@ -161,57 +161,57 @@
// LogAttrs is a more efficient version of [Logger.Log] that accepts only Attrs.
func (l *Logger) LogAttrs(level Level, msg string, attrs ...Attr) {
- l.LogAttrsDepth(0, level, msg, attrs...)
+ l.LogAttrsDepth(1, level, msg, attrs...)
}
// Debug logs at LevelDebug.
func (l *Logger) Debug(msg string, args ...any) {
- l.LogDepth(0, LevelDebug, msg, args...)
+ l.LogDepth(1, LevelDebug, msg, args...)
}
// Info logs at LevelInfo.
func (l *Logger) Info(msg string, args ...any) {
- l.LogDepth(0, LevelInfo, msg, args...)
+ l.LogDepth(1, LevelInfo, msg, args...)
}
// Warn logs at LevelWarn.
func (l *Logger) Warn(msg string, args ...any) {
- l.LogDepth(0, LevelWarn, msg, args...)
+ l.LogDepth(1, LevelWarn, msg, args...)
}
// Error logs at LevelError.
// If err is non-nil, Error appends Any(ErrorKey, err)
// to the list of attributes.
func (l *Logger) Error(msg string, err error, args ...any) {
- l.logDepthErr(err, 0, LevelError, msg, args...)
+ l.logDepthErr(err, 1, LevelError, msg, args...)
}
// Debug calls Logger.Debug on the default logger.
func Debug(msg string, args ...any) {
- Default().LogDepth(0, LevelDebug, msg, args...)
+ Default().LogDepth(1, LevelDebug, msg, args...)
}
// Info calls Logger.Info on the default logger.
func Info(msg string, args ...any) {
- Default().LogDepth(0, LevelInfo, msg, args...)
+ Default().LogDepth(1, LevelInfo, msg, args...)
}
// Warn calls Logger.Warn on the default logger.
func Warn(msg string, args ...any) {
- Default().LogDepth(0, LevelWarn, msg, args...)
+ Default().LogDepth(1, LevelWarn, msg, args...)
}
// Error calls Logger.Error on the default logger.
func Error(msg string, err error, args ...any) {
- Default().logDepthErr(err, 0, LevelError, msg, args...)
+ Default().logDepthErr(err, 1, LevelError, msg, args...)
}
// Log calls Logger.Log on the default logger.
func Log(level Level, msg string, args ...any) {
- Default().LogDepth(0, level, msg, args...)
+ Default().LogDepth(1, level, msg, args...)
}
// LogAttrs calls Logger.LogAttrs on the default logger.
func LogAttrs(level Level, msg string, attrs ...Attr) {
- Default().LogAttrsDepth(0, level, msg, attrs...)
+ Default().LogAttrsDepth(1, level, msg, attrs...)
}
diff --git a/slog/pc.go b/slog/pc.go
index a95fcdb..cf2d771 100644
--- a/slog/pc.go
+++ b/slog/pc.go
@@ -6,20 +6,22 @@
package slog
-import "runtime"
+import (
+ "runtime"
+)
// These functions compute the pc early and pass it down the call chain,
// which is faster than computing it later with a larger skip.
// LogDepth is like [Logger.Log], but accepts a call depth to adjust the
-// file and line number in the log record. 0 refers to the caller
-// of LogDepth; 1 refers to the caller's caller; and so on.
+// file and line number in the log record. 1 refers to the caller
+// of LogDepth; 2 refers to the caller's caller; and so on.
func (l *Logger) LogDepth(calldepth int, level Level, msg string, args ...any) {
if !l.Enabled(level) {
return
}
var pcs [1]uintptr
- runtime.Callers(calldepth+3, pcs[:])
+ runtime.Callers(calldepth+2, pcs[:])
l.logPC(nil, pcs[0], level, msg, args...)
}
@@ -30,7 +32,7 @@
return
}
var pcs [1]uintptr
- runtime.Callers(calldepth+3, pcs[:])
+ runtime.Callers(calldepth+2, pcs[:])
r := l.makeRecord(msg, level, pcs[0])
r.AddAttrs(attrs...)
_ = l.Handler().Handle(r)
@@ -38,13 +40,13 @@
// logDepthErr is a trivial wrapper around logDepth, just to make the call
// depths on all paths the same. This is important only for the defaultHandler,
-// which passes a fixed call depth to log.Output. When slog moves to the
-// standard library, we can replace that fixed call depth with logic based on
-// the Record's pc, and remove this function. See the comment on
-// TestConnections/wrap_default_handler.
+// which passes a fixed call depth to log.Output.
+// TODO: When slog moves to the standard library, replace the fixed call depth
+// with logic based on the Record's pc, and remove this function. See the
+// comment on TestConnections/wrap_default_handler.
func (l *Logger) logDepthErr(err error, calldepth int, level Level, msg string, args ...any) {
var pcs [1]uintptr
- runtime.Callers(calldepth+3, pcs[:])
+ runtime.Callers(calldepth+2, pcs[:])
l.logPC(err, pcs[0], level, msg, args...)
}
diff --git a/slog/record.go b/slog/record.go
index 5220bf7..081db1b 100644
--- a/slog/record.go
+++ b/slog/record.go
@@ -63,7 +63,7 @@
func NewRecord(t time.Time, level Level, msg string, calldepth int, ctx context.Context) Record {
var p uintptr
if calldepth > 0 {
- p = pc(calldepth + 1)
+ p = pc(calldepth + 2)
}
return Record{
Time: t,
diff --git a/slog/record_test.go b/slog/record_test.go
index e7c1652..0a608ce 100644
--- a/slog/record_test.go
+++ b/slog/record_test.go
@@ -35,7 +35,8 @@
}{
{0, "", false},
{-16, "", false},
- {1, "record.go", true},
+ {1, "record_test.go", true}, // 1: caller of NewRecord
+ {2, "testing.go", true},
} {
r := NewRecord(time.Time{}, 0, "", test.depth, nil)
gotFile, gotLine := r.SourceLine()
diff --git a/slog/text_handler_test.go b/slog/text_handler_test.go
index 47fe2b0..faece65 100644
--- a/slog/text_handler_test.go
+++ b/slog/text_handler_test.go
@@ -114,7 +114,7 @@
func TestTextHandlerSource(t *testing.T) {
var buf bytes.Buffer
h := HandlerOptions{AddSource: true}.NewTextHandler(&buf)
- r := NewRecord(testTime, LevelInfo, "m", 2, nil)
+ r := NewRecord(testTime, LevelInfo, "m", 1, nil)
if err := h.Handle(r); err != nil {
t.Fatal(err)
}