github.com/MagHErmit/tendermint@v0.282.1/libs/log/tracing_logger.go (about) 1 package log 2 3 import ( 4 "fmt" 5 6 "github.com/pkg/errors" 7 ) 8 9 // NewTracingLogger enables tracing by wrapping all errors (if they 10 // implement stackTracer interface) in tracedError. 11 // 12 // All errors returned by https://github.com/pkg/errors implement stackTracer 13 // interface. 14 // 15 // For debugging purposes only as it doubles the amount of allocations. 16 func NewTracingLogger(next Logger) Logger { 17 return &tracingLogger{ 18 next: next, 19 } 20 } 21 22 type stackTracer interface { 23 error 24 StackTrace() errors.StackTrace 25 } 26 27 type tracingLogger struct { 28 next Logger 29 } 30 31 func (l *tracingLogger) Info(msg string, keyvals ...interface{}) { 32 l.next.Info(msg, formatErrors(keyvals)...) 33 } 34 35 func (l *tracingLogger) Debug(msg string, keyvals ...interface{}) { 36 l.next.Debug(msg, formatErrors(keyvals)...) 37 } 38 39 func (l *tracingLogger) Error(msg string, keyvals ...interface{}) { 40 l.next.Error(msg, formatErrors(keyvals)...) 41 } 42 43 func (l *tracingLogger) With(keyvals ...interface{}) Logger { 44 return &tracingLogger{next: l.next.With(formatErrors(keyvals)...)} 45 } 46 47 func formatErrors(keyvals []interface{}) []interface{} { 48 newKeyvals := make([]interface{}, len(keyvals)) 49 copy(newKeyvals, keyvals) 50 for i := 0; i < len(newKeyvals)-1; i += 2 { 51 if err, ok := newKeyvals[i+1].(stackTracer); ok { 52 newKeyvals[i+1] = tracedError{err} 53 } 54 } 55 return newKeyvals 56 } 57 58 // tracedError wraps a stackTracer and just makes the Error() result 59 // always return a full stack trace. 60 type tracedError struct { 61 wrapped stackTracer 62 } 63 64 var _ stackTracer = tracedError{} 65 66 func (t tracedError) StackTrace() errors.StackTrace { 67 return t.wrapped.StackTrace() 68 } 69 70 func (t tracedError) Cause() error { 71 return t.wrapped 72 } 73 74 func (t tracedError) Error() string { 75 return fmt.Sprintf("%+v", t.wrapped) 76 }