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.

182 lines
5.5 KiB

  1. package internal
  2. import (
  3. "context"
  4. "fmt"
  5. "gin-vue-admin/global"
  6. "go.uber.org/zap"
  7. "gorm.io/gorm/logger"
  8. "gorm.io/gorm/utils"
  9. "io/ioutil"
  10. "log"
  11. "os"
  12. "time"
  13. )
  14. // writer log writer interface
  15. type writer interface {
  16. Printf(string, ...interface{})
  17. }
  18. type config struct {
  19. SlowThreshold time.Duration
  20. Colorful bool
  21. LogLevel logger.LogLevel
  22. }
  23. var (
  24. Discard = New(log.New(ioutil.Discard, "", log.LstdFlags), config{})
  25. Default = New(log.New(os.Stdout, "\r\n", log.LstdFlags), config{
  26. SlowThreshold: 200 * time.Millisecond,
  27. LogLevel: logger.Warn,
  28. Colorful: true,
  29. })
  30. Recorder = traceRecorder{Interface: Default, BeginAt: time.Now()}
  31. )
  32. func New(writer writer, config config) logger.Interface {
  33. var (
  34. infoStr = "%s\n[info] "
  35. warnStr = "%s\n[warn] "
  36. errStr = "%s\n[error] "
  37. traceStr = "%s\n[%.3fms] [rows:%v] %s"
  38. traceWarnStr = "%s %s\n[%.3fms] [rows:%v] %s"
  39. traceErrStr = "%s %s\n[%.3fms] [rows:%v] %s"
  40. )
  41. if config.Colorful {
  42. infoStr = logger.Green + "%s\n" + logger.Reset + logger.Green + "[info] " + logger.Reset
  43. warnStr = logger.BlueBold + "%s\n" + logger.Reset + logger.Magenta + "[warn] " + logger.Reset
  44. errStr = logger.Magenta + "%s\n" + logger.Reset + logger.Red + "[error] " + logger.Reset
  45. traceStr = logger.Green + "%s\n" + logger.Reset + logger.Yellow + "[%.3fms] " + logger.BlueBold + "[rows:%v]" + logger.Reset + " %s"
  46. traceWarnStr = logger.Green + "%s " + logger.Yellow + "%s\n" + logger.Reset + logger.RedBold + "[%.3fms] " + logger.Yellow + "[rows:%v]" + logger.Magenta + " %s" + logger.Reset
  47. traceErrStr = logger.RedBold + "%s " + logger.MagentaBold + "%s\n" + logger.Reset + logger.Yellow + "[%.3fms] " + logger.BlueBold + "[rows:%v]" + logger.Reset + " %s"
  48. }
  49. return &customLogger{
  50. writer: writer,
  51. config: config,
  52. infoStr: infoStr,
  53. warnStr: warnStr,
  54. errStr: errStr,
  55. traceStr: traceStr,
  56. traceWarnStr: traceWarnStr,
  57. traceErrStr: traceErrStr,
  58. }
  59. }
  60. type customLogger struct {
  61. writer
  62. config
  63. infoStr, warnStr, errStr string
  64. traceStr, traceErrStr, traceWarnStr string
  65. }
  66. // LogMode log mode
  67. func (c *customLogger) LogMode(level logger.LogLevel) logger.Interface {
  68. newLogger := *c
  69. newLogger.LogLevel = level
  70. return &newLogger
  71. }
  72. // Info print info
  73. func (c *customLogger) Info(ctx context.Context, message string, data ...interface{}) {
  74. if c.LogLevel >= logger.Info {
  75. c.Printf(c.infoStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...)
  76. }
  77. }
  78. // Warn print warn messages
  79. func (c *customLogger) Warn(ctx context.Context, message string, data ...interface{}) {
  80. if c.LogLevel >= logger.Warn {
  81. c.Printf(c.warnStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...)
  82. }
  83. }
  84. // Error print error messages
  85. func (c *customLogger) Error(ctx context.Context, message string, data ...interface{}) {
  86. if c.LogLevel >= logger.Error {
  87. c.Printf(c.errStr+message, append([]interface{}{utils.FileWithLineNum()}, data...)...)
  88. }
  89. }
  90. // Trace print sql message
  91. func (c *customLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
  92. if c.LogLevel > 0 {
  93. elapsed := time.Since(begin)
  94. switch {
  95. case err != nil && c.LogLevel >= logger.Error:
  96. sql, rows := fc()
  97. if rows == -1 {
  98. c.Printf(c.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql)
  99. } else {
  100. c.Printf(c.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql)
  101. }
  102. case elapsed > c.SlowThreshold && c.SlowThreshold != 0 && c.LogLevel >= logger.Warn:
  103. sql, rows := fc()
  104. slowLog := fmt.Sprintf("SLOW SQL >= %v", c.SlowThreshold)
  105. if rows == -1 {
  106. c.Printf(c.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql)
  107. } else {
  108. c.Printf(c.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql)
  109. }
  110. case c.LogLevel >= logger.Info:
  111. sql, rows := fc()
  112. if rows == -1 {
  113. c.Printf(c.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql)
  114. } else {
  115. c.Printf(c.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql)
  116. }
  117. }
  118. }
  119. }
  120. func (c *customLogger) Printf(message string, data ...interface{}) {
  121. if global.GVA_CONFIG.Mysql.LogZap != "" {
  122. switch len(data) {
  123. case 0:
  124. global.GVA_LOG.Info(message)
  125. case 1:
  126. global.GVA_LOG.Info("gorm", zap.Any("src", data[0]))
  127. case 2:
  128. global.GVA_LOG.Info("gorm", zap.Any("src", data[0]), zap.Any("duration", data[1]))
  129. case 3:
  130. global.GVA_LOG.Info("gorm", zap.Any("src", data[0]), zap.Any("duration", data[1]), zap.Any("rows", data[2]))
  131. case 4:
  132. global.GVA_LOG.Info("gorm", zap.Any("src", data[0]), zap.Any("duration", data[1]), zap.Any("rows", data[2]), zap.Any("sql", data[3]))
  133. }
  134. return
  135. }
  136. switch len(data) {
  137. case 0:
  138. c.writer.Printf(message, "")
  139. case 1:
  140. c.writer.Printf(message, data[0])
  141. case 2:
  142. c.writer.Printf(message, data[0], data[1])
  143. case 3:
  144. c.writer.Printf(message, data[0], data[1], data[2])
  145. case 4:
  146. c.writer.Printf(message, data[0], data[1], data[2], data[3])
  147. case 5:
  148. c.writer.Printf(message, data[0], data[1], data[2], data[3], data[4])
  149. }
  150. }
  151. type traceRecorder struct {
  152. logger.Interface
  153. BeginAt time.Time
  154. SQL string
  155. RowsAffected int64
  156. Err error
  157. }
  158. func (t traceRecorder) New() *traceRecorder {
  159. return &traceRecorder{Interface: t.Interface, BeginAt: time.Now()}
  160. }
  161. func (t *traceRecorder) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
  162. t.BeginAt = begin
  163. t.SQL, t.RowsAffected = fc()
  164. t.Err = err
  165. }