github.com/wfusion/gofusion@v1.1.14/log/customlogger/redis.go (about) 1 package customlogger 2 3 import ( 4 "context" 5 "net" 6 "reflect" 7 "strings" 8 "time" 9 10 "github.com/spf13/cast" 11 12 "github.com/wfusion/gofusion/common/utils" 13 "github.com/wfusion/gofusion/config" 14 "github.com/wfusion/gofusion/log" 15 16 rdsDrv "github.com/redis/go-redis/v9" 17 ) 18 19 var ( 20 // RedisLoggerType FIXME: should not be deleted to avoid compiler optimized 21 RedisLoggerType = reflect.TypeOf(redisLogger{}) 22 redisFields = log.Fields{"component": strings.ToLower(config.ComponentRedis)} 23 ) 24 25 type redisLogger struct { 26 log log.Loggable 27 appName string 28 confName string 29 enabled bool 30 unloggableCommandSet *utils.Set[string] 31 } 32 33 func (r *redisLogger) Init(log log.Loggable, appName, name string) { 34 r.log = log 35 r.appName = appName 36 r.confName = name 37 r.reloadConfig() 38 } 39 40 func (r *redisLogger) DialHook(next rdsDrv.DialHook) rdsDrv.DialHook { 41 return func(ctx context.Context, network, addr string) (c net.Conn, e error) { return next(ctx, network, addr) } 42 } 43 44 func (r *redisLogger) ProcessHook(next rdsDrv.ProcessHook) rdsDrv.ProcessHook { 45 return func(ctx context.Context, cmd rdsDrv.Cmder) (err error) { 46 if !r.isLoggableCommandSet(cmd.Name()) { 47 return next(ctx, cmd) 48 } 49 50 begin := time.Now() 51 if err = next(ctx, cmd); err != nil { 52 r.logger().Warn(ctx, "%s failed [command[%s]]", cmd.FullName(), cmd.String(), 53 r.fields(log.Fields{"latency": time.Since(begin).Milliseconds()})) 54 return 55 } 56 57 r.logger().Info(ctx, "%s succeeded [command[%s]]", cmd.FullName(), cmd.String(), 58 r.fields(log.Fields{"latency": time.Since(begin).Milliseconds()})) 59 return 60 } 61 } 62 63 func (r *redisLogger) ProcessPipelineHook(next rdsDrv.ProcessPipelineHook) rdsDrv.ProcessPipelineHook { 64 return func(ctx context.Context, cmds []rdsDrv.Cmder) (err error) { 65 if !r.isLoggable() { 66 return next(ctx, cmds) 67 } 68 begin := time.Now() 69 fullNameSb := new(strings.Builder) 70 for _, cmd := range cmds { 71 _, _ = fullNameSb.WriteString(cmd.FullName() + " -> ") 72 } 73 74 if err = next(ctx, cmds); err != nil { 75 r.logger().Warn(ctx, "%s failed", fullNameSb.String(), 76 r.fields(log.Fields{"latency": time.Since(begin).Milliseconds()})) 77 return 78 } 79 80 r.logger().Info(ctx, "%s succeeded", fullNameSb.String(), 81 r.fields(log.Fields{"latency": time.Since(begin).Milliseconds()})) 82 return 83 } 84 } 85 86 func (r *redisLogger) logger() log.Loggable { 87 if r.log != nil { 88 return r.log 89 } 90 return log.Use(config.DefaultInstanceKey, log.AppName(r.appName)) 91 } 92 93 func (r *redisLogger) fields(fields log.Fields) log.Fields { 94 return utils.MapMerge(fields, redisFields) 95 } 96 97 func (r *redisLogger) isLoggableCommandSet(command string) bool { 98 if r.confName == "" { 99 return true 100 } 101 102 r.reloadConfig() 103 if !r.enabled { 104 return false 105 } 106 if r.unloggableCommandSet == nil { 107 return true 108 } 109 return !r.unloggableCommandSet.Contains(command) 110 } 111 112 func (r *redisLogger) isLoggable() bool { 113 if r.confName == "" { 114 return true 115 } 116 r.reloadConfig() 117 return r.enabled 118 } 119 120 func (r *redisLogger) reloadConfig() { 121 var cfgs map[string]map[string]any 122 _ = config.Use(r.appName).LoadComponentConfig(config.ComponentRedis, &cfgs) 123 if len(cfgs) == 0 { 124 return 125 } 126 127 cfg, ok := cfgs[r.confName] 128 if !ok { 129 return 130 } 131 enabled := cast.ToBool(cfg["enable_logger"]) 132 r.enabled = enabled 133 134 unloggableCommandsObj, ok1 := cfg["unloggable_commands"] 135 unloggableCommands, ok2 := unloggableCommandsObj.([]string) 136 if !ok1 || !ok2 { 137 return 138 } 139 sets := utils.NewSet(unloggableCommands...) 140 r.unloggableCommandSet = sets 141 }