gitee.com/h79/goutils@v1.22.10/dao/db/logger.go (about)

     1  package db
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"gitee.com/h79/goutils/common/logger"
     9  	"gitee.com/h79/goutils/common/result"
    10  	"gitee.com/h79/goutils/dao/config"
    11  	"gitee.com/h79/goutils/dao/util"
    12  	"go.uber.org/zap"
    13  	"gorm.io/gorm"
    14  	gormLogger "gorm.io/gorm/logger"
    15  	"strconv"
    16  	"strings"
    17  	"time"
    18  )
    19  
    20  type Logger struct {
    21  	config.SqlLogger
    22  }
    23  
    24  // LogMode log mode
    25  func (l *Logger) LogMode(level gormLogger.LogLevel) gormLogger.Interface {
    26  	newLogger := *l
    27  	newLogger.LogLevel = int(level)
    28  	return &newLogger
    29  }
    30  
    31  // Info print info
    32  func (l *Logger) Info(ctx context.Context, msg string, data ...interface{}) {
    33  	if l.check(gormLogger.Info) {
    34  		logger.Info(msg, data...)
    35  	}
    36  }
    37  
    38  // Warn print warn messages
    39  func (l *Logger) Warn(ctx context.Context, msg string, data ...interface{}) {
    40  	if l.check(gormLogger.Warn) {
    41  		logger.Warn(msg, data...)
    42  	}
    43  }
    44  
    45  // Error print error messages
    46  func (l *Logger) Error(ctx context.Context, msg string, data ...interface{}) {
    47  	if l.check(gormLogger.Error) {
    48  		logger.Error(msg, data...)
    49  	}
    50  }
    51  
    52  // Trace print sql message
    53  func (l *Logger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
    54  
    55  	elapsed := time.Now().Sub(begin)
    56  	switch {
    57  	case err != nil:
    58  
    59  		recordNotFound := errors.Is(err, gorm.ErrRecordNotFound)
    60  		logEnabled := l.check(gormLogger.Error) && (!recordNotFound || !l.IgnoreRecordNotFoundError)
    61  		if !logEnabled && !l.AlarmEnabled {
    62  			return
    63  		}
    64  
    65  		sql, rows := fc()
    66  		if logEnabled {
    67  			zap.L().Info("DB",
    68  				zap.Error(err),
    69  				zap.Int64("rows", rows),
    70  				zap.String("sql", sql),
    71  				zap.String("speed", elapsed.String()))
    72  		}
    73  
    74  		if l.AlarmEnabled && !recordNotFound {
    75  			var b = strings.Builder{}
    76  			b.WriteString("sql: '")
    77  			b.WriteString(sql)
    78  			b.WriteString("',rows: '")
    79  			b.WriteString(strconv.Itoa(int(rows)))
    80  			b.WriteString("',speed: '")
    81  			b.WriteString(elapsed.String())
    82  			b.WriteString("'")
    83  			util.Alarm(result.ErrDbInternal, "Sql", b.String(), err)
    84  		}
    85  
    86  	case elapsed > l.SlowThreshold && l.SlowThreshold != 0:
    87  
    88  		if !l.check(gormLogger.Warn) && !l.AlarmEnabled {
    89  			return
    90  		}
    91  		sql, rows := fc()
    92  		if l.check(gormLogger.Warn) {
    93  			zap.L().Warn("DB",
    94  				zap.String("slow", fmt.Sprintf("SLOW SQL >= %v", l.SlowThreshold)),
    95  				zap.Int64("rows", rows),
    96  				zap.String("sql", sql),
    97  				zap.String("speed", elapsed.String()))
    98  		}
    99  
   100  		if l.AlarmEnabled {
   101  			var b = strings.Builder{}
   102  			b.WriteString("sql: '")
   103  			b.WriteString(sql)
   104  			b.WriteString("',rows: '")
   105  			b.WriteString(strconv.Itoa(int(rows)))
   106  			b.WriteString("',speed: '")
   107  			b.WriteString(elapsed.String())
   108  			b.WriteString("'")
   109  			util.Alarm(result.ErrDbInternal, "Sql", b.String(), nil)
   110  		}
   111  
   112  	case l.check(gormLogger.Info):
   113  		sql, rows := fc()
   114  		zap.L().Info("DB",
   115  			zap.Int64("rows", rows),
   116  			zap.String("sql", sql),
   117  			zap.String("speed", elapsed.String()))
   118  	}
   119  }
   120  
   121  func (l *Logger) check(level gormLogger.LogLevel) bool {
   122  	return gormLogger.LogLevel(l.LogLevel) >= level
   123  }
   124  
   125  func (l *Logger) handlerConfig(ctx context.Context, cmd int, configType, conf string) (any, error) {
   126  	switch cmd {
   127  	case 1:
   128  		var c = config.SqlLogger{}
   129  		var err = json.Unmarshal([]byte(conf), &c)
   130  		if err != nil {
   131  			return "", err
   132  		}
   133  		l.LogLevel = c.LogLevel
   134  		l.IgnoreRecordNotFoundError = c.IgnoreRecordNotFoundError
   135  		l.AlarmEnabled = c.AlarmEnabled
   136  		l.SlowThreshold = c.SlowThreshold
   137  		return "", nil
   138  	case 2: //获取
   139  		return config.SqlLogger{}, nil
   140  	}
   141  	return "", result.RErrNotSupport
   142  }
   143  
   144  type esLogger struct {
   145  	Level    int  `json:"level"`
   146  	LogLevel int8 `json:"logLevel"`
   147  }
   148  
   149  func (l *esLogger) Printf(format string, v ...interface{}) {
   150  	if l.LogLevel < int8(l.Level) {
   151  		return
   152  	}
   153  	switch l.LogLevel {
   154  	case logger.ErrorLevel:
   155  		logger.E("Elastic", format, v...)
   156  	case logger.DebugLevel:
   157  		logger.D("Elastic", format, v...)
   158  	case logger.InfoLevel:
   159  		logger.I("Elastic", format, v...)
   160  	}
   161  }
   162  
   163  func (l *esLogger) handlerConfig(ctx context.Context, cmd int, configType, conf string) (any, error) {
   164  	switch cmd {
   165  	case 1:
   166  		var c = esLogger{}
   167  		var err = json.Unmarshal([]byte(conf), &c)
   168  		if err != nil {
   169  			return "", err
   170  		}
   171  		l.Level = c.Level
   172  		l.LogLevel = c.LogLevel
   173  		return "", nil
   174  	case 2: //获取
   175  		return esLogger{}, nil
   176  	}
   177  	return "", result.RErrNotSupport
   178  }