1
0
mirror of https://github.com/redis/go-redis.git synced 2025-12-02 06:22:31 +03:00

reorg and refactor of types

This commit is contained in:
Nedyalko Dyakov
2025-11-25 17:39:50 +02:00
parent f8945609f2
commit 8bf1376591
21 changed files with 113 additions and 115 deletions

View File

@@ -13,6 +13,7 @@ import (
"time"
"github.com/redis/go-redis/v9/internal"
"github.com/redis/go-redis/v9/logging"
)
// KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
@@ -28,11 +29,7 @@ func usePrecise(dur time.Duration) bool {
func formatMs(ctx context.Context, dur time.Duration) int64 {
if dur > 0 && dur < time.Millisecond {
internal.Logger.Printf(
ctx,
"specified duration is %s, but minimal supported value is %s - truncating to 1ms",
dur, time.Millisecond,
)
logging.LoggerWithLevel().Infof(ctx, "specified duration is %s, but minimal supported value is %s - truncating to 1ms", dur, time.Millisecond)
return 1
}
return int64(dur / time.Millisecond)
@@ -40,11 +37,7 @@ func formatMs(ctx context.Context, dur time.Duration) int64 {
func formatSec(ctx context.Context, dur time.Duration) int64 {
if dur > 0 && dur < time.Second {
internal.Logger.Printf(
ctx,
"specified duration is %s, but minimal supported value is %s - truncating to 1s",
dur, time.Second,
)
logging.LoggerWithLevel().Infof(ctx, "specified duration is %s, but minimal supported value is %s - truncating to 1s", dur, time.Second)
return 1
}
return int64(dur / time.Second)

View File

@@ -6,9 +6,9 @@ import (
"net"
"strings"
"github.com/redis/go-redis/v9/internal"
"github.com/redis/go-redis/v9/internal/hashtag"
"github.com/redis/go-redis/v9/internal/pool"
"github.com/redis/go-redis/v9/logging"
)
func (c *baseClient) Pool() pool.Pooler {
@@ -87,7 +87,7 @@ func (c *clusterState) IsConsistent(ctx context.Context) bool {
func GetSlavesAddrByName(ctx context.Context, c *SentinelClient, name string) []string {
addrs, err := c.Replicas(ctx, name).Result()
if err != nil {
internal.Logger.Printf(ctx, "sentinel: Replicas name=%q failed: %s",
logging.LoggerWithLevel.Errorf(ctx, "sentinel: Replicas name=%q failed: %s",
name, err)
return []string{}
}

View File

@@ -166,7 +166,7 @@ func (r *ReAuthPoolHook) OnPut(_ context.Context, conn *pool.Conn) (bool, bool,
defer func() {
if rec := recover(); rec != nil {
// once again - safety first
internal.Logger.Printf(context.Background(), "panic in reauth worker: %v", rec)
LoggerWrapper.Printf(context.Background(), "panic in reauth worker: %v", rec)
}
r.scheduledLock.Lock()
delete(r.scheduledReAuth, connID)

View File

@@ -38,6 +38,7 @@ var LogLevel LogLevelT = LogLevelError
type LogLevelT int
// Log level constants for the entire go-redis library
// TODO(ndyakov): In v10 align those levels with slog.Level
const (
LogLevelError LogLevelT = iota // 0 - errors only
LogLevelWarn // 1 - warnings and errors

View File

@@ -11,9 +11,9 @@ import (
"sync/atomic"
"time"
"github.com/redis/go-redis/v9/internal"
"github.com/redis/go-redis/v9/internal/maintnotifications/logs"
"github.com/redis/go-redis/v9/internal/proto"
"github.com/redis/go-redis/v9/logging"
)
var noDeadline = time.Time{}
@@ -508,7 +508,7 @@ func (cn *Conn) getEffectiveReadTimeout(normalTimeout time.Duration) time.Durati
// Deadline has passed, clear relaxed timeouts atomically and use normal timeout
newCount := cn.relaxedCounter.Add(-1)
if newCount <= 0 {
internal.Logger.Printf(context.Background(), logs.UnrelaxedTimeoutAfterDeadline(cn.GetID()))
logging.LoggerWithLevel().Infof(context.Background(), logs.UnrelaxedTimeoutAfterDeadline(cn.GetID()))
cn.clearRelaxedTimeout()
}
return normalTimeout
@@ -542,7 +542,7 @@ func (cn *Conn) getEffectiveWriteTimeout(normalTimeout time.Duration) time.Durat
// Deadline has passed, clear relaxed timeouts atomically and use normal timeout
newCount := cn.relaxedCounter.Add(-1)
if newCount <= 0 {
internal.Logger.Printf(context.Background(), logs.UnrelaxedTimeoutAfterDeadline(cn.GetID()))
logging.LoggerWithLevel().Infof(context.Background(), logs.UnrelaxedTimeoutAfterDeadline(cn.GetID()))
cn.clearRelaxedTimeout()
}
return normalTimeout

View File

@@ -122,7 +122,7 @@ type Options struct {
DialerRetryTimeout time.Duration
// Optional logger for connection pool operations.
Logger *logging.CustomLogger
Logger logging.Lgr
}
type lastDialErrorWrap struct {
@@ -1050,10 +1050,9 @@ func (p *ConnPool) isHealthyConn(cn *Conn, nowNs int64) bool {
return true
}
func (p *ConnPool) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
func (p *ConnPool) logger() logging.Lgr {
if p.cfg != nil && p.cfg.Logger != nil {
logger = p.cfg.Logger
return p.cfg.Logger
}
return logger
return logging.LoggerWithLevel()
}

View File

@@ -5,17 +5,15 @@ import (
"fmt"
)
// CustomLogger is a logger interface with leveled logging methods.
//
// This interface can be implemented by custom loggers to provide leveled logging.
type CustomLogger struct {
logger LoggerWithLevel
// LoggerWrapper is a slog.Logger wrapper that implements the Lgr interface.
type LoggerWrapper struct {
logger LoggerWithLevelI
loggerLevel *LogLevelT
printfAdapter PrintfAdapter
}
func NewCustomLogger(logger LoggerWithLevel, opts ...CustomLoggerOption) *CustomLogger {
cl := &CustomLogger{
func NewLoggerWrapper(logger LoggerWithLevelI, opts ...LoggerWrapperOption) *LoggerWrapper {
cl := &LoggerWrapper{
logger: logger,
}
for _, opt := range opts {
@@ -24,16 +22,16 @@ func NewCustomLogger(logger LoggerWithLevel, opts ...CustomLoggerOption) *Custom
return cl
}
type CustomLoggerOption func(*CustomLogger)
type LoggerWrapperOption func(*LoggerWrapper)
func WithPrintfAdapter(adapter PrintfAdapter) CustomLoggerOption {
return func(cl *CustomLogger) {
func WithPrintfAdapter(adapter PrintfAdapter) LoggerWrapperOption {
return func(cl *LoggerWrapper) {
cl.printfAdapter = adapter
}
}
func WithLoggerLevel(level LogLevelT) CustomLoggerOption {
return func(cl *CustomLogger) {
func WithLoggerLevel(level LogLevelT) LoggerWrapperOption {
return func(cl *LoggerWrapper) {
cl.loggerLevel = &level
}
}
@@ -43,7 +41,7 @@ func WithLoggerLevel(level LogLevelT) CustomLoggerOption {
type PrintfAdapter func(ctx context.Context, format string, v ...any) (context.Context, string, []any)
// Error is a structured error level logging method with context and arguments.
func (cl *CustomLogger) Error(ctx context.Context, msg string, args ...any) {
func (cl *LoggerWrapper) Error(ctx context.Context, msg string, args ...any) {
if cl == nil || cl.logger == nil {
legacyLoggerWithLevel.Errorf(ctx, msg, args...)
return
@@ -51,7 +49,7 @@ func (cl *CustomLogger) Error(ctx context.Context, msg string, args ...any) {
cl.logger.ErrorContext(ctx, msg, args...)
}
func (cl *CustomLogger) Errorf(ctx context.Context, format string, v ...any) {
func (cl *LoggerWrapper) Errorf(ctx context.Context, format string, v ...any) {
if cl == nil || cl.logger == nil {
legacyLoggerWithLevel.Errorf(ctx, format, v...)
return
@@ -60,7 +58,7 @@ func (cl *CustomLogger) Errorf(ctx context.Context, format string, v ...any) {
}
// Warn is a structured warning level logging method with context and arguments.
func (cl *CustomLogger) Warn(ctx context.Context, msg string, args ...any) {
func (cl *LoggerWrapper) Warn(ctx context.Context, msg string, args ...any) {
if cl == nil || cl.logger == nil {
legacyLoggerWithLevel.Warnf(ctx, msg, args...)
return
@@ -68,7 +66,7 @@ func (cl *CustomLogger) Warn(ctx context.Context, msg string, args ...any) {
cl.logger.WarnContext(ctx, msg, args...)
}
func (cl *CustomLogger) Warnf(ctx context.Context, format string, v ...any) {
func (cl *LoggerWrapper) Warnf(ctx context.Context, format string, v ...any) {
if cl == nil || cl.logger == nil {
legacyLoggerWithLevel.Warnf(ctx, format, v...)
return
@@ -77,7 +75,7 @@ func (cl *CustomLogger) Warnf(ctx context.Context, format string, v ...any) {
}
// Info is a structured info level logging method with context and arguments.
func (cl *CustomLogger) Info(ctx context.Context, msg string, args ...any) {
func (cl *LoggerWrapper) Info(ctx context.Context, msg string, args ...any) {
if cl == nil || cl.logger == nil {
legacyLoggerWithLevel.Infof(ctx, msg, args...)
return
@@ -86,7 +84,7 @@ func (cl *CustomLogger) Info(ctx context.Context, msg string, args ...any) {
}
// Debug is a structured debug level logging method with context and arguments.
func (cl *CustomLogger) Debug(ctx context.Context, msg string, args ...any) {
func (cl *LoggerWrapper) Debug(ctx context.Context, msg string, args ...any) {
if cl == nil || cl.logger == nil {
legacyLoggerWithLevel.Debugf(ctx, msg, args...)
return
@@ -94,7 +92,7 @@ func (cl *CustomLogger) Debug(ctx context.Context, msg string, args ...any) {
cl.logger.DebugContext(ctx, msg, args...)
}
func (cl *CustomLogger) Infof(ctx context.Context, format string, v ...any) {
func (cl *LoggerWrapper) Infof(ctx context.Context, format string, v ...any) {
if cl == nil || cl.logger == nil {
legacyLoggerWithLevel.Infof(ctx, format, v...)
return
@@ -103,7 +101,7 @@ func (cl *CustomLogger) Infof(ctx context.Context, format string, v ...any) {
cl.logger.InfoContext(cl.printfToStructured(ctx, format, v...))
}
func (cl *CustomLogger) Debugf(ctx context.Context, format string, v ...any) {
func (cl *LoggerWrapper) Debugf(ctx context.Context, format string, v ...any) {
if cl == nil || cl.logger == nil {
legacyLoggerWithLevel.Debugf(ctx, format, v...)
return
@@ -111,14 +109,14 @@ func (cl *CustomLogger) Debugf(ctx context.Context, format string, v ...any) {
cl.logger.DebugContext(cl.printfToStructured(ctx, format, v...))
}
func (cl *CustomLogger) printfToStructured(ctx context.Context, format string, v ...any) (context.Context, string, []any) {
func (cl *LoggerWrapper) printfToStructured(ctx context.Context, format string, v ...any) (context.Context, string, []any) {
if cl != nil && cl.printfAdapter != nil {
return cl.printfAdapter(ctx, format, v...)
}
return ctx, fmt.Sprintf(format, v...), nil
}
func (cl *CustomLogger) Enabled(ctx context.Context, level LogLevelT) bool {
func (cl *LoggerWrapper) Enabled(ctx context.Context, level LogLevelT) bool {
if cl != nil && cl.loggerLevel != nil {
return level >= *cl.loggerLevel
}
@@ -126,10 +124,10 @@ func (cl *CustomLogger) Enabled(ctx context.Context, level LogLevelT) bool {
return legacyLoggerWithLevel.Enabled(ctx, level)
}
// LoggerWithLevel is a logger interface with leveled logging methods.
// LoggerWithLevelI is a logger interface with leveled logging methods.
//
// [slog.Logger] from the standard library satisfies this interface.
type LoggerWithLevel interface {
type LoggerWithLevelI interface {
// InfoContext logs an info level message
InfoContext(ctx context.Context, format string, v ...any)

View File

@@ -6,11 +6,11 @@ import (
"github.com/redis/go-redis/v9/internal"
)
// legacyLoggerAdapter is a logger that implements [LoggerWithLevel] interface
// legacyLoggerAdapter is a logger that implements [LoggerWithLevelI] interface
// using the global [internal.Logger] and [internal.LogLevel] variables.
type legacyLoggerAdapter struct{}
var _ LoggerWithLevel = (*legacyLoggerAdapter)(nil)
var _ LoggerWithLevelI = (*legacyLoggerAdapter)(nil)
// structuredToPrintf converts a structured log message and key-value pairs into something a Printf-style logger can understand.
func (l *legacyLoggerAdapter) structuredToPrintf(msg string, v ...any) (string, []any) {
@@ -92,3 +92,7 @@ func (l *legacyLoggerAdapter) Enabled(ctx context.Context, level LogLevelT) bool
}
var legacyLoggerWithLevel = &legacyLoggerAdapter{}
func LoggerWithLevel() Lgr {
return legacyLoggerWithLevel
}

View File

@@ -90,3 +90,21 @@ func (l *filterLogger) Printf(ctx context.Context, format string, v ...interface
}
}
// Lgr is a logger interface with leveled logging methods.
// It is implemented by LoggerWrapper and legacyLoggerAdapter.
// If you would like to use `slog.Logger` from the standard library, you can use LoggerWrapper.
//
// logger := slog.New(slog.NewTextHandler(os.Stderr))
// db := redis.NewClient(&redis.Options{
// Logger: logging.NewLoggerWrapper(logger),
// })
//
// This will NOT handle all logging at the moment, singe there is still a global logger in use.
// that will be deprecated in the future.
type Lgr interface {
Errorf(ctx context.Context, format string, v ...any)
Warnf(ctx context.Context, format string, v ...any)
Infof(ctx context.Context, format string, v ...any)
Debugf(ctx context.Context, format string, v ...any)
Enabled(ctx context.Context, level LogLevelT) bool
}

View File

@@ -194,12 +194,11 @@ func (cb *CircuitBreaker) GetStats() CircuitBreakerStats {
}
}
func (cb *CircuitBreaker) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
func (cb *CircuitBreaker) logger() logging.Lgr {
if cb.config != nil && cb.config.Logger != nil {
logger = cb.config.Logger
return cb.config.Logger
}
return logger
return logging.LoggerWithLevel()
}
// CircuitBreakerStats provides statistics about a circuit breaker
@@ -352,10 +351,9 @@ func (cbm *CircuitBreakerManager) Reset() {
})
}
func (cbm *CircuitBreakerManager) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
func (cbm *CircuitBreakerManager) logger() logging.Lgr {
if cbm.config != nil && cbm.config.Logger != nil {
logger = cbm.config.Logger
return cbm.config.Logger
}
return logger
return logging.LoggerWithLevel()
}

View File

@@ -130,7 +130,7 @@ type Config struct {
MaxHandoffRetries int
// Logger is an optional custom logger for maintenance notifications.
Logger *logging.CustomLogger
Logger logging.Lgr
}
func (c *Config) IsEnabled() bool {
@@ -369,12 +369,11 @@ func (c *Config) applyWorkerDefaults(poolSize int) {
}
}
func (c *Config) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
func (c *Config) logger() logging.Lgr {
if c.Logger != nil {
logger = c.Logger
return c.Logger
}
return logger
return logging.LoggerWithLevel()
}
// DetectEndpointType automatically detects the appropriate endpoint type

View File

@@ -494,10 +494,9 @@ func (hwm *handoffWorkerManager) closeConnFromRequest(ctx context.Context, reque
}
}
func (hwm *handoffWorkerManager) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
func (hwm *handoffWorkerManager) logger() logging.Lgr {
if hwm.config != nil && hwm.config.Logger != nil {
logger = hwm.config.Logger
return hwm.config.Logger
}
return logger
return logging.LoggerWithLevel()
}

View File

@@ -311,10 +311,9 @@ func (hm *Manager) AddNotificationHook(notificationHook NotificationHook) {
hm.hooks = append(hm.hooks, notificationHook)
}
func (hm *Manager) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
func (hm *Manager) logger() logging.Lgr {
if hm.config != nil && hm.config.Logger != nil {
logger = hm.config.Logger
return hm.config.Logger
}
return logger
return logging.LoggerWithLevel()
}

View File

@@ -181,10 +181,9 @@ func (ph *PoolHook) Shutdown(ctx context.Context) error {
return ph.workerManager.shutdownWorkers(ctx)
}
func (ph *PoolHook) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
func (ph *PoolHook) logger() logging.Lgr {
if ph.config != nil && ph.config.Logger != nil {
logger = ph.config.Logger
return ph.config.Logger
}
return logger
return logging.LoggerWithLevel()
}

View File

@@ -274,10 +274,9 @@ func (snh *NotificationHandler) handleFailedOver(ctx context.Context, handlerCtx
return nil
}
func (snh *NotificationHandler) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
if snh.manager != nil && snh.manager.config != nil && snh.manager.config.Logger != nil {
logger = snh.manager.config.Logger
func (snh *NotificationHandler) logger() logging.Lgr {
if snh.manager != nil {
return snh.manager.logger()
}
return logger
return logging.LoggerWithLevel()
}

View File

@@ -270,8 +270,11 @@ type Options struct {
MaintNotificationsConfig *maintnotifications.Config
// Logger is the logger used by the client for logging.
// If none is provided, the global logger [internal.LegacyLoggerWithLevel] is used.
Logger *logging.CustomLogger
// If none is provided, the global logger [internal.Logger] is used.
// Keep in mind that the global logger is shared by all clients in the library, and at this time
// it is still the only logger for some internal components. This will change in the future and the global
// logger will be removed.
Logger logging.Lgr
}
func (opt *Options) init() {

View File

@@ -151,7 +151,7 @@ type ClusterOptions struct {
MaintNotificationsConfig *maintnotifications.Config
// Logger is an optional logger for logging cluster-related messages.
Logger *logging.CustomLogger
Logger logging.Lgr
}
func (opt *ClusterOptions) init() {
@@ -709,12 +709,11 @@ func (c *clusterNodes) Random() (*clusterNode, error) {
return c.GetOrCreate(addrs[n])
}
func (c *clusterNodes) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
func (c *clusterNodes) logger() logging.Lgr {
if c.opt != nil && c.opt.Logger != nil {
logger = c.opt.Logger
return c.opt.Logger
}
return logger
return logging.LoggerWithLevel()
}
//------------------------------------------------------------------------------
@@ -2140,12 +2139,11 @@ func (c *ClusterClient) context(ctx context.Context) context.Context {
return context.Background()
}
func (c *ClusterClient) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
func (c *ClusterClient) logger() logging.Lgr {
if c.opt != nil && c.opt.Logger != nil {
logger = c.opt.Logger
return c.opt.Logger
}
return logger
return logging.LoggerWithLevel()
}
func appendIfNotExist[T comparable](vals []T, newVal T) []T {

View File

@@ -145,12 +145,11 @@ func mapKeys(m map[string]struct{}) []string {
// logger is a wrapper around the logger to log messages with context.
//
// it uses the client logger if set, otherwise it uses the global logger.
func (c *PubSub) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
func (c *PubSub) logger() logging.Lgr {
if c.opt != nil && c.opt.Logger != nil {
logger = c.opt.Logger
return c.opt.Logger
}
return logger
return logging.LoggerWithLevel()
}
func (c *PubSub) _subscribe(
@@ -647,7 +646,7 @@ type channel struct {
pubSub *PubSub
// Optional logger for logging channel-related messages.
Logger *logging.CustomLogger
Logger logging.Lgr
msgCh chan *Message
allCh chan interface{}
@@ -810,10 +809,9 @@ func (c *channel) initAllChan() {
}()
}
func (c *channel) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
func (c *channel) logger() logging.Lgr {
if c.Logger != nil {
logger = c.Logger
return c.Logger
}
return logger
return logging.LoggerWithLevel()
}

View File

@@ -229,9 +229,6 @@ type baseClient struct {
// streamingCredentialsManager is used to manage streaming credentials
streamingCredentialsManager *streaming.Manager
// loggerWithLevel is used for logging
loggerWithLevel *logging.CustomLogger
}
func (c *baseClient) clone() *baseClient {
@@ -246,7 +243,6 @@ func (c *baseClient) clone() *baseClient {
pushProcessor: c.pushProcessor,
maintNotificationsManager: maintNotificationsManager,
streamingCredentialsManager: c.streamingCredentialsManager,
loggerWithLevel: c.loggerWithLevel,
}
return clone
}
@@ -755,12 +751,11 @@ func (c *baseClient) context(ctx context.Context) context.Context {
// logger is a wrapper around the logger to log messages with context.
// it uses the client logger if set, otherwise it uses the global logger.
func (c *baseClient) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
func (c *baseClient) logger() logging.Lgr {
if c.opt != nil && c.opt.Logger != nil {
logger = c.opt.Logger
return c.opt.Logger
}
return logger
return logging.LoggerWithLevel()
}
// createInitConnFunc creates a connection initialization function that can be used for reconnections.

View File

@@ -156,7 +156,7 @@ type RingOptions struct {
IdentitySuffix string
UnstableResp3 bool
Logger *logging.CustomLogger
Logger logging.Lgr
}
func (opt *RingOptions) init() {
@@ -562,12 +562,11 @@ func (c *ringSharding) Close() error {
return firstErr
}
func (c *ringSharding) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
func (c *ringSharding) logger() logging.Lgr {
if c.opt != nil && c.opt.Logger != nil {
logger = c.opt.Logger
return c.opt.Logger
}
return logger
return logging.LoggerWithLevel()
}
//------------------------------------------------------------------------------

View File

@@ -151,7 +151,7 @@ type FailoverOptions struct {
//MaintNotificationsConfig *maintnotifications.Config
// Optional logger for logging
Logger *logging.CustomLogger
Logger logging.Lgr
}
func (opt *FailoverOptions) clientOptions() *Options {
@@ -1132,12 +1132,11 @@ func (c *sentinelFailover) listen(pubsub *PubSub) {
}
}
func (c *sentinelFailover) logger() *logging.CustomLogger {
var logger *logging.CustomLogger
func (c *sentinelFailover) logger() logging.Lgr {
if c.opt != nil && c.opt.Logger != nil {
logger = c.opt.Logger
return c.opt.Logger
}
return logger
return logging.LoggerWithLevel()
}
func contains(slice []string, str string) bool {