Skip to content

Commit 6ad9c42

Browse files
committed
fix(tracing): show the whole command rather than truncated version of it
Truncate version of a long key might not be useful when debugging Signed-off-by: Rodney Osodo <[email protected]>
1 parent 4f09082 commit 6ad9c42

File tree

2 files changed

+164
-18
lines changed

2 files changed

+164
-18
lines changed

extra/rediscmd/rediscmd.go

-18
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ func CmdString(cmd redis.Cmder) string {
1717
}
1818

1919
func CmdsString(cmds []redis.Cmder) (string, string) {
20-
const numCmdLimit = 100
2120
const numNameLimit = 10
2221

2322
seen := make(map[string]struct{}, numNameLimit)
@@ -26,10 +25,6 @@ func CmdsString(cmds []redis.Cmder) (string, string) {
2625
b := make([]byte, 0, 32*len(cmds))
2726

2827
for i, cmd := range cmds {
29-
if i > numCmdLimit {
30-
break
31-
}
32-
3328
if i > 0 {
3429
b = append(b, '\n')
3530
}
@@ -51,12 +46,7 @@ func CmdsString(cmds []redis.Cmder) (string, string) {
5146
}
5247

5348
func AppendCmd(b []byte, cmd redis.Cmder) []byte {
54-
const numArgLimit = 32
55-
5649
for i, arg := range cmd.Args() {
57-
if i > numArgLimit {
58-
break
59-
}
6050
if i > 0 {
6151
b = append(b, ' ')
6252
}
@@ -72,20 +62,12 @@ func AppendCmd(b []byte, cmd redis.Cmder) []byte {
7262
}
7363

7464
func appendArg(b []byte, v interface{}) []byte {
75-
const argLenLimit = 64
76-
7765
switch v := v.(type) {
7866
case nil:
7967
return append(b, "<nil>"...)
8068
case string:
81-
if len(v) > argLenLimit {
82-
v = v[:argLenLimit]
83-
}
8469
return appendUTF8String(b, Bytes(v))
8570
case []byte:
86-
if len(v) > argLenLimit {
87-
v = v[:argLenLimit]
88-
}
8971
return appendUTF8String(b, v)
9072
case int:
9173
return strconv.AppendInt(b, int64(v), 10)

extra/redisotel/tracing_test.go

+164
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"net"
7+
"strings"
78
"testing"
89

910
"go.opentelemetry.io/otel/attribute"
@@ -222,6 +223,169 @@ func TestTracingHook_ProcessPipelineHook(t *testing.T) {
222223
}
223224
}
224225

226+
func TestTracingHook_ProcessHook_LongCommand(t *testing.T) {
227+
imsb := tracetest.NewInMemoryExporter()
228+
provider := sdktrace.NewTracerProvider(sdktrace.WithSyncer(imsb))
229+
hook := newTracingHook(
230+
"redis://localhost:6379",
231+
WithTracerProvider(provider),
232+
)
233+
longValue := strings.Repeat("a", 102400)
234+
235+
tests := []struct {
236+
name string
237+
cmd redis.Cmder
238+
expected string
239+
}{
240+
{
241+
name: "short command",
242+
cmd: redis.NewCmd(context.Background(), "SET", "key", "value"),
243+
expected: "SET key value",
244+
},
245+
{
246+
name: "set command with long key",
247+
cmd: redis.NewCmd(context.Background(), "SET", longValue, "value"),
248+
expected: "SET " + longValue + " value",
249+
},
250+
{
251+
name: "set command with long value",
252+
cmd: redis.NewCmd(context.Background(), "SET", "key", longValue),
253+
expected: "SET key " + longValue,
254+
},
255+
{
256+
name: "set command with long key and value",
257+
cmd: redis.NewCmd(context.Background(), "SET", longValue, longValue),
258+
expected: "SET " + longValue + " " + longValue,
259+
},
260+
{
261+
name: "short command with many arguments",
262+
cmd: redis.NewCmd(context.Background(), "MSET", "key1", "value1", "key2", "value2", "key3", "value3", "key4", "value4", "key5", "value5"),
263+
expected: "MSET key1 value1 key2 value2 key3 value3 key4 value4 key5 value5",
264+
},
265+
{
266+
name: "long command",
267+
cmd: redis.NewCmd(context.Background(), longValue, "key", "value"),
268+
expected: longValue + " key value",
269+
},
270+
}
271+
272+
for _, tt := range tests {
273+
t.Run(tt.name, func(t *testing.T) {
274+
defer imsb.Reset()
275+
276+
processHook := hook.ProcessHook(func(ctx context.Context, cmd redis.Cmder) error {
277+
return nil
278+
})
279+
280+
if err := processHook(context.Background(), tt.cmd); err != nil {
281+
t.Fatal(err)
282+
}
283+
284+
assertEqual(t, 1, len(imsb.GetSpans()))
285+
286+
spanData := imsb.GetSpans()[0]
287+
288+
var dbStatement string
289+
for _, attr := range spanData.Attributes {
290+
if attr.Key == semconv.DBStatementKey {
291+
dbStatement = attr.Value.AsString()
292+
break
293+
}
294+
}
295+
296+
if dbStatement != tt.expected {
297+
t.Errorf("Expected DB statement: %q\nGot: %q", tt.expected, dbStatement)
298+
}
299+
})
300+
}
301+
}
302+
303+
func TestTracingHook_ProcessPipelineHook_LongCommands(t *testing.T) {
304+
imsb := tracetest.NewInMemoryExporter()
305+
provider := sdktrace.NewTracerProvider(sdktrace.WithSyncer(imsb))
306+
hook := newTracingHook(
307+
"redis://localhost:6379",
308+
WithTracerProvider(provider),
309+
)
310+
311+
tests := []struct {
312+
name string
313+
cmds []redis.Cmder
314+
expected string
315+
}{
316+
{
317+
name: "multiple short commands",
318+
cmds: []redis.Cmder{
319+
redis.NewCmd(context.Background(), "SET", "key1", "value1"),
320+
redis.NewCmd(context.Background(), "SET", "key2", "value2"),
321+
},
322+
expected: "SET key1 value1\nSET key2 value2",
323+
},
324+
{
325+
name: "multiple short commands with long key",
326+
cmds: []redis.Cmder{
327+
redis.NewCmd(context.Background(), "SET", strings.Repeat("a", 102400), "value1"),
328+
redis.NewCmd(context.Background(), "SET", strings.Repeat("b", 102400), "value2"),
329+
},
330+
expected: "SET " + strings.Repeat("a", 102400) + " value1\nSET " + strings.Repeat("b", 102400) + " value2",
331+
},
332+
{
333+
name: "multiple short commands with long value",
334+
cmds: []redis.Cmder{
335+
redis.NewCmd(context.Background(), "SET", "key1", strings.Repeat("a", 102400)),
336+
redis.NewCmd(context.Background(), "SET", "key2", strings.Repeat("b", 102400)),
337+
},
338+
expected: "SET key1 " + strings.Repeat("a", 102400) + "\nSET key2 " + strings.Repeat("b", 102400),
339+
},
340+
{
341+
name: "multiple short commands with long key and value",
342+
cmds: []redis.Cmder{
343+
redis.NewCmd(context.Background(), "SET", strings.Repeat("a", 102400), strings.Repeat("b", 102400)),
344+
redis.NewCmd(context.Background(), "SET", strings.Repeat("c", 102400), strings.Repeat("d", 102400)),
345+
},
346+
expected: "SET " + strings.Repeat("a", 102400) + " " + strings.Repeat("b", 102400) + "\nSET " + strings.Repeat("c", 102400) + " " + strings.Repeat("d", 102400),
347+
},
348+
{
349+
name: "multiple long commands",
350+
cmds: []redis.Cmder{
351+
redis.NewCmd(context.Background(), strings.Repeat("a", 102400), "key1", "value1"),
352+
redis.NewCmd(context.Background(), strings.Repeat("a", 102400), "key2", "value2"),
353+
},
354+
expected: strings.Repeat("a", 102400) + " key1 value1\n" + strings.Repeat("a", 102400) + " key2 value2",
355+
},
356+
}
357+
358+
for _, tt := range tests {
359+
t.Run(tt.name, func(t *testing.T) {
360+
defer imsb.Reset()
361+
362+
processHook := hook.ProcessPipelineHook(func(ctx context.Context, cmds []redis.Cmder) error {
363+
return nil
364+
})
365+
366+
if err := processHook(context.Background(), tt.cmds); err != nil {
367+
t.Fatal(err)
368+
}
369+
370+
assertEqual(t, 1, len(imsb.GetSpans()))
371+
372+
spanData := imsb.GetSpans()[0]
373+
374+
var dbStatement string
375+
for _, attr := range spanData.Attributes {
376+
if attr.Key == semconv.DBStatementKey {
377+
dbStatement = attr.Value.AsString()
378+
break
379+
}
380+
}
381+
382+
if dbStatement != tt.expected {
383+
t.Errorf("Expected DB statement:\n%q\nGot:\n%q", tt.expected, dbStatement)
384+
}
385+
})
386+
}
387+
}
388+
225389
func assertEqual(t *testing.T, expected, actual interface{}) {
226390
t.Helper()
227391
if expected != actual {

0 commit comments

Comments
 (0)