Skip to content

Commit 1ab25f2

Browse files
committed
cleanup the logging a bit
1 parent 74164a4 commit 1ab25f2

File tree

11 files changed

+121
-88
lines changed

11 files changed

+121
-88
lines changed

async_handoff_integration_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/redis/go-redis/v9/hitless"
1111
"github.com/redis/go-redis/v9/internal/pool"
12+
"github.com/redis/go-redis/v9/logging"
1213
)
1314

1415
// mockNetConn implements net.Conn for testing
@@ -348,5 +349,5 @@ func TestEventDrivenHandoffIntegration(t *testing.T) {
348349
}
349350

350351
func init() {
351-
SetLogger(&VoidLogger{})
352+
logging.Disable()
352353
}

hitless/config.go

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,6 @@ import (
1212
"github.com/redis/go-redis/v9/logging"
1313
)
1414

15-
// LogLevel represents the logging level for hitless upgrades
16-
type LogLevel = logging.LogLevel
17-
18-
// Log level constants for hitless upgrades
19-
const (
20-
LogLevelError LogLevel = logging.LogLevelError // 0 - errors only
21-
LogLevelWarn LogLevel = logging.LogLevelWarn // 1 - warnings and errors
22-
LogLevelInfo LogLevel = logging.LogLevelInfo // 2 - info, warnings, and errors
23-
LogLevelDebug LogLevel = logging.LogLevelDebug // 3 - debug, info, warnings, and errors
24-
)
25-
2615
// MaintNotificationsMode represents the maintenance notifications mode
2716
type MaintNotificationsMode string
2817

@@ -124,8 +113,8 @@ type Config struct {
124113

125114
// LogLevel controls the verbosity of hitless upgrade logging.
126115
// LogLevelError (0) = errors only, LogLevelWarn (1) = warnings, LogLevelInfo (2) = info, LogLevelDebug (3) = debug
127-
// Default: LogLevelError(0)
128-
LogLevel LogLevel
116+
// Default: logging.LogLevelError(0)
117+
LogLevel logging.LogLevel
129118

130119
// MaxHandoffRetries is the maximum number of times to retry a failed handoff.
131120
// After this many retries, the connection will be removed from the pool.
@@ -291,7 +280,7 @@ func (c *Config) ApplyDefaultsWithPoolConfig(poolSize int, maxActiveConns int) *
291280
result.MaxHandoffRetries = c.MaxHandoffRetries
292281
}
293282

294-
if result.LogLevel >= LogLevelDebug {
283+
if result.LogLevel.DebugOrAbove() {
295284
internal.Logger.Printf(context.Background(), "hitless: debug logging enabled")
296285
internal.Logger.Printf(context.Background(), "hitless: config: %+v", result)
297286
}

hitless/hitless_manager.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,12 @@ func (hm *HitlessManager) TrackMovingOperationWithConnID(ctx context.Context, ne
148148
// Use LoadOrStore for atomic check-and-set operation
149149
if _, loaded := hm.activeMovingOps.LoadOrStore(key, movingOp); loaded {
150150
// Duplicate MOVING notification, ignore
151-
if hm.config.LogLevel >= LogLevelDebug { // Debug level
151+
if hm.config.LogLevel.DebugOrAbove() { // Debug level
152152
internal.Logger.Printf(context.Background(), "hitless: conn[%d] seqID[%d] Duplicate MOVING operation ignored: %s", connID, seqID, key.String())
153153
}
154154
return nil
155155
}
156-
if hm.config.LogLevel >= LogLevelDebug { // Debug level
156+
if hm.config.LogLevel.DebugOrAbove() { // Debug level
157157
internal.Logger.Printf(context.Background(), "hitless: conn[%d] seqID[%d] Tracking MOVING operation: %s", connID, seqID, key.String())
158158
}
159159

@@ -173,13 +173,13 @@ func (hm *HitlessManager) UntrackOperationWithConnID(seqID int64, connID uint64)
173173

174174
// Remove from active operations atomically
175175
if _, loaded := hm.activeMovingOps.LoadAndDelete(key); loaded {
176-
if hm.config.LogLevel >= LogLevelDebug { // Debug level
176+
if hm.config.LogLevel.DebugOrAbove() { // Debug level
177177
internal.Logger.Printf(context.Background(), "hitless: conn[%d] seqID[%d] Untracking MOVING operation: %s", connID, seqID, key.String())
178178
}
179179
// Decrement active operation count only if operation existed
180180
hm.activeOperationCount.Add(-1)
181181
} else {
182-
if hm.config.LogLevel >= LogLevelDebug { // Debug level
182+
if hm.config.LogLevel.DebugOrAbove() { // Debug level
183183
internal.Logger.Printf(context.Background(), "hitless: conn[%d] seqID[%d] Operation not found for untracking: %s", connID, seqID, key.String())
184184
}
185185
}

hitless/hooks.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type LoggingHook struct {
1616

1717
// PreHook logs the notification before processing and allows modification.
1818
func (lh *LoggingHook) PreHook(ctx context.Context, notificationCtx push.NotificationHandlerContext, notificationType string, notification []interface{}) ([]interface{}, bool) {
19-
if lh.LogLevel >= logging.LogLevelInfo { // Info level
19+
if lh.LogLevel.InfoOrAbove() { // Info level
2020
// Log the notification type and content
2121
connID := uint64(0)
2222
if conn, ok := notificationCtx.Conn.(*pool.Conn); ok {
@@ -33,9 +33,9 @@ func (lh *LoggingHook) PostHook(ctx context.Context, notificationCtx push.Notifi
3333
if conn, ok := notificationCtx.Conn.(*pool.Conn); ok {
3434
connID = conn.GetID()
3535
}
36-
if result != nil && lh.LogLevel >= logging.LogLevelWarn { // Warning level
36+
if result != nil && lh.LogLevel.WarnOrAbove() { // Warning level
3737
internal.Logger.Printf(ctx, "hitless: conn[%d] %s notification processing failed: %v - %v", connID, notificationType, result, notification)
38-
} else if lh.LogLevel >= logging.LogLevelDebug { // Debug level
38+
} else if lh.LogLevel.DebugOrAbove() { // Debug level
3939
internal.Logger.Printf(ctx, "hitless: conn[%d] %s notification processed successfully", connID, notificationType)
4040
}
4141
}

hitless/pool_hook.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ func (ph *PoolHook) onDemandWorker() {
207207
return
208208
case <-time.After(ph.workerTimeout):
209209
// Worker has been idle for too long, exit to save resources
210-
if ph.config != nil && ph.config.LogLevel >= LogLevelDebug { // Debug level
210+
if ph.config != nil && ph.config.LogLevel.InfoOrAbove() { // Debug level
211211
internal.Logger.Printf(context.Background(),
212212
"hitless: worker exiting due to inactivity timeout (%v)", ph.workerTimeout)
213213
}
@@ -302,14 +302,14 @@ func (ph *PoolHook) closeConnFromRequest(ctx context.Context, request HandoffReq
302302
conn := request.Conn
303303
if pooler != nil {
304304
pooler.Remove(ctx, conn, err)
305-
if ph.config != nil && ph.config.LogLevel >= LogLevelWarn { // Warning level
305+
if ph.config != nil && ph.config.LogLevel.WarnOrAbove() { // Warning level
306306
internal.Logger.Printf(ctx,
307307
"hitless: removed conn[%d] from pool due to max handoff retries reached: %v",
308308
conn.GetID(), err)
309309
}
310310
} else {
311311
conn.Close()
312-
if ph.config != nil && ph.config.LogLevel >= LogLevelWarn { // Warning level
312+
if ph.config != nil && ph.config.LogLevel.WarnOrAbove() { // Warning level
313313
internal.Logger.Printf(ctx,
314314
"hitless: no pool provided for conn[%d], cannot remove due to handoff initialization failure: %v",
315315
conn.GetID(), err)
@@ -357,11 +357,11 @@ func (ph *PoolHook) queueHandoff(conn *pool.Conn) error {
357357
// Queue is full - log and attempt scaling
358358
queueLen := len(ph.handoffQueue)
359359
queueCap := cap(ph.handoffQueue)
360-
if ph.config != nil && ph.config.LogLevel >= LogLevelWarn { // Warning level
360+
if ph.config != nil && ph.config.LogLevel.WarnOrAbove() { // Warning level
361361
internal.Logger.Printf(context.Background(),
362362
"hitless: handoff queue is full (%d/%d), cant queue handoff request for conn[%d] seqID[%d]",
363363
queueLen, queueCap, request.ConnID, request.SeqID)
364-
if ph.config.LogLevel >= LogLevelDebug { // Debug level
364+
if ph.config.LogLevel.DebugOrAbove() { // Debug level
365365
ph.pending.Range(func(k, v interface{}) bool {
366366
internal.Logger.Printf(context.Background(), "hitless: pending handoff for conn[%d] seqID[%d]", k, v)
367367
return true
@@ -396,7 +396,7 @@ func (ph *PoolHook) performConnectionHandoff(ctx context.Context, conn *pool.Con
396396
}
397397

398398
if retries > maxRetries {
399-
if ph.config != nil && ph.config.LogLevel >= LogLevelWarn { // Warning level
399+
if ph.config != nil && ph.config.LogLevel.WarnOrAbove() { // Warning level
400400
internal.Logger.Printf(ctx,
401401
"hitless: reached max retries (%d) for handoff of conn[%d] to %s",
402402
maxRetries, conn.GetID(), conn.GetHandoffEndpoint())
@@ -430,7 +430,7 @@ func (ph *PoolHook) performConnectionHandoff(ctx context.Context, conn *pool.Con
430430
deadline := time.Now().Add(ph.config.PostHandoffRelaxedDuration)
431431
conn.SetRelaxedTimeoutWithDeadline(relaxedTimeout, relaxedTimeout, deadline)
432432

433-
if ph.config.LogLevel >= 2 { // Info level
433+
if ph.config.LogLevel.InfoOrAbove() {
434434
internal.Logger.Printf(context.Background(),
435435
"hitless: conn[%d] applied post-handoff relaxed timeout (%v) until %v",
436436
connID, relaxedTimeout, deadline.Format("15:04:05.000"))

hitless/push_notification_handler.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func (snh *NotificationHandler) handleMoving(ctx context.Context, handlerCtx pus
115115
deadline := time.Now().Add(time.Duration(timeS) * time.Second)
116116
// If newEndpoint is empty, we should schedule a handoff to the current endpoint in timeS/2 seconds
117117
if newEndpoint == "" || newEndpoint == internal.RedisNull {
118-
if snh.manager.config.LogLevel >= LogLevelDebug { // Debug level
118+
if snh.manager.config.LogLevel.DebugOrAbove() { // Debug level
119119
internal.Logger.Printf(ctx, "hitless: conn[%d] scheduling handoff to current endpoint in %v seconds",
120120
poolConn.GetID(), timeS/2)
121121
}
@@ -179,7 +179,7 @@ func (snh *NotificationHandler) handleMigrating(ctx context.Context, handlerCtx
179179
}
180180

181181
// Apply relaxed timeout to this specific connection
182-
if snh.manager.config.LogLevel >= LogLevelDebug { // Debug level
182+
if snh.manager.config.LogLevel.InfoOrAbove() { // Debug level
183183
internal.Logger.Printf(ctx, "hitless: conn[%d] applying relaxed timeout (%v) for MIGRATING notification",
184184
conn.GetID(),
185185
snh.manager.config.RelaxedTimeout)
@@ -209,7 +209,7 @@ func (snh *NotificationHandler) handleMigrated(ctx context.Context, handlerCtx p
209209
}
210210

211211
// Clear relaxed timeout for this specific connection
212-
if snh.manager.config.LogLevel >= LogLevelDebug { // Debug level
212+
if snh.manager.config.LogLevel.InfoOrAbove() { // Debug level
213213
connID := conn.GetID()
214214
internal.Logger.Printf(ctx, "hitless: conn[%d] clearing relaxed timeout for MIGRATED notification", connID)
215215
}
@@ -238,7 +238,7 @@ func (snh *NotificationHandler) handleFailingOver(ctx context.Context, handlerCt
238238
}
239239

240240
// Apply relaxed timeout to this specific connection
241-
if snh.manager.config.LogLevel >= LogLevelDebug { // Debug level
241+
if snh.manager.config.LogLevel.InfoOrAbove() { // Debug level
242242
connID := conn.GetID()
243243
internal.Logger.Printf(ctx, "hitless: conn[%d] applying relaxed timeout (%v) for FAILING_OVER notification", connID, snh.manager.config.RelaxedTimeout)
244244
}
@@ -267,7 +267,7 @@ func (snh *NotificationHandler) handleFailedOver(ctx context.Context, handlerCtx
267267
}
268268

269269
// Clear relaxed timeout for this specific connection
270-
if snh.manager.config.LogLevel >= LogLevelDebug { // Debug level
270+
if snh.manager.config.LogLevel.InfoOrAbove() { // Debug level
271271
connID := conn.GetID()
272272
internal.Logger.Printf(ctx, "hitless: conn[%d] clearing relaxed timeout for FAILED_OVER notification", connID)
273273
}

internal/log.go

Lines changed: 7 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,6 @@ import (
55
"fmt"
66
"log"
77
"os"
8-
"strings"
9-
10-
"github.com/redis/go-redis/v9/logging"
11-
)
12-
13-
// LogLevel is an alias to the public logging.LogLevel for internal use
14-
type LogLevel = logging.LogLevel
15-
16-
// Log level constants for internal use
17-
const (
18-
LogLevelError = logging.LogLevelError
19-
LogLevelWarn = logging.LogLevelWarn
20-
LogLevelInfo = logging.LogLevelInfo
21-
LogLevelDebug = logging.LogLevelDebug
228
)
239

2410
// TODO (ned): Revisit logging
@@ -28,41 +14,20 @@ type Logging interface {
2814
Printf(ctx context.Context, format string, v ...interface{})
2915
}
3016

31-
type logger struct {
17+
type DefaultLogger struct {
3218
log *log.Logger
3319
}
3420

35-
func (l *logger) Printf(ctx context.Context, format string, v ...interface{}) {
21+
func (l *DefaultLogger) Printf(ctx context.Context, format string, v ...interface{}) {
3622
_ = l.log.Output(2, fmt.Sprintf(format, v...))
3723
}
3824

39-
// Logger calls Output to print to the stderr.
40-
// Arguments are handled in the manner of fmt.Print.
41-
var Logger Logging = &logger{
42-
log: log.New(os.Stderr, "redis: ", log.LstdFlags|log.Lshortfile),
43-
}
44-
45-
func NewFilterLogger(substr []string) Logging {
46-
l := &logger{
25+
func NewDefaultLogger() Logging {
26+
return &DefaultLogger{
4727
log: log.New(os.Stderr, "redis: ", log.LstdFlags|log.Lshortfile),
4828
}
49-
return &filterLogger{logger: l, substr: substr}
5029
}
5130

52-
type filterLogger struct {
53-
logger Logging
54-
substr []string
55-
}
56-
57-
func (l *filterLogger) Printf(ctx context.Context, format string, v ...interface{}) {
58-
msg := fmt.Sprintf(format, v...)
59-
for _, substr := range l.substr {
60-
if strings.Contains(msg, substr) {
61-
return
62-
}
63-
}
64-
if l.logger != nil {
65-
l.logger.Printf(ctx, format, v...)
66-
return
67-
}
68-
}
31+
// Logger calls Output to print to the stderr.
32+
// Arguments are handled in the manner of fmt.Print.
33+
var Logger Logging = NewDefaultLogger()

internal/pool/pool_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
. "github.com/bsm/gomega"
1313
"github.com/redis/go-redis/v9"
1414
"github.com/redis/go-redis/v9/internal/pool"
15+
"github.com/redis/go-redis/v9/logging"
1516
)
1617

1718
var _ = Describe("ConnPool", func() {
@@ -438,5 +439,5 @@ var _ = Describe("race", func() {
438439
})
439440

440441
func init() {
441-
redis.SetLogger(&redis.VoidLogger{})
442+
logging.Disable()
442443
}

logging/logging.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
// This package centralizes logging configuration to ensure consistency across all components.
33
package logging
44

5+
import (
6+
"context"
7+
"fmt"
8+
"strings"
9+
10+
"github.com/redis/go-redis/v9/internal"
11+
)
12+
513
// LogLevel represents the logging level
614
type LogLevel int
715

@@ -33,3 +41,81 @@ func (l LogLevel) String() string {
3341
func (l LogLevel) IsValid() bool {
3442
return l >= LogLevelError && l <= LogLevelDebug
3543
}
44+
45+
func (l LogLevel) WarnOrAbove() bool {
46+
return l >= LogLevelWarn
47+
}
48+
49+
func (l LogLevel) InfoOrAbove() bool {
50+
return l >= LogLevelInfo
51+
}
52+
53+
func (l LogLevel) DebugOrAbove() bool {
54+
return l >= LogLevelDebug
55+
}
56+
57+
// VoidLogger is a logger that does nothing.
58+
// Used to disable logging and thus speed up the library.
59+
type VoidLogger struct{}
60+
61+
func (v *VoidLogger) Printf(_ context.Context, _ string, _ ...interface{}) {
62+
// do nothing
63+
}
64+
65+
// Disable disables logging by setting the internal logger to a void logger.
66+
// This can be used to speed up the library if logging is not needed.
67+
// It will override any custom logger that was set before and set the VoidLogger.
68+
func Disable() {
69+
internal.Logger = &VoidLogger{}
70+
}
71+
72+
// Enable enables logging by setting the internal logger to the default logger.
73+
// This is the default behavior.
74+
// You can use redis.SetLogger to set a custom logger.
75+
//
76+
// NOTE: This function is not thread-safe.
77+
// It will override any custom logger that was set before and set the DefaultLogger.
78+
func Enable() {
79+
internal.Logger = internal.NewDefaultLogger()
80+
}
81+
82+
// NewBlacklistLogger returns a new logger that filters out messages containing any of the substrings.
83+
// This can be used to filter out messages containing sensitive information.
84+
func NewBlacklistLogger(substr []string) internal.Logging {
85+
l := internal.NewDefaultLogger()
86+
return &filterLogger{logger: l, substr: substr, blacklist: true}
87+
}
88+
89+
// NewWhitelistLogger returns a new logger that only logs messages containing any of the substrings.
90+
// This can be used to only log messages related to specific commands or patterns.
91+
func NewWhitelistLogger(substr []string) internal.Logging {
92+
l := internal.NewDefaultLogger()
93+
return &filterLogger{logger: l, substr: substr, blacklist: false}
94+
}
95+
96+
type filterLogger struct {
97+
logger internal.Logging
98+
blacklist bool
99+
substr []string
100+
}
101+
102+
func (l *filterLogger) Printf(ctx context.Context, format string, v ...interface{}) {
103+
msg := fmt.Sprintf(format, v...)
104+
found := false
105+
for _, substr := range l.substr {
106+
if strings.Contains(msg, substr) {
107+
found = true
108+
if l.blacklist {
109+
return
110+
}
111+
}
112+
}
113+
// whitelist, only log if one of the substrings is present
114+
if !l.blacklist && !found {
115+
return
116+
}
117+
if l.logger != nil {
118+
l.logger.Printf(ctx, format, v...)
119+
return
120+
}
121+
}

0 commit comments

Comments
 (0)