From ee9ecbdca4d80e0daaec7146e8aca4c079d32775 Mon Sep 17 00:00:00 2001 From: Paddy Carver Date: Mon, 10 May 2021 13:15:57 -0700 Subject: [PATCH] Add an AdditionalLocationOffset option to LoggerOptions. Add the ability for wrappers of hclog to have the file and line number point to their caller, instead of the wrappers, by specifying additional offsets for the callstack when creating a logger. --- intlogger.go | 2 +- logger.go | 4 ++++ logger_test.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ stdlog_test.go | 29 +++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/intlogger.go b/intlogger.go index f8f6ebd..6099e67 100644 --- a/intlogger.go +++ b/intlogger.go @@ -124,7 +124,7 @@ func newLogger(opts *LoggerOptions) *intLogger { independentLevels: opts.IndependentLevels, } if opts.IncludeLocation { - l.callerOffset = offsetIntLogger + l.callerOffset = offsetIntLogger + opts.AdditionalLocationOffset } if l.json { diff --git a/logger.go b/logger.go index 83eafc1..7f36b1f 100644 --- a/logger.go +++ b/logger.go @@ -235,6 +235,10 @@ type LoggerOptions struct { // Include file and line information in each log line IncludeLocation bool + // AdditionalLocationOffset is the number of additional stack levels to skip + // when finding the file and line information for the log line + AdditionalLocationOffset int + // The time format to use instead of the default TimeFormat string diff --git a/logger_test.go b/logger_test.go index b1ef347..6e4bd58 100644 --- a/logger_test.go +++ b/logger_test.go @@ -176,6 +176,30 @@ func TestLogger(t *testing.T) { assert.Equal(t, "[INFO] go-hclog/logger_test.go:169: test: this is test: who=programmer why=\"testing is fun\"\n", rest) }) + t.Run("includes the caller location excluding helper functions", func(t *testing.T) { + var buf bytes.Buffer + + logMe := func(l Logger) { + l.Info("this is test", "who", "programmer", "why", "testing is fun") + } + + logger := New(&LoggerOptions{ + Name: "test", + Output: &buf, + IncludeLocation: true, + AdditionalLocationOffset: 1, + }) + + logMe(logger) + + str := buf.String() + dataIdx := strings.IndexByte(str, ' ') + rest := str[dataIdx+1:] + + // This test will break if you move this around, it's line dependent, just fyi + assert.Equal(t, "[INFO] go-hclog/logger_test.go:193: test: this is test: who=programmer why=\"testing is fun\"\n", rest) + }) + t.Run("prefixes the name", func(t *testing.T) { var buf bytes.Buffer @@ -805,6 +829,36 @@ func TestLogger_JSON(t *testing.T) { assert.Equal(t, fmt.Sprintf("%v:%d", file, line-1), raw["@caller"]) }) + t.Run("includes the caller location excluding helper functions", func(t *testing.T) { + var buf bytes.Buffer + + logMe := func(l Logger) { + l.Info("this is test", "who", "programmer", "why", "testing is fun") + } + + logger := New(&LoggerOptions{ + Name: "test", + Output: &buf, + JSONFormat: true, + IncludeLocation: true, + AdditionalLocationOffset: 1, + }) + + logMe(logger) + _, file, line, ok := runtime.Caller(0) + require.True(t, ok) + + b := buf.Bytes() + + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + t.Fatal(err) + } + + assert.Equal(t, "this is test", raw["@message"]) + assert.Equal(t, fmt.Sprintf("%v:%d", file, line-1), raw["@caller"]) + }) + t.Run("handles non-serializable entries", func(t *testing.T) { var buf bytes.Buffer diff --git a/stdlog_test.go b/stdlog_test.go index 446fa56..de7c3bf 100644 --- a/stdlog_test.go +++ b/stdlog_test.go @@ -181,3 +181,32 @@ func TestFromStandardLogger(t *testing.T) { prefix := "test-stdlib-log " require.Equal(t, prefix, actual[:16]) } + +func TestFromStandardLogger_helper(t *testing.T) { + var buf bytes.Buffer + + sl := log.New(&buf, "test-stdlib-log ", log.Ltime) + + hl := FromStandardLogger(sl, &LoggerOptions{ + Name: "hclog-inner", + IncludeLocation: true, + AdditionalLocationOffset: 1, + }) + + helper := func() { + hl.Info("this is a test", "name", "tester", "count", 1) + } + + helper() + _, file, line, ok := runtime.Caller(0) + require.True(t, ok) + + actual := buf.String() + suffix := fmt.Sprintf( + "[INFO] go-hclog/%s:%d: hclog-inner: this is a test: name=tester count=1\n", + filepath.Base(file), line-1) + require.Equal(t, suffix, actual[25:]) + + prefix := "test-stdlib-log " + require.Equal(t, prefix, actual[:16]) +}