diff --git a/internal/testutils/testutils.go b/internal/testutils/testutils.go index 20bc3c3..6e3a620 100644 --- a/internal/testutils/testutils.go +++ b/internal/testutils/testutils.go @@ -40,7 +40,7 @@ func LogAndAssertText(t *testing.T, log func(*Logger), assertions func(fields ma log(logger) fields := make(map[string]string) - for _, kv := range strings.Split(buffer.String(), " ") { + for _, kv := range strings.Split(strings.TrimRight(buffer.String(), "\n"), " ") { if !strings.Contains(kv, "=") { continue } diff --git a/logrus_test.go b/logrus_test.go index 47a386f..dfa053b 100644 --- a/logrus_test.go +++ b/logrus_test.go @@ -53,6 +53,17 @@ func TestReportCallerWhenConfigured(t *testing.T) { assert.Equal(t, "somekindoffunc", fields[FieldKeyFunc]) assert.Equal(t, "thisisafilename", fields[FieldKeyFile]) }) + + LogAndAssertText(t, func(log *Logger) { + log.ReportCaller = true + log.Formatter.(*TextFormatter).CallerPrettyfier = func(f *runtime.Frame) (string, string) { + return "somekindoffunc", "thisisafilename" + } + log.Print("testWithCallerPrettyfier") + }, func(fields map[string]string) { + assert.Equal(t, "somekindoffunc", fields[FieldKeyFunc]) + assert.Equal(t, "thisisafilename", fields[FieldKeyFile]) + }) } func logSomething(t *testing.T, message string) Fields { diff --git a/text_formatter.go b/text_formatter.go index 786bedf..b3b1a30 100644 --- a/text_formatter.go +++ b/text_formatter.go @@ -72,6 +72,12 @@ type TextFormatter struct { // FieldKeyMsg: "@message"}} FieldMap FieldMap + // CallerPrettyfier can be set by the user to modify the content + // of the function and file keys in the json data when ReportCaller is + // activated. If any of the returned value is the empty string the + // corresponding key will be removed from json fields. + CallerPrettyfier func(*runtime.Frame) (function string, file string) + terminalInitOnce sync.Once } @@ -113,6 +119,8 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { keys = append(keys, k) } + var funcVal, fileVal string + fixedKeys := make([]string, 0, 4+len(data)) if !f.DisableTimestamp { fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyTime)) @@ -127,6 +135,12 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { if entry.HasCaller() { fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyFunc), f.FieldMap.resolve(FieldKeyFile)) + if f.CallerPrettyfier != nil { + funcVal, fileVal = f.CallerPrettyfier(entry.Caller) + } else { + funcVal = entry.Caller.Function + fileVal = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + } } if !f.DisableSorting { @@ -161,6 +175,7 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { if f.isColored() { f.printColored(b, entry, keys, data, timestampFormat) } else { + for _, key := range fixedKeys { var value interface{} switch { @@ -173,9 +188,9 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { case key == f.FieldMap.resolve(FieldKeyLogrusError): value = entry.err case key == f.FieldMap.resolve(FieldKeyFunc) && entry.HasCaller(): - value = entry.Caller.Function + value = funcVal case key == f.FieldMap.resolve(FieldKeyFile) && entry.HasCaller(): - value = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + value = fileVal default: value = data[key] } @@ -212,8 +227,13 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin caller := "" if entry.HasCaller() { - caller = fmt.Sprintf("%s:%d %s()", - entry.Caller.File, entry.Caller.Line, entry.Caller.Function) + funcVal := fmt.Sprintf("%s()", entry.Caller.Function) + fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + + if f.CallerPrettyfier != nil { + funcVal, fileVal = f.CallerPrettyfier(entry.Caller) + } + caller = fileVal + " " + funcVal } if f.DisableTimestamp {