Skip to content

Commit bf8d4aa

Browse files
authored
feat(redisotel): ability to override TracerProvider (#1998)
1 parent f1dd3d5 commit bf8d4aa

File tree

4 files changed

+112
-30
lines changed

4 files changed

+112
-30
lines changed

extra/redisotel/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ replace github.com/go-redis/redis/extra/rediscmd/v8 => ../rediscmd
99
require (
1010
github.com/go-redis/redis/extra/rediscmd/v8 v8.11.4
1111
github.com/go-redis/redis/v8 v8.11.4
12-
go.opentelemetry.io/otel v1.0.0
13-
go.opentelemetry.io/otel/trace v1.0.0
12+
go.opentelemetry.io/otel v1.3.0
13+
go.opentelemetry.io/otel/trace v1.3.0
1414
)

extra/redisotel/go.sum

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu
88
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
99
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
1010
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
11+
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
12+
github.com/go-logr/logr v1.2.1 h1:DX7uPQ4WgAWfoh+NGGlbJQswnYIVvz0SRlLS3rPZQDA=
13+
github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
14+
github.com/go-logr/stdr v1.2.0 h1:j4LrlVXgrbIWO83mmQUnK0Hi+YnbD+vzrE1z/EphbFE=
15+
github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI=
1116
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
1217
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
1318
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
@@ -31,24 +36,25 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
3136
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
3237
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
3338
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
34-
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
3539
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
40+
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
3641
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
3742
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
3843
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
39-
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
4044
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
45+
github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE=
46+
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
4147
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4248
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
4349
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
4450
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
4551
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
4652
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
4753
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
48-
go.opentelemetry.io/otel v1.0.0 h1:qTTn6x71GVBvoafHK/yaRUmFzI4LcONZD0/kXxl5PHI=
49-
go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
50-
go.opentelemetry.io/otel/trace v1.0.0 h1:TSBr8GTEtKevYMG/2d21M989r5WJYVimhTHBKVEZuh4=
51-
go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
54+
go.opentelemetry.io/otel v1.3.0 h1:APxLf0eiBwLl+SOXiJJCVYzA1OOJNyAoV8C5RNRyy7Y=
55+
go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs=
56+
go.opentelemetry.io/otel/trace v1.3.0 h1:doy8Hzb1RJ+I3yFhtDmwNc7tIyw1tNMOIsyPzp1NOGY=
57+
go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk=
5258
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
5359
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
5460
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=

extra/redisotel/redisotel.go

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,57 @@ import (
66
"go.opentelemetry.io/otel"
77
"go.opentelemetry.io/otel/attribute"
88
"go.opentelemetry.io/otel/codes"
9+
semconv "go.opentelemetry.io/otel/semconv/v1.7.0"
910
"go.opentelemetry.io/otel/trace"
1011

1112
"github.com/go-redis/redis/extra/rediscmd/v8"
1213
"github.com/go-redis/redis/v8"
1314
)
1415

15-
var tracer = otel.Tracer("github.com/go-redis/redis")
16+
const (
17+
// todo: consider using the full module path "github.com/go-redis/redis/extra/redisotel"
18+
defaultTracerName = "github.com/go-redis/redis"
19+
)
1620

17-
type TracingHook struct{}
21+
type TracingHook struct {
22+
tracer trace.Tracer
23+
}
1824

19-
var _ redis.Hook = (*TracingHook)(nil)
25+
func NewTracingHook(opts ...Option) *TracingHook {
26+
cfg := &config{
27+
tp: otel.GetTracerProvider(),
28+
}
29+
for _, opt := range opts {
30+
opt.apply(cfg)
31+
}
2032

21-
func NewTracingHook() *TracingHook {
22-
return new(TracingHook)
33+
tracer := cfg.tp.Tracer(
34+
defaultTracerName,
35+
// todo: consider adding a version
36+
// trace.WithInstrumentationVersion("semver:8.11.4"),
37+
)
38+
return &TracingHook{tracer: tracer}
2339
}
2440

25-
func (TracingHook) BeforeProcess(ctx context.Context, cmd redis.Cmder) (context.Context, error) {
41+
func (th *TracingHook) BeforeProcess(ctx context.Context, cmd redis.Cmder) (context.Context, error) {
2642
if !trace.SpanFromContext(ctx).IsRecording() {
2743
return ctx, nil
2844
}
2945

30-
attrs := []attribute.KeyValue{
31-
attribute.String("db.system", "redis"),
32-
attribute.String("db.statement", rediscmd.CmdString(cmd)),
33-
}
3446
opts := []trace.SpanStartOption{
3547
trace.WithSpanKind(trace.SpanKindClient),
36-
trace.WithAttributes(attrs...),
48+
trace.WithAttributes(
49+
semconv.DBSystemRedis,
50+
semconv.DBStatementKey.String(rediscmd.CmdString(cmd)),
51+
),
3752
}
3853

39-
ctx, _ = tracer.Start(ctx, cmd.FullName(), opts...)
54+
ctx, _ = th.tracer.Start(ctx, cmd.FullName(), opts...)
4055

4156
return ctx, nil
4257
}
4358

44-
func (TracingHook) AfterProcess(ctx context.Context, cmd redis.Cmder) error {
59+
func (th *TracingHook) AfterProcess(ctx context.Context, cmd redis.Cmder) error {
4560
span := trace.SpanFromContext(ctx)
4661
if err := cmd.Err(); err != nil {
4762
recordError(ctx, span, err)
@@ -50,29 +65,28 @@ func (TracingHook) AfterProcess(ctx context.Context, cmd redis.Cmder) error {
5065
return nil
5166
}
5267

53-
func (TracingHook) BeforeProcessPipeline(ctx context.Context, cmds []redis.Cmder) (context.Context, error) {
68+
func (th *TracingHook) BeforeProcessPipeline(ctx context.Context, cmds []redis.Cmder) (context.Context, error) {
5469
if !trace.SpanFromContext(ctx).IsRecording() {
5570
return ctx, nil
5671
}
5772

5873
summary, cmdsString := rediscmd.CmdsString(cmds)
5974

60-
attrs := []attribute.KeyValue{
61-
attribute.String("db.system", "redis"),
62-
attribute.Int("db.redis.num_cmd", len(cmds)),
63-
attribute.String("db.statement", cmdsString),
64-
}
6575
opts := []trace.SpanStartOption{
6676
trace.WithSpanKind(trace.SpanKindClient),
67-
trace.WithAttributes(attrs...),
77+
trace.WithAttributes(
78+
semconv.DBSystemRedis,
79+
semconv.DBStatementKey.String(cmdsString),
80+
attribute.Int("db.redis.num_cmd", len(cmds)),
81+
),
6882
}
6983

70-
ctx, _ = tracer.Start(ctx, "pipeline "+summary, opts...)
84+
ctx, _ = th.tracer.Start(ctx, "pipeline "+summary, opts...)
7185

7286
return ctx, nil
7387
}
7488

75-
func (TracingHook) AfterProcessPipeline(ctx context.Context, cmds []redis.Cmder) error {
89+
func (th *TracingHook) AfterProcessPipeline(ctx context.Context, cmds []redis.Cmder) error {
7690
span := trace.SpanFromContext(ctx)
7791
if err := cmds[0].Err(); err != nil {
7892
recordError(ctx, span, err)
@@ -87,3 +101,28 @@ func recordError(ctx context.Context, span trace.Span, err error) {
87101
span.SetStatus(codes.Error, err.Error())
88102
}
89103
}
104+
105+
type config struct {
106+
tp trace.TracerProvider
107+
}
108+
109+
// Option specifies instrumentation configuration options.
110+
type Option interface {
111+
apply(*config)
112+
}
113+
114+
type optionFunc func(*config)
115+
116+
func (o optionFunc) apply(c *config) {
117+
o(c)
118+
}
119+
120+
// WithTracerProvider specifies a tracer provider to use for creating a tracer.
121+
// If none is specified, the global provider is used.
122+
func WithTracerProvider(provider trace.TracerProvider) Option {
123+
return optionFunc(func(cfg *config) {
124+
if provider != nil {
125+
cfg.tp = provider
126+
}
127+
})
128+
}

extra/redisotel/redisotel_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package redisotel_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/go-redis/redis/extra/redisotel/v8"
7+
"github.com/go-redis/redis/v8"
8+
"go.opentelemetry.io/otel"
9+
"go.opentelemetry.io/otel/trace"
10+
)
11+
12+
func TestNew(t *testing.T) {
13+
// this also functions as a compile-time test that the
14+
// TracingHook conforms to the Hook interface
15+
var _ redis.Hook = redisotel.NewTracingHook()
16+
}
17+
18+
type providerFunc func(name string, opts ...trace.TracerOption) trace.Tracer
19+
20+
func (fn providerFunc) Tracer(name string, opts ...trace.TracerOption) trace.Tracer {
21+
return fn(name, opts...)
22+
}
23+
24+
func TestNewWithTracerProvider(t *testing.T) {
25+
invoked := false
26+
27+
tp := providerFunc(func(name string, opts ...trace.TracerOption) trace.Tracer {
28+
invoked = true
29+
return otel.GetTracerProvider().Tracer(name, opts...)
30+
})
31+
32+
_ = redisotel.NewTracingHook(redisotel.WithTracerProvider(tp))
33+
34+
if !invoked {
35+
t.Fatalf("did not call custom TraceProvider")
36+
}
37+
}

0 commit comments

Comments
 (0)