OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / tendermint / tmlibs / log / tracing_logger.go
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 }