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  }