Codebase list golang-github-go-logr-logr / 56380ab
funcr: Add Options.LogCallerFunc This optional (default off) flag tells funcr to look up the calling function name and include that in the caller information. Tim Hockin 2 years ago
2 changed file(s) with 72 addition(s) and 19 deletion(s). Raw diff Collapse all Expand all
8484 // This has some overhead, so some users might not want it.
8585 LogCaller MessageClass
8686
87 // LogCallerFunc tells funcr to also log the calling function name. This
88 // has no effect if caller logging is not enabled (see Options.LogCaller).
89 LogCallerFunc bool
90
8791 // LogTimestamp tells funcr to add a "ts" key to log lines. This has some
8892 // overhead, so some users might not want it.
8993 LogTimestamp bool
163167
164168 func newFormatter(opts Options, outfmt outputFormat) Formatter {
165169 f := Formatter{
166 outputFormat: outfmt,
167 prefix: "",
168 values: nil,
169 depth: 0,
170 logCaller: opts.LogCaller,
171 logTimestamp: opts.LogTimestamp,
172 verbosity: opts.Verbosity,
170 outputFormat: outfmt,
171 prefix: "",
172 values: nil,
173 depth: 0,
174 logCaller: opts.LogCaller,
175 logCallerFunc: opts.LogCallerFunc,
176 logTimestamp: opts.LogTimestamp,
177 verbosity: opts.Verbosity,
173178 }
174179 return f
175180 }
178183 // implementation. It should be constructed with NewFormatter. Some of
179184 // its methods directly implement logr.LogSink.
180185 type Formatter struct {
181 outputFormat outputFormat
182 prefix string
183 values []interface{}
184 valuesStr string
185 depth int
186 logCaller MessageClass
187 logTimestamp bool
188 verbosity int
186 outputFormat outputFormat
187 prefix string
188 values []interface{}
189 valuesStr string
190 depth int
191 logCaller MessageClass
192 logCallerFunc bool
193 logTimestamp bool
194 verbosity int
189195 }
190196
191197 // outputFormat indicates which outputFormat to use.
473479 type callerID struct {
474480 File string `json:"file"`
475481 Line int `json:"line"`
482 Func string `json:"function,omitempty"`
476483 }
477484
478485 func (f Formatter) caller() callerID {
479486 // +1 for this frame, +1 for Info/Error.
480 _, file, line, ok := runtime.Caller(f.depth + 2)
487 pc, file, line, ok := runtime.Caller(f.depth + 2)
481488 if !ok {
482 return callerID{"<unknown>", 0}
483 }
484 return callerID{filepath.Base(file), line}
489 return callerID{"<unknown>", 0, ""}
490 }
491 fn := ""
492 if f.logCallerFunc {
493 if fp := runtime.FuncForPC(pc); fp != nil {
494 fn = fp.Name()
495 }
496 }
497
498 return callerID{filepath.Base(file), line, fn}
485499 }
486500
487501 // Init configures this Formatter from runtime info, such as the call depth
579579 if cap.log != expect {
580580 t.Errorf("\nexpected %q\n got %q", expect, cap.log)
581581 }
582 sink.Error(fmt.Errorf("error"), "msg")
583 _, file, line, _ = runtime.Caller(0)
584 expect = fmt.Sprintf(` "caller"={"file":%q,"line":%d} "msg"="msg" "error"="error"`, filepath.Base(file), line-1)
585 if cap.log != expect {
586 t.Errorf("\nexpected %q\n got %q", expect, cap.log)
587 }
588 })
589 t.Run("LogCaller=All, LogCallerFunc=true", func(t *testing.T) {
590 thisFunc := "github.com/go-logr/logr/funcr.TestInfoWithCaller.func2"
591 cap := &capture{}
592 sink := newSink(cap.Func, NewFormatter(Options{LogCaller: All, LogCallerFunc: true}))
593 sink.Info(0, "msg")
594 _, file, line, _ := runtime.Caller(0)
595 expect := fmt.Sprintf(` "caller"={"file":%q,"line":%d,"function":%q} "level"=0 "msg"="msg"`, filepath.Base(file), line-1, thisFunc)
596 if cap.log != expect {
597 t.Errorf("\nexpected %q\n got %q", expect, cap.log)
598 }
599 sink.Error(fmt.Errorf("error"), "msg")
600 _, file, line, _ = runtime.Caller(0)
601 expect = fmt.Sprintf(` "caller"={"file":%q,"line":%d,"function":%q} "msg"="msg" "error"="error"`, filepath.Base(file), line-1, thisFunc)
602 if cap.log != expect {
603 t.Errorf("\nexpected %q\n got %q", expect, cap.log)
604 }
582605 })
583606 t.Run("LogCaller=Info", func(t *testing.T) {
584607 cap := &capture{}
589612 if cap.log != expect {
590613 t.Errorf("\nexpected %q\n got %q", expect, cap.log)
591614 }
615 sink.Error(fmt.Errorf("error"), "msg")
616 expect = ` "msg"="msg" "error"="error"`
617 if cap.log != expect {
618 t.Errorf("\nexpected %q\n got %q", expect, cap.log)
619 }
592620 })
593621 t.Run("LogCaller=Error", func(t *testing.T) {
594622 cap := &capture{}
598626 if cap.log != expect {
599627 t.Errorf("\nexpected %q\n got %q", expect, cap.log)
600628 }
629 sink.Error(fmt.Errorf("error"), "msg")
630 _, file, line, _ := runtime.Caller(0)
631 expect = fmt.Sprintf(` "caller"={"file":%q,"line":%d} "msg"="msg" "error"="error"`, filepath.Base(file), line-1)
632 if cap.log != expect {
633 t.Errorf("\nexpected %q\n got %q", expect, cap.log)
634 }
601635 })
602636 t.Run("LogCaller=None", func(t *testing.T) {
603637 cap := &capture{}
604638 sink := newSink(cap.Func, NewFormatter(Options{LogCaller: None}))
605639 sink.Info(0, "msg")
606640 expect := ` "level"=0 "msg"="msg"`
641 if cap.log != expect {
642 t.Errorf("\nexpected %q\n got %q", expect, cap.log)
643 }
644 sink.Error(fmt.Errorf("error"), "msg")
645 expect = ` "msg"="msg" "error"="error"`
607646 if cap.log != expect {
608647 t.Errorf("\nexpected %q\n got %q", expect, cap.log)
609648 }