hermez-node/log/log.go
log/log.goRaw
1package log
2
3import (
4 "fmt"
5 "strings"
6 "time"
7
8 "github.com/hermeznetwork/tracerr"
9 "go.uber.org/zap"
10 "go.uber.org/zap/zapcore"
11)
12
13var log *zap.SugaredLogger
14
15func init() {
16 // default level: debug
17 Init("debug", []string{"stdout"})
18}
19
20// Init the logger with defined level. outputs defines the outputs where the
21// logs will be sent. By default outputs contains "stdout", which prints the
22// logs at the output of the process. To add a log file as output, the path
23// should be added at the outputs array. To avoid printing the logs but storing
24// them on a file, can use []string{"pathtofile.log"}
25func Init(levelStr string, outputs []string) {
26 var level zap.AtomicLevel
27 err := level.UnmarshalText([]byte(levelStr))
28 if err != nil {
29 panic(fmt.Errorf("Error on setting log level: %s", err))
30 }
31
32 cfg := zap.Config{
33 Level: level,
34 Encoding: "console",
35 OutputPaths: outputs,
36 ErrorOutputPaths: []string{"stderr"},
37 EncoderConfig: zapcore.EncoderConfig{
38 MessageKey: "message",
39
40 LevelKey: "level",
41 EncodeLevel: zapcore.CapitalColorLevelEncoder,
42
43 TimeKey: "timestamp",
44 EncodeTime: func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) {
45 encoder.AppendString(ts.Local().Format(time.RFC3339))
46 },
47 EncodeDuration: zapcore.SecondsDurationEncoder,
48
49 CallerKey: "caller",
50 EncodeCaller: zapcore.ShortCallerEncoder,
51
52 // StacktraceKey: "stacktrace",
53 StacktraceKey: "",
54 LineEnding: zapcore.DefaultLineEnding,
55 },
56 }
57
58 logger, err := cfg.Build()
59 if err != nil {
60 panic(err)
61 }
62 //nolint:errcheck
63 defer logger.Sync()
64 withOptions := logger.WithOptions(zap.AddCallerSkip(1))
65 log = withOptions.Sugar()
66}
67
68func sprintStackTrace(st []tracerr.Frame) string {
69 builder := strings.Builder{}
70 // Skip deepest frame because it belongs to the go runtime and we don't
71 // care about it.
72 if len(st) > 0 {
73 st = st[:len(st)-1]
74 }
75 for _, f := range st {
76 builder.WriteString(fmt.Sprintf("\n%s:%d %s()", f.Path, f.Line, f.Func))
77 }
78 builder.WriteString("\n")
79 return builder.String()
80}
81
82// appendStackTraceMaybeArgs will append the stacktrace to the args if one of them
83// is a tracerr.Error
84func appendStackTraceMaybeArgs(args []interface{}) []interface{} {
85 for i := range args {
86 if err, ok := args[i].(tracerr.Error); ok {
87 st := err.StackTrace()
88 return append(args, sprintStackTrace(st))
89 }
90 }
91 return args
92}
93
94// Debug calls log.Debug
95func Debug(args ...interface{}) {
96 log.Debug(args...)
97}
98
99// Info calls log.Info
100func Info(args ...interface{}) {
101 log.Info(args...)
102}
103
104// Warn calls log.Warn
105func Warn(args ...interface{}) {
106 args = appendStackTraceMaybeArgs(args)
107 log.Warn(args...)
108}
109
110// Error calls log.Error
111func Error(args ...interface{}) {
112 args = appendStackTraceMaybeArgs(args)
113 log.Error(args...)
114}
115
116// Fatal calls log.Fatal
117func Fatal(args ...interface{}) {
118 args = appendStackTraceMaybeArgs(args)
119 log.Fatal(args...)
120}
121
122// Debugf calls log.Debugf
123func Debugf(template string, args ...interface{}) {
124 log.Debugf(template, args...)
125}
126
127// Infof calls log.Infof
128func Infof(template string, args ...interface{}) {
129 log.Infof(template, args...)
130}
131
132// Warnf calls log.Warnf
133func Warnf(template string, args ...interface{}) {
134 log.Warnf(template, args...)
135}
136
137// Fatalf calls log.Warnf
138func Fatalf(template string, args ...interface{}) {
139 log.Fatalf(template, args...)
140}
141
142// Errorf calls log.Errorf and stores the error message into the ErrorFile
143func Errorf(template string, args ...interface{}) {
144 log.Errorf(template, args...)
145}
146
147// appendStackTraceMaybeKV will append the stacktrace to the KV if one of them
148// is a tracerr.Error
149func appendStackTraceMaybeKV(msg string, kv []interface{}) string {
150 for i := range kv {
151 if i%2 == 0 {
152 continue
153 }
154 if err, ok := kv[i].(tracerr.Error); ok {
155 st := err.StackTrace()
156 return fmt.Sprintf("%v: %v%v\n", msg, err, sprintStackTrace(st))
157 }
158 }
159 return msg
160}
161
162// Debugw calls log.Debugw
163func Debugw(template string, kv ...interface{}) {
164 log.Debugw(template, kv...)
165}
166
167// Infow calls log.Infow
168func Infow(template string, kv ...interface{}) {
169 log.Infow(template, kv...)
170}
171
172// Warnw calls log.Warnw
173func Warnw(template string, kv ...interface{}) {
174 template = appendStackTraceMaybeKV(template, kv)
175 log.Warnw(template, kv...)
176}
177
178// Errorw calls log.Errorw
179func Errorw(template string, kv ...interface{}) {
180 template = appendStackTraceMaybeKV(template, kv)
181 log.Errorw(template, kv...)
182}
183
184// Fatalw calls log.Fatalw
185func Fatalw(template string, kv ...interface{}) {
186 template = appendStackTraceMaybeKV(template, kv)
187 log.Fatalw(template, kv...)
188}