@@ -119,6 +119,9 @@ type Options struct {
119119 // DialerRetryTimeout is the backoff duration between retry attempts.
120120 // Default: 100ms
121121 DialerRetryTimeout time.Duration
122+
123+ // Optional logger for connection pool operations.
124+ Logger internal.LoggerWithLevel
122125}
123126
124127type lastDialErrorWrap struct {
@@ -247,7 +250,7 @@ func (p *ConnPool) checkMinIdleConns() {
247250 p .idleConnsLen .Add (- 1 )
248251
249252 p .freeTurn ()
250- internal . Logger . Printf (context .Background (), "addIdleConn panic: %+v" , err )
253+ p . logger (). Errorf (context .Background (), "addIdleConn panic: %+v" , err )
251254 }
252255 }()
253256
@@ -400,7 +403,7 @@ func (p *ConnPool) dialConn(ctx context.Context, pooled bool) (*Conn, error) {
400403 return cn , nil
401404 }
402405
403- internal . Logger . Printf (ctx , "redis: connection pool: failed to dial after %d attempts: %v" , attempt , lastErr )
406+ p . logger (). Errorf (ctx , "redis: connection pool: failed to dial after %d attempts: %v" , attempt , lastErr )
404407 // All retries failed - handle error tracking
405408 p .setLastDialError (lastErr )
406409 if atomic .AddUint32 (& p .dialErrorsNum , 1 ) == uint32 (p .cfg .PoolSize ) {
@@ -494,10 +497,10 @@ func (p *ConnPool) getConn(ctx context.Context) (*Conn, error) {
494497 acceptConn , err := hookManager .ProcessOnGet (ctx , cn , false )
495498 if err != nil || ! acceptConn {
496499 if err != nil {
497- internal . Logger . Printf (ctx , "redis: connection pool: failed to process idle connection by hook: %v" , err )
500+ p . logger (). Errorf (ctx , "redis: connection pool: failed to process idle connection by hook: %v" , err )
498501 _ = p .CloseConn (cn )
499502 } else {
500- internal . Logger . Printf (ctx , "redis: connection pool: conn[%d] rejected by hook, returning to pool" , cn .GetID ())
503+ p . logger (). Errorf (ctx , "redis: connection pool: conn[%d] rejected by hook, returning to pool" , cn .GetID ())
501504 // Return connection to pool without freeing the turn that this Get() call holds.
502505 // We use putConnWithoutTurn() to run all the Put hooks and logic without freeing a turn.
503506 p .putConnWithoutTurn (ctx , cn )
@@ -525,7 +528,7 @@ func (p *ConnPool) getConn(ctx context.Context) (*Conn, error) {
525528 // this should not happen with a new connection, but we handle it gracefully
526529 if err != nil || ! acceptConn {
527530 // Failed to process connection, discard it
528- internal . Logger . Printf (ctx , "redis: connection pool: failed to process new connection conn[%d] by hook: accept=%v, err=%v" , newcn .GetID (), acceptConn , err )
531+ p . logger (). Errorf (ctx , "redis: connection pool: failed to process new connection conn[%d] by hook: accept=%v, err=%v" , newcn .GetID (), acceptConn , err )
529532 _ = p .CloseConn (newcn )
530533 return nil , err
531534 }
@@ -568,7 +571,7 @@ func (p *ConnPool) queuedNewConn(ctx context.Context) (*Conn, error) {
568571 if ! freeTurnCalled {
569572 p .freeTurn ()
570573 }
571- internal . Logger . Printf ( context . Background () , "queuedNewConn panic: %+v" , err )
574+ p . logger (). Errorf ( ctx , "queuedNewConn panic: %+v" , err )
572575 }
573576 }()
574577
@@ -712,7 +715,7 @@ func (p *ConnPool) popIdle() (*Conn, error) {
712715
713716 // If we exhausted all attempts without finding a usable connection, return nil
714717 if attempts > 1 && attempts >= maxAttempts && int32 (attempts ) >= p .poolSize .Load () {
715- internal . Logger . Printf (context .Background (), "redis: connection pool: failed to get a usable connection after %d attempts" , attempts )
718+ p . logger (). Errorf (context .Background (), "redis: connection pool: failed to get a usable connection after %d attempts" , attempts )
716719 return nil , nil
717720 }
718721
@@ -741,7 +744,7 @@ func (p *ConnPool) putConn(ctx context.Context, cn *Conn, freeTurn bool) {
741744 // Peek at the reply type to check if it's a push notification
742745 if replyType , err := cn .PeekReplyTypeSafe (); err != nil || replyType != proto .RespPush {
743746 // Not a push notification or error peeking, remove connection
744- internal . Logger . Printf (ctx , "Conn has unread data (not push notification), removing it" )
747+ p . logger (). Errorf (ctx , "Conn has unread data (not push notification), removing it" )
745748 p .removeConnInternal (ctx , cn , err , freeTurn )
746749 return
747750 }
@@ -754,7 +757,7 @@ func (p *ConnPool) putConn(ctx context.Context, cn *Conn, freeTurn bool) {
754757 if hookManager != nil {
755758 shouldPool , shouldRemove , err = hookManager .ProcessOnPut (ctx , cn )
756759 if err != nil {
757- internal . Logger . Printf (ctx , "Connection hook error: %v" , err )
760+ p . logger (). Errorf (ctx , "Connection hook error: %v" , err )
758761 p .removeConnInternal (ctx , cn , err , freeTurn )
759762 return
760763 }
@@ -787,12 +790,12 @@ func (p *ConnPool) putConn(ctx context.Context, cn *Conn, freeTurn bool) {
787790 case StateUnusable :
788791 // expected state, don't log it
789792 case StateClosed :
790- internal . Logger . Printf (ctx , "Unexpected conn[%d] state changed by hook to %v, closing it" , cn .GetID (), currentState )
793+ p . logger (). Errorf (ctx , "Unexpected conn[%d] state changed by hook to %v, closing it" , cn .GetID (), currentState )
791794 shouldCloseConn = true
792795 p .removeConnWithLock (cn )
793796 default :
794797 // Pool as-is
795- internal . Logger . Printf (ctx , "Unexpected conn[%d] state changed by hook to %v, pooling as-is" , cn .GetID (), currentState )
798+ p . logger (). Warnf (ctx , "Unexpected conn[%d] state changed by hook to %v, pooling as-is" , cn .GetID (), currentState )
796799 }
797800 }
798801
@@ -887,6 +890,7 @@ func (p *ConnPool) removeConn(cn *Conn) {
887890 // this can be idle conn
888891 for idx , ic := range p .idleConns {
889892 if ic == cn {
893+ p .logger ().Infof (context .Background (), "redis: connection pool: removing idle conn[%d]" , cid )
890894 p .idleConns = append (p .idleConns [:idx ], p .idleConns [idx + 1 :]... )
891895 p .idleConnsLen .Add (- 1 )
892896 break
@@ -1009,7 +1013,7 @@ func (p *ConnPool) isHealthyConn(cn *Conn, nowNs int64) bool {
10091013 if replyType , err := cn .rd .PeekReplyType (); err == nil && replyType == proto .RespPush {
10101014 // For RESP3 connections with push notifications, we allow some buffered data
10111015 // The client will process these notifications before using the connection
1012- internal . Logger . Printf (
1016+ p . logger (). Infof (
10131017 context .Background (),
10141018 "push: conn[%d] has buffered data, likely push notifications - will be processed by client" ,
10151019 cn .GetID (),
@@ -1032,3 +1036,11 @@ func (p *ConnPool) isHealthyConn(cn *Conn, nowNs int64) bool {
10321036 cn .SetUsedAtNs (nowNs )
10331037 return true
10341038}
1039+
1040+ func (p * ConnPool ) logger () internal.LoggerWithLevel {
1041+ if p .cfg .Logger != nil {
1042+ return p .cfg .Logger
1043+ }
1044+
1045+ return internal .LegacyLoggerWithLevel
1046+ }
0 commit comments