You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
4.5 KiB

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