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.

183 lines
4.3 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 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. for _, f := range st {
  59. builder.WriteString(fmt.Sprintf("\n%s:%d %s()", f.Path, f.Line, f.Func))
  60. }
  61. builder.WriteString("\n")
  62. return builder.String()
  63. }
  64. // appendStackTraceMaybeArgs will append the stacktrace to the args if one of them
  65. // is a tracerr.Error
  66. func appendStackTraceMaybeArgs(args []interface{}) []interface{} {
  67. for i := range args {
  68. if err, ok := args[i].(tracerr.Error); ok {
  69. st := err.StackTrace()
  70. return append(args, sprintStackTrace(st))
  71. }
  72. }
  73. return args
  74. }
  75. // Debug calls log.Debug
  76. func Debug(args ...interface{}) {
  77. log.Debug(args...)
  78. }
  79. // Info calls log.Info
  80. func Info(args ...interface{}) {
  81. log.Info(args...)
  82. }
  83. // Warn calls log.Warn
  84. func Warn(args ...interface{}) {
  85. args = appendStackTraceMaybeArgs(args)
  86. log.Warn(args...)
  87. }
  88. // Error calls log.Error
  89. func Error(args ...interface{}) {
  90. args = appendStackTraceMaybeArgs(args)
  91. log.Error(args...)
  92. }
  93. // Fatal calls log.Fatal
  94. func Fatal(args ...interface{}) {
  95. args = appendStackTraceMaybeArgs(args)
  96. log.Fatal(args...)
  97. }
  98. // Debugf calls log.Debugf
  99. func Debugf(template string, args ...interface{}) {
  100. log.Debugf(template, args...)
  101. }
  102. // Infof calls log.Infof
  103. func Infof(template string, args ...interface{}) {
  104. log.Infof(template, args...)
  105. }
  106. // Warnf calls log.Warnf
  107. func Warnf(template string, args ...interface{}) {
  108. log.Warnf(template, args...)
  109. }
  110. // Fatalf calls log.Warnf
  111. func Fatalf(template string, args ...interface{}) {
  112. log.Fatalf(template, args...)
  113. }
  114. // Errorf calls log.Errorf and stores the error message into the ErrorFile
  115. func Errorf(template string, args ...interface{}) {
  116. log.Errorf(template, args...)
  117. }
  118. // appendStackTraceMaybeKV will append the stacktrace to the KV if one of them
  119. // is a tracerr.Error
  120. func appendStackTraceMaybeKV(msg string, kv []interface{}) string {
  121. for i := range kv {
  122. if i%2 == 0 {
  123. continue
  124. }
  125. if err, ok := kv[i].(tracerr.Error); ok {
  126. st := err.StackTrace()
  127. return fmt.Sprintf("%v: %v%v\n", msg, err, sprintStackTrace(st))
  128. }
  129. }
  130. return msg
  131. }
  132. // Debugw calls log.Debugw
  133. func Debugw(template string, kv ...interface{}) {
  134. log.Debugw(template, kv...)
  135. }
  136. // Infow calls log.Infow
  137. func Infow(template string, kv ...interface{}) {
  138. log.Infow(template, kv...)
  139. }
  140. // Warnw calls log.Warnw
  141. func Warnw(template string, kv ...interface{}) {
  142. template = appendStackTraceMaybeKV(template, kv)
  143. log.Warnw(template, kv...)
  144. }
  145. // Errorw calls log.Errorw
  146. func Errorw(template string, kv ...interface{}) {
  147. template = appendStackTraceMaybeKV(template, kv)
  148. log.Errorw(template, kv...)
  149. }
  150. // Fatalw calls log.Fatalw
  151. func Fatalw(template string, kv ...interface{}) {
  152. template = appendStackTraceMaybeKV(template, kv)
  153. log.Fatalw(template, kv...)
  154. }