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.

152 lines
4.6 KiB

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