github.com/unionj-cloud/go-doudou@v1.3.8-0.20221011095552-0088008e5b31/toolkit/sqlext/logger/logger.go (about) 1 package logger 2 3 import ( 4 "context" 5 "fmt" 6 "github.com/ascarter/requestid" 7 "github.com/opentracing/opentracing-go" 8 "github.com/pkg/errors" 9 "github.com/rs/zerolog" 10 "github.com/uber/jaeger-client-go" 11 "github.com/unionj-cloud/go-doudou/toolkit/caller" 12 "github.com/unionj-cloud/go-doudou/toolkit/cast" 13 "github.com/unionj-cloud/go-doudou/toolkit/reflectutils" 14 "github.com/unionj-cloud/go-doudou/toolkit/stringutils" 15 "github.com/unionj-cloud/go-doudou/toolkit/zlogger" 16 "os" 17 "regexp" 18 "strings" 19 ) 20 21 type SqlLogger struct { 22 Logger zerolog.Logger 23 } 24 25 func (receiver SqlLogger) Enable() bool { 26 return cast.ToBoolOrDefault(os.Getenv("GDD_SQL_LOG_ENABLE"), false) 27 } 28 29 func (receiver SqlLogger) Log(ctx context.Context, query string, args ...interface{}) { 30 if !receiver.Enable() { 31 return 32 } 33 receiver.LogWithErr(ctx, nil, nil, query, args...) 34 } 35 36 type SqlLoggerOption func(logger *SqlLogger) 37 38 func WithLogger(logger zerolog.Logger) SqlLoggerOption { 39 return func(sqlLogger *SqlLogger) { 40 sqlLogger.Logger = logger 41 } 42 } 43 44 func NewSqlLogger(opts ...SqlLoggerOption) SqlLogger { 45 sqlLogger := SqlLogger{ 46 Logger: zlogger.Logger, 47 } 48 for _, item := range opts { 49 item(&sqlLogger) 50 } 51 return sqlLogger 52 } 53 54 var limitre *regexp.Regexp 55 56 func init() { 57 limitre = regexp.MustCompile(`limit '\d+'(,'\d+')?`) 58 } 59 60 func PopulatedSql(query string, args ...interface{}) string { 61 query = strings.Join(strings.Fields(query), " ") 62 copiedArgs := make([]interface{}, len(args)) 63 copy(copiedArgs, args) 64 for i, arg := range copiedArgs { 65 if arg == nil { 66 continue 67 } 68 value := reflectutils.ValueOf(arg) 69 if value.IsValid() { 70 copiedArgs[i] = value.Interface() 71 } 72 } 73 str := strings.ReplaceAll(fmt.Sprintf(strings.ReplaceAll(query, "?", "'%v'"), copiedArgs...), "'<nil>'", "null") 74 if limitre.MatchString(str) { 75 str = limitre.ReplaceAllStringFunc(str, func(s string) string { 76 return strings.ReplaceAll(s, "'", "") 77 }) 78 } 79 return str 80 } 81 82 func (receiver SqlLogger) LogWithErr(ctx context.Context, err error, hit *bool, query string, args ...interface{}) { 83 if !receiver.Enable() { 84 return 85 } 86 var sb strings.Builder 87 if reqId, ok := requestid.FromContext(ctx); ok && stringutils.IsNotEmpty(reqId) { 88 sb.WriteString(fmt.Sprintf("RequestID: %s\t", reqId)) 89 } 90 span := opentracing.SpanFromContext(ctx) 91 if span != nil { 92 if jspan, ok := span.(*jaeger.Span); ok { 93 sb.WriteString(fmt.Sprintf("TraceID: %s\t", jspan.SpanContext().TraceID().String())) 94 } else { 95 sb.WriteString(fmt.Sprintf("TraceID: %s\t", span)) 96 } 97 } 98 sb.WriteString(fmt.Sprintf("SQL: %s", PopulatedSql(query, args...))) 99 if hit != nil { 100 sb.WriteString(fmt.Sprintf("\tHIT: %t", *hit)) 101 } 102 if err != nil { 103 sb.WriteString(fmt.Sprintf("\tERR: %s", errors.Wrap(err, caller.NewCaller().String()))) 104 } 105 receiver.Logger.Info().Msgf(sb.String()) 106 }