github.com/arcology-network/consensus-engine@v1.9.0/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  }