github.com/abolfazlbeh/zhycan@v0.0.0-20230819144214-24cf38237387/internal/db/logger.go (about)

     1  package db
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	zlogger "github.com/abolfazlbeh/zhycan/internal/logger"
     8  	"go.mongodb.org/mongo-driver/mongo/options"
     9  	"gorm.io/gorm/logger"
    10  	"gorm.io/gorm/utils"
    11  	"strings"
    12  	"time"
    13  )
    14  
    15  // MARK: Variables
    16  var (
    17  	DbLogType      = zlogger.NewLogType("DB_OP")
    18  	DbTraceLogType = zlogger.NewLogType("DB_TRACE_OP")
    19  )
    20  
    21  // DbLogger - DB Logger struct
    22  type DbLogger struct {
    23  	logger.Config
    24  }
    25  
    26  // NewDbLogger - return instance of DbLogger which implement Interface
    27  func NewDbLogger(config LoggerConfig) logger.Interface {
    28  	logLevel := logger.Silent
    29  	switch strings.ToLower(config.LogLevel) {
    30  	case "error":
    31  		logLevel = logger.Error
    32  		break
    33  	case "warn":
    34  		logLevel = logger.Warn
    35  		break
    36  	case "info":
    37  		logLevel = logger.Info
    38  		break
    39  	}
    40  
    41  	return &DbLogger{Config: logger.Config{
    42  		SlowThreshold:             time.Duration(config.SlowThreshold) * time.Millisecond,
    43  		Colorful:                  false,
    44  		IgnoreRecordNotFoundError: config.IgnoreRecordNotFoundError,
    45  		ParameterizedQueries:      config.ParameterizedQueries,
    46  		LogLevel:                  logLevel,
    47  	}}
    48  }
    49  
    50  // LogMode - set log mode
    51  func (l *DbLogger) LogMode(level logger.LogLevel) logger.Interface {
    52  	newlogger := *l
    53  	newlogger.LogLevel = level
    54  	return &newlogger
    55  }
    56  
    57  // Info - print info
    58  func (l DbLogger) Info(ctx context.Context, msg string, data ...interface{}) {
    59  	ll, _ := zlogger.GetManager().GetLogger()
    60  	if l.LogLevel >= logger.Info && ll != nil {
    61  		newMsg := fmt.Sprintf(msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)
    62  		ll.Log(zlogger.NewLogObject(
    63  			zlogger.INFO, "db", DbLogType,
    64  			time.Now().UTC(), newMsg, nil,
    65  		))
    66  	}
    67  }
    68  
    69  // Warn - print warn messages
    70  func (l DbLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
    71  	ll, _ := zlogger.GetManager().GetLogger()
    72  	if l.LogLevel >= logger.Warn && ll != nil {
    73  		newMsg := fmt.Sprintf(msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)
    74  		ll.Log(zlogger.NewLogObject(
    75  			zlogger.WARNING, "db", DbLogType,
    76  			time.Now().UTC(), newMsg, nil,
    77  		))
    78  	}
    79  }
    80  
    81  // Error - print error messages
    82  func (l DbLogger) Error(ctx context.Context, msg string, data ...interface{}) {
    83  	ll, _ := zlogger.GetManager().GetLogger()
    84  	if l.LogLevel >= logger.Error && ll != nil {
    85  		newMsg := fmt.Sprintf(msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)
    86  		ll.Log(zlogger.NewLogObject(
    87  			zlogger.ERROR, "db", DbLogType,
    88  			time.Now().UTC(), newMsg, nil,
    89  		))
    90  	}
    91  }
    92  
    93  // Trace - print sql message
    94  func (l DbLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
    95  	if l.LogLevel <= logger.Silent {
    96  		return
    97  	}
    98  
    99  	ll, _ := zlogger.GetManager().GetLogger()
   100  	if ll != nil {
   101  		elapsed := time.Since(begin)
   102  		switch {
   103  		case err != nil && l.LogLevel >= logger.Error &&
   104  			(!errors.Is(err, logger.ErrRecordNotFound) ||
   105  				!l.IgnoreRecordNotFoundError):
   106  			sql, rows := fc()
   107  			msgLiteral := "%s %s\n[%.3fms] [rows:%v] %s"
   108  			if rows == -1 {
   109  				msg := fmt.Sprintf(msgLiteral, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql)
   110  				ll.Log(zlogger.NewLogObject(
   111  					zlogger.ERROR, "db", DbTraceLogType,
   112  					time.Now().UTC(), msg, []interface{}{err, sql},
   113  				))
   114  			} else {
   115  				msg := fmt.Sprintf(msgLiteral, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql)
   116  				ll.Log(zlogger.NewLogObject(
   117  					zlogger.ERROR, "db", DbTraceLogType,
   118  					time.Now().UTC(), msg, []interface{}{err, sql, rows},
   119  				))
   120  			}
   121  		case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= logger.Warn:
   122  			sql, rows := fc()
   123  			slowLog := fmt.Sprintf("SLOW SQL >= %v", l.SlowThreshold)
   124  
   125  			msgLiteral := "%s %s\n[%.3fms] [rows:%v] %s"
   126  			if rows == -1 {
   127  				msg := fmt.Sprintf(msgLiteral, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql)
   128  				ll.Log(zlogger.NewLogObject(
   129  					zlogger.WARNING, "db", DbTraceLogType,
   130  					time.Now().UTC(), msg, []interface{}{slowLog, sql},
   131  				))
   132  			} else {
   133  				msg := fmt.Sprintf(msgLiteral, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql)
   134  				ll.Log(zlogger.NewLogObject(
   135  					zlogger.WARNING, "db", DbTraceLogType,
   136  					time.Now().UTC(), msg, []interface{}{slowLog, sql, rows},
   137  				))
   138  			}
   139  		case l.LogLevel == logger.Info:
   140  			sql, rows := fc()
   141  
   142  			msgLiteral := "%s\n[%.3fms] [rows:%v] %s"
   143  			if rows == -1 {
   144  				msg := fmt.Sprintf(msgLiteral, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql)
   145  				ll.Log(zlogger.NewLogObject(
   146  					zlogger.INFO, "db", DbTraceLogType,
   147  					time.Now().UTC(), msg, []interface{}{sql},
   148  				))
   149  			} else {
   150  				msg := fmt.Sprintf(msgLiteral, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql)
   151  				ll.Log(zlogger.NewLogObject(
   152  					zlogger.INFO, "db", DbTraceLogType,
   153  					time.Now().UTC(), msg, []interface{}{sql, rows},
   154  				))
   155  			}
   156  		}
   157  	}
   158  }
   159  
   160  // MongoLogger - Mongo DB Logger struct
   161  type MongoLogger struct {
   162  }
   163  
   164  func (m *MongoLogger) Info(level int, message string, keysAndValues ...interface{}) {
   165  	ll, _ := zlogger.GetManager().GetLogger()
   166  	if ll != nil {
   167  		if options.LogLevel(level) == options.LogLevelInfo {
   168  			ll.Log(zlogger.NewLogObject(
   169  				zlogger.INFO, "mongodb", DbLogType,
   170  				time.Now().UTC(), message, keysAndValues,
   171  			))
   172  		} else if options.LogLevel(level) == options.LogLevelDebug {
   173  			ll.Log(zlogger.NewLogObject(
   174  				zlogger.DEBUG, "mongodb", DbLogType,
   175  				time.Now().UTC(), message, keysAndValues,
   176  			))
   177  		}
   178  	}
   179  }
   180  
   181  func (m *MongoLogger) Error(err error, message string, keysAndValues ...interface{}) {
   182  	ll, _ := zlogger.GetManager().GetLogger()
   183  	if ll != nil {
   184  		msg := fmt.Sprintf("%s -> err: %v", message, err)
   185  		ll.Log(zlogger.NewLogObject(
   186  			zlogger.ERROR, "mongodb", DbLogType,
   187  			time.Now().UTC(), msg, keysAndValues,
   188  		))
   189  	}
   190  }