logger.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package database
  2. import (
  3. "context"
  4. "go.uber.org/zap"
  5. "go.uber.org/zap/zapcore"
  6. "gorm.io/gorm/logger"
  7. "gorm.io/gorm/utils"
  8. "time"
  9. )
  10. // Colors
  11. const (
  12. Reset = "\033[0m"
  13. Red = "\033[31m"
  14. Green = "\033[32m"
  15. Yellow = "\033[33m"
  16. Blue = "\033[34m"
  17. Magenta = "\033[35m"
  18. Cyan = "\033[36m"
  19. White = "\033[37m"
  20. BlueBold = "\033[34;1m"
  21. MagentaBold = "\033[35;1m"
  22. RedBold = "\033[31;1m"
  23. YellowBold = "\033[33;1m"
  24. )
  25. // Writer log writer interface
  26. type Writer interface {
  27. Printf(string, ...interface{})
  28. }
  29. type CustomLogger struct {
  30. Writer
  31. Config
  32. infoStr, warnStr, errStr string
  33. traceStr, traceErrStr, traceWarnStr string
  34. }
  35. type Config struct {
  36. SlowThreshold time.Duration
  37. Colorful bool
  38. IgnoreRecordNotFoundError bool
  39. LogLevel zapcore.Level
  40. TraceWithLevel zapcore.Level
  41. Zap *zap.Logger
  42. }
  43. var gormLogLevelMap = map[logger.LogLevel]zapcore.Level{
  44. logger.Info: zap.InfoLevel,
  45. logger.Warn: zap.WarnLevel,
  46. logger.Error: zap.ErrorLevel,
  47. }
  48. // LogMode log mode
  49. func (c CustomLogger) LogMode(level logger.LogLevel) logger.Interface {
  50. zapLevel, exist := gormLogLevelMap[level]
  51. if !exist {
  52. zapLevel = zap.DebugLevel
  53. }
  54. newlogger := c
  55. newlogger.LogLevel = zapLevel
  56. newlogger.TraceWithLevel = zapLevel
  57. return &newlogger
  58. }
  59. func (c CustomLogger) Info(ctx context.Context, msg string, data ...interface{}) {
  60. if c.Config.LogLevel <= zap.InfoLevel && c.Config.Zap != nil {
  61. c.Config.Zap.Sugar().Infof(msg, data...)
  62. }
  63. }
  64. func (c CustomLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
  65. if c.Config.LogLevel <= zap.WarnLevel && c.Config.Zap != nil {
  66. c.Config.Zap.Sugar().Warnf(msg, data...)
  67. }
  68. }
  69. func (c CustomLogger) Error(ctx context.Context, msg string, data ...interface{}) {
  70. if c.Config.LogLevel <= zap.ErrorLevel && c.Config.Zap != nil {
  71. c.Config.Zap.Sugar().Errorf(msg, data...)
  72. }
  73. }
  74. func (c CustomLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
  75. elapsed := time.Since(begin)
  76. sql, rows := fc()
  77. if c.Config.LogLevel <= zap.InfoLevel {
  78. c.Printf(c.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql)
  79. }
  80. if c.Config.Zap == nil {
  81. return
  82. }
  83. switch {
  84. case err != nil:
  85. c.Config.Zap.Error("sql: "+sql, zap.Float64("elapsed", elapsed.Seconds()), zap.Int64("rows", rows), zap.String("error", err.Error()))
  86. case c.Config.SlowThreshold != 0 && elapsed.Seconds() > c.Config.SlowThreshold.Seconds():
  87. c.Config.Zap.Warn("sql: "+sql, zap.Float64("elapsed", elapsed.Seconds()), zap.Int64("rows", rows), zap.Float64("threshold", c.Config.SlowThreshold.Seconds()))
  88. case c.Config.LogLevel == zap.DebugLevel:
  89. log := c.Config.Zap.Debug
  90. if c.Config.TraceWithLevel == zap.InfoLevel {
  91. log = c.Config.Zap.Info
  92. } else if c.Config.TraceWithLevel == zap.WarnLevel {
  93. log = c.Config.Zap.Warn
  94. } else if c.Config.TraceWithLevel == zap.ErrorLevel {
  95. log = c.Config.Zap.Error
  96. }
  97. log("sql: "+sql, zap.Float64("elapsed", elapsed.Seconds()), zap.Int64("rows", rows))
  98. }
  99. }
  100. // NewGormLogger 返回带 zap logger 的 GormLogger
  101. func NewGormLogger(writer Writer, config Config) CustomLogger {
  102. var (
  103. infoStr = "%s\n[info] "
  104. warnStr = "%s\n[warn] "
  105. errStr = "%s\n[error] "
  106. traceStr = "%s\n[%.3fms] [rows:%v] %s"
  107. traceWarnStr = "%s %s\n[%.3fms] [rows:%v] %s"
  108. traceErrStr = "%s %s\n[%.3fms] [rows:%v] %s"
  109. )
  110. if config.Colorful {
  111. infoStr = Green + "%s\n" + Reset + Green + "[info] " + Reset
  112. warnStr = BlueBold + "%s\n" + Reset + Magenta + "[warn] " + Reset
  113. errStr = Magenta + "%s\n" + Reset + Red + "[error] " + Reset
  114. traceStr = Green + "%s\n" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s"
  115. traceWarnStr = Green + "%s " + Yellow + "%s\n" + Reset + RedBold + "[%.3fms] " + Yellow + "[rows:%v]" + Magenta + " %s" + Reset
  116. traceErrStr = RedBold + "%s " + MagentaBold + "%s\n" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s"
  117. }
  118. return CustomLogger{
  119. Writer: writer,
  120. Config: config,
  121. infoStr: infoStr,
  122. warnStr: warnStr,
  123. errStr: errStr,
  124. traceStr: traceStr,
  125. traceWarnStr: traceWarnStr,
  126. traceErrStr: traceErrStr,
  127. }
  128. }