Skip to content

Commit c4bf074

Browse files
authoredApr 12, 2024··
datadog: Add tracer option to check error eligibility in the span (#1438)
1 parent 5bff6f8 commit c4bf074

File tree

3 files changed

+78
-6
lines changed

3 files changed

+78
-6
lines changed
 

‎contrib/datadog/tracing/interceptor.go

+23-6
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ type TracerOptions struct {
4646

4747
// DisableQueryTracing can be set to disable query tracing.
4848
DisableQueryTracing bool
49+
50+
// OnFinish sets finish options.
51+
// If unset, this will use [tracer.WithError]
52+
// in case [interceptor.TracerFinishSpanOptions.Error] is non-nil and not [workflow.IsContinueAsNewError].
53+
OnFinish func(options *interceptor.TracerFinishSpanOptions) []tracer.FinishOption
4954
}
5055

5156
// NewTracingInterceptor convenience method that wraps a NeTracer() with a tracing interceptor
@@ -57,10 +62,23 @@ func NewTracingInterceptor(opts TracerOptions) interceptor.Interceptor {
5762
// NewTracer creates an interceptor for setting on client options
5863
// that implements Datadog tracing for workflows.
5964
func NewTracer(opts TracerOptions) interceptor.Tracer {
65+
if opts.OnFinish == nil {
66+
opts.OnFinish = func(options *interceptor.TracerFinishSpanOptions) []tracer.FinishOption {
67+
var finishOpts []tracer.FinishOption
68+
69+
if err := options.Error; err != nil && !workflow.IsContinueAsNewError(err) {
70+
finishOpts = append(finishOpts, tracer.WithError(err))
71+
}
72+
73+
return finishOpts
74+
}
75+
}
76+
6077
return &tracerImpl{
6178
opts: TracerOptions{
6279
DisableSignalTracing: opts.DisableSignalTracing,
6380
DisableQueryTracing: opts.DisableQueryTracing,
81+
OnFinish: opts.OnFinish,
6482
},
6583
}
6684
}
@@ -114,7 +132,7 @@ func (t *tracerImpl) SpanFromContext(ctx context.Context) interceptor.TracerSpan
114132
if !ok {
115133
return nil
116134
}
117-
return &tracerSpan{Span: span}
135+
return &tracerSpan{OnFinish: t.opts.OnFinish, Span: span}
118136
}
119137

120138
func (t *tracerImpl) ContextWithSpan(ctx context.Context, span interceptor.TracerSpan) context.Context {
@@ -174,7 +192,7 @@ func (t *tracerImpl) StartSpan(options *interceptor.TracerStartSpanOptions) (int
174192

175193
// Start and return span
176194
s := tracer.StartSpan(t.SpanName(options), startOpts...)
177-
return &tracerSpan{Span: s}, nil
195+
return &tracerSpan{OnFinish: t.opts.OnFinish, Span: s}, nil
178196
}
179197

180198
func (t *tracerImpl) GetLogger(logger log.Logger, ref interceptor.TracerSpanRef) log.Logger {
@@ -223,6 +241,7 @@ func (r spanContextReader) ForeachKey(handler func(key string, value string) err
223241

224242
type tracerSpan struct {
225243
ddtrace.Span
244+
OnFinish func(options *interceptor.TracerFinishSpanOptions) []tracer.FinishOption
226245
}
227246
type tracerSpanCtx struct {
228247
ddtrace.SpanContext
@@ -241,9 +260,7 @@ func (t *tracerSpan) ForeachBaggageItem(handler func(k string, v string) bool) {
241260
}
242261

243262
func (t *tracerSpan) Finish(options *interceptor.TracerFinishSpanOptions) {
244-
var opts []tracer.FinishOption
245-
if err := options.Error; err != nil && !workflow.IsContinueAsNewError(err) {
246-
opts = append(opts, tracer.WithError(err))
247-
}
263+
opts := t.OnFinish(options)
264+
248265
t.Span.Finish(opts...)
249266
}

‎contrib/datadog/tracing/interceptor_test.go

+29
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@
2222
package tracing
2323

2424
import (
25+
"strings"
2526
"testing"
2627

2728
"github.com/stretchr/testify/require"
2829
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/mocktracer"
30+
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
2931

3032
"go.temporal.io/sdk/interceptor"
3133
"go.temporal.io/sdk/internal/interceptortest"
@@ -110,3 +112,30 @@ func Test_tracerImpl_genSpanID(t1 *testing.T) {
110112
})
111113
}
112114
}
115+
func Test_OnFinishOption(t *testing.T) {
116+
mt := mocktracer.Start()
117+
defer mt.Stop()
118+
119+
onFinish := func(options *interceptor.TracerFinishSpanOptions) []tracer.FinishOption {
120+
var finishOpts []tracer.FinishOption
121+
122+
if err := options.Error; strings.Contains(err.Error(), "ignore me") {
123+
finishOpts = append(finishOpts, tracer.WithError(err))
124+
}
125+
126+
return finishOpts
127+
}
128+
129+
impl := NewTracer(TracerOptions{OnFinish: onFinish})
130+
trc := testTracer{
131+
Tracer: impl,
132+
mt: mt,
133+
}
134+
135+
interceptortest.RunTestWorkflowWithError(t, trc)
136+
137+
spans := trc.FinishedSpans()
138+
139+
require.Len(t, spans, 1)
140+
require.Equal(t, "temporal.RunWorkflow", spans[0].Name)
141+
}

‎internal/interceptortest/tracing.go

+26
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ package interceptortest
2424

2525
import (
2626
"context"
27+
"errors"
2728
"fmt"
2829
"testing"
2930
"time"
@@ -90,6 +91,27 @@ func RunTestWorkflow(t *testing.T, tracer interceptor.Tracer) {
9091
require.Equal(t, "query-response", queryResp)
9192
}
9293

94+
func RunTestWorkflowWithError(t *testing.T, tracer interceptor.Tracer) {
95+
var suite testsuite.WorkflowTestSuite
96+
env := suite.NewTestWorkflowEnvironment()
97+
98+
env.RegisterWorkflow(testWorkflowWithError)
99+
100+
// Set tracer interceptor
101+
env.SetWorkerOptions(worker.Options{
102+
Interceptors: []interceptor.WorkerInterceptor{interceptor.NewTracingInterceptor(tracer)},
103+
})
104+
105+
env.SetStartTime(testWorkflowStartTime)
106+
107+
// Exec
108+
env.ExecuteWorkflow(testWorkflowWithError)
109+
110+
// Confirm result
111+
require.True(t, env.IsWorkflowCompleted())
112+
require.Error(t, env.GetWorkflowError())
113+
}
114+
93115
func AssertSpanPropagation(t *testing.T, tracer TestTracer) {
94116

95117
require.Equal(t, []*SpanInfo{
@@ -110,6 +132,10 @@ func AssertSpanPropagation(t *testing.T, tracer TestTracer) {
110132
}, tracer.FinishedSpans())
111133
}
112134

135+
func testWorkflowWithError(_ workflow.Context) error {
136+
return errors.New("ignore me")
137+
}
138+
113139
func testWorkflow(ctx workflow.Context) ([]string, error) {
114140
// Run code
115141
ret, err := workflowInternal(ctx, false)

0 commit comments

Comments
 (0)
Please sign in to comment.