Skip to content

Commit 5a34ede

Browse files
authored
Merge branch 'master' into norm-credential-provider
2 parents 37f58ab + fa475cb commit 5a34ede

File tree

8 files changed

+211
-62
lines changed

8 files changed

+211
-62
lines changed

command.go

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,55 @@ import (
1717
"github.com/redis/go-redis/v9/internal/util"
1818
)
1919

20+
// keylessCommands contains Redis commands that have empty key specifications (9th slot empty)
21+
// Only includes core Redis commands, excludes FT.*, ts.*, timeseries.*, search.* and subcommands
22+
var keylessCommands = map[string]struct{}{
23+
"acl": {},
24+
"asking": {},
25+
"auth": {},
26+
"bgrewriteaof": {},
27+
"bgsave": {},
28+
"client": {},
29+
"cluster": {},
30+
"config": {},
31+
"debug": {},
32+
"discard": {},
33+
"echo": {},
34+
"exec": {},
35+
"failover": {},
36+
"function": {},
37+
"hello": {},
38+
"latency": {},
39+
"lolwut": {},
40+
"module": {},
41+
"monitor": {},
42+
"multi": {},
43+
"pfselftest": {},
44+
"ping": {},
45+
"psubscribe": {},
46+
"psync": {},
47+
"publish": {},
48+
"pubsub": {},
49+
"punsubscribe": {},
50+
"quit": {},
51+
"readonly": {},
52+
"readwrite": {},
53+
"replconf": {},
54+
"replicaof": {},
55+
"role": {},
56+
"save": {},
57+
"script": {},
58+
"select": {},
59+
"shutdown": {},
60+
"slaveof": {},
61+
"slowlog": {},
62+
"subscribe": {},
63+
"swapdb": {},
64+
"sync": {},
65+
"unsubscribe": {},
66+
"unwatch": {},
67+
}
68+
2069
type Cmder interface {
2170
// command name.
2271
// e.g. "set k v ex 10" -> "set", "cluster info" -> "cluster".
@@ -75,12 +124,22 @@ func writeCmd(wr *proto.Writer, cmd Cmder) error {
75124
return wr.WriteArgs(cmd.Args())
76125
}
77126

127+
// cmdFirstKeyPos returns the position of the first key in the command's arguments.
128+
// If the command does not have a key, it returns 0.
129+
// TODO: Use the data in CommandInfo to determine the first key position.
78130
func cmdFirstKeyPos(cmd Cmder) int {
79131
if pos := cmd.firstKeyPos(); pos != 0 {
80132
return int(pos)
81133
}
82134

83-
switch cmd.Name() {
135+
name := cmd.Name()
136+
137+
// first check if the command is keyless
138+
if _, ok := keylessCommands[name]; ok {
139+
return 0
140+
}
141+
142+
switch name {
84143
case "eval", "evalsha", "eval_ro", "evalsha_ro":
85144
if cmd.stringArg(2) != "0" {
86145
return 3

extra/redisotel/config.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type config struct {
2020
tracer trace.Tracer
2121

2222
dbStmtEnabled bool
23+
callerEnabled bool
2324

2425
// Metrics options.
2526

@@ -57,6 +58,7 @@ func newConfig(opts ...baseOption) *config {
5758
tp: otel.GetTracerProvider(),
5859
mp: otel.GetMeterProvider(),
5960
dbStmtEnabled: true,
61+
callerEnabled: true,
6062
}
6163

6264
for _, opt := range opts {
@@ -106,13 +108,20 @@ func WithTracerProvider(provider trace.TracerProvider) TracingOption {
106108
})
107109
}
108110

109-
// WithDBStatement tells the tracing hook not to log raw redis commands.
111+
// WithDBStatement tells the tracing hook to log raw redis commands.
110112
func WithDBStatement(on bool) TracingOption {
111113
return tracingOption(func(conf *config) {
112114
conf.dbStmtEnabled = on
113115
})
114116
}
115117

118+
// WithCallerEnabled tells the tracing hook to log the calling function, file and line.
119+
func WithCallerEnabled(on bool) TracingOption {
120+
return tracingOption(func(conf *config) {
121+
conf.callerEnabled = on
122+
})
123+
}
124+
116125
//------------------------------------------------------------------------------
117126

118127
type MetricsOption interface {

extra/redisotel/tracing.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,16 @@ func (th *tracingHook) DialHook(hook redis.DialHook) redis.DialHook {
101101

102102
func (th *tracingHook) ProcessHook(hook redis.ProcessHook) redis.ProcessHook {
103103
return func(ctx context.Context, cmd redis.Cmder) error {
104-
fn, file, line := funcFileLine("github.com/redis/go-redis")
105104

106105
attrs := make([]attribute.KeyValue, 0, 8)
107-
attrs = append(attrs,
108-
semconv.CodeFunction(fn),
109-
semconv.CodeFilepath(file),
110-
semconv.CodeLineNumber(line),
111-
)
106+
if th.conf.callerEnabled {
107+
fn, file, line := funcFileLine("github.com/redis/go-redis")
108+
attrs = append(attrs,
109+
semconv.CodeFunction(fn),
110+
semconv.CodeFilepath(file),
111+
semconv.CodeLineNumber(line),
112+
)
113+
}
112114

113115
if th.conf.dbStmtEnabled {
114116
cmdString := rediscmd.CmdString(cmd)
@@ -133,16 +135,20 @@ func (th *tracingHook) ProcessPipelineHook(
133135
hook redis.ProcessPipelineHook,
134136
) redis.ProcessPipelineHook {
135137
return func(ctx context.Context, cmds []redis.Cmder) error {
136-
fn, file, line := funcFileLine("github.com/redis/go-redis")
137-
138138
attrs := make([]attribute.KeyValue, 0, 8)
139139
attrs = append(attrs,
140-
semconv.CodeFunction(fn),
141-
semconv.CodeFilepath(file),
142-
semconv.CodeLineNumber(line),
143140
attribute.Int("db.redis.num_cmd", len(cmds)),
144141
)
145142

143+
if th.conf.callerEnabled {
144+
fn, file, line := funcFileLine("github.com/redis/go-redis")
145+
attrs = append(attrs,
146+
semconv.CodeFunction(fn),
147+
semconv.CodeFilepath(file),
148+
semconv.CodeLineNumber(line),
149+
)
150+
}
151+
146152
summary, cmdsString := rediscmd.CmdsString(cmds)
147153
if th.conf.dbStmtEnabled {
148154
attrs = append(attrs, semconv.DBStatement(cmdsString))

extra/redisotel/tracing_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,35 @@ func TestWithDBStatement(t *testing.T) {
6666
}
6767
}
6868

69+
func TestWithoutCaller(t *testing.T) {
70+
provider := sdktrace.NewTracerProvider()
71+
hook := newTracingHook(
72+
"",
73+
WithTracerProvider(provider),
74+
WithCallerEnabled(false),
75+
)
76+
ctx, span := provider.Tracer("redis-test").Start(context.TODO(), "redis-test")
77+
cmd := redis.NewCmd(ctx, "ping")
78+
defer span.End()
79+
80+
processHook := hook.ProcessHook(func(ctx context.Context, cmd redis.Cmder) error {
81+
attrs := trace.SpanFromContext(ctx).(sdktrace.ReadOnlySpan).Attributes()
82+
for _, attr := range attrs {
83+
switch attr.Key {
84+
case semconv.CodeFunctionKey,
85+
semconv.CodeFilepathKey,
86+
semconv.CodeLineNumberKey:
87+
t.Fatalf("Attribute with %s statement should not exist", attr.Key)
88+
}
89+
}
90+
return nil
91+
})
92+
err := processHook(ctx, cmd)
93+
if err != nil {
94+
t.Fatal(err)
95+
}
96+
}
97+
6998
func TestTracingHook_DialHook(t *testing.T) {
7099
imsb := tracetest.NewInMemoryExporter()
71100
provider := sdktrace.NewTracerProvider(sdktrace.WithSyncer(imsb))

internal_test.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,15 +364,22 @@ var _ = Describe("ClusterClient", func() {
364364
It("select slot from args for GETKEYSINSLOT command", func() {
365365
cmd := NewStringSliceCmd(ctx, "cluster", "getkeysinslot", 100, 200)
366366

367-
slot := client.cmdSlot(cmd)
367+
slot := client.cmdSlot(cmd, -1)
368368
Expect(slot).To(Equal(100))
369369
})
370370

371371
It("select slot from args for COUNTKEYSINSLOT command", func() {
372372
cmd := NewStringSliceCmd(ctx, "cluster", "countkeysinslot", 100)
373373

374-
slot := client.cmdSlot(cmd)
374+
slot := client.cmdSlot(cmd, -1)
375375
Expect(slot).To(Equal(100))
376376
})
377+
378+
It("follows preferred random slot", func() {
379+
cmd := NewStatusCmd(ctx, "ping")
380+
381+
slot := client.cmdSlot(cmd, 101)
382+
Expect(slot).To(Equal(101))
383+
})
377384
})
378385
})

0 commit comments

Comments
 (0)