11package opentelemetry_test
22
33import (
4+ "context"
5+ "errors"
46 "testing"
57 "time"
68
79 "github.com/stretchr/testify/assert"
810 "github.com/stretchr/testify/require"
11+ "go.opentelemetry.io/otel/attribute"
912 "go.opentelemetry.io/otel/codes"
1013 sdktrace "go.opentelemetry.io/otel/sdk/trace"
1114 "go.opentelemetry.io/otel/sdk/trace/tracetest"
@@ -15,6 +18,9 @@ import (
1518 "go.temporal.io/sdk/interceptor"
1619 "go.temporal.io/sdk/internal/interceptortest"
1720 "go.temporal.io/sdk/temporal"
21+ "go.temporal.io/sdk/testsuite"
22+ "go.temporal.io/sdk/worker"
23+ "go.temporal.io/sdk/workflow"
1824)
1925
2026func TestSpanPropagation (t * testing.T ) {
@@ -152,3 +158,80 @@ func TestBenignErrorSpanStatus(t *testing.T) {
152158 })
153159 }
154160}
161+
162+ func setCustomSpanAttrWorkflow (ctx workflow.Context ) error {
163+ span , ok := opentelemetry .SpanFromWorkflowContext (ctx )
164+ if ! ok {
165+ return errors .New ("Did not find span in workflow context" )
166+ }
167+
168+ span .SetAttributes (attribute .String ("testTag" , "testValue" ))
169+ return nil
170+ }
171+
172+ func TestSpanFromWorkflowContext (t * testing.T ) {
173+ rec := tracetest .NewSpanRecorder ()
174+ tracer , err := opentelemetry .NewTracer (opentelemetry.TracerOptions {
175+ Tracer : sdktrace .NewTracerProvider (sdktrace .WithSpanProcessor (rec )).Tracer ("" ),
176+ })
177+ require .NoError (t , err )
178+
179+ var suite testsuite.WorkflowTestSuite
180+ env := suite .NewTestWorkflowEnvironment ()
181+ env .RegisterWorkflow (setCustomSpanAttrWorkflow )
182+
183+ // Set tracer interceptor
184+ env .SetWorkerOptions (worker.Options {
185+ Interceptors : []interceptor.WorkerInterceptor {interceptor .NewTracingInterceptor (tracer )},
186+ })
187+
188+ env .ExecuteWorkflow (setCustomSpanAttrWorkflow )
189+
190+ require .True (t , env .IsWorkflowCompleted ())
191+
192+ // Verify span was recorded with added attribute
193+ spans := rec .Ended ()
194+ require .GreaterOrEqual (t , len (spans ), 1 )
195+
196+ found := false
197+ for _ , s := range spans {
198+ for _ , kv := range s .Attributes () {
199+ if string (kv .Key ) == "testTag" && kv .Value .AsString () == "testValue" {
200+ found = true
201+ break
202+ }
203+ }
204+ if found {
205+ break
206+ }
207+ }
208+
209+ require .True (t , found , "expected to find attribute 'testTag=testValue' on recorded spans" )
210+ }
211+
212+ func TestSpanFromWorkflowContextNoOpSpan (t * testing.T ) {
213+ var suite testsuite.WorkflowTestSuite
214+ env := suite .NewTestWorkflowEnvironment ()
215+
216+ nilValueWorkflow := func (ctx workflow.Context ) error {
217+ span , ok := opentelemetry .SpanFromWorkflowContext (ctx )
218+
219+ if ! ok {
220+ return errors .New ("Expected ok to be true" )
221+ }
222+
223+ // Make sure we retain behavior of returning no-op span when no span is present in context
224+ noopSpan := trace .SpanFromContext (context .TODO ())
225+ if span != noopSpan {
226+ return errors .New ("Expected span to be no-op span" )
227+ }
228+
229+ return nil
230+ }
231+
232+ env .RegisterWorkflow (nilValueWorkflow )
233+ env .ExecuteWorkflow (nilValueWorkflow )
234+
235+ require .True (t , env .IsWorkflowCompleted ())
236+ require .NoError (t , env .GetWorkflowError ())
237+ }
0 commit comments