Skip to content

Commit 190f562

Browse files
committed
code changes to resolve conditional server span creation for WSGI (open-telemetry#454)
1 parent 0b9e96d commit 190f562

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -280,11 +280,17 @@ def __call__(self, environ, start_response):
280280
start_response: The WSGI start_response callable.
281281
"""
282282

283-
token = context.attach(extract(environ, getter=wsgi_getter))
283+
token = ctx = None
284+
span_kind = trace.SpanKind.INTERNAL
285+
if trace.get_current_span() is trace.INVALID_SPAN:
286+
ctx = extract(environ, getter=wsgi_getter)
287+
token = context.attach(ctx)
288+
span_kind = trace.SpanKind.SERVER
284289

285290
span = self.tracer.start_span(
286291
get_default_span_name(environ),
287-
kind=trace.SpanKind.SERVER,
292+
context=ctx,
293+
kind=span_kind,
288294
attributes=collect_request_attributes(environ),
289295
)
290296

@@ -308,7 +314,8 @@ def __call__(self, environ, start_response):
308314
if span.is_recording():
309315
span.set_status(Status(StatusCode.ERROR, str(ex)))
310316
span.end()
311-
context.detach(token)
317+
if token is not None:
318+
context.detach(token)
312319
raise
313320

314321

@@ -324,7 +331,8 @@ def _end_span_after_iterating(iterable, span, tracer, token):
324331
if close:
325332
close()
326333
span.end()
327-
context.detach(token)
334+
if token is not None:
335+
context.detach(token)
328336

329337

330338
# TODO: inherit from opentelemetry.instrumentation.propagators.Setter

instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py

+30
Original file line numberDiff line numberDiff line change
@@ -414,5 +414,35 @@ def test_basic_wsgi_call(self):
414414
self.validate_response(response, exporter)
415415

416416

417+
class TestWsgiMiddlewareWrappedWithAnotherFramework(WsgiTestBase):
418+
def test_mark_span_internal_in_presence_of_span_from_other_framework(self):
419+
tracer_provider, exporter = TestBase.create_tracer_provider()
420+
tracer = tracer_provider.get_tracer(__name__)
421+
422+
with tracer.start_as_current_span(
423+
"test", kind=trace_api.SpanKind.SERVER
424+
) as parent_span:
425+
app = otel_wsgi.OpenTelemetryMiddleware(
426+
simple_wsgi, tracer_provider=tracer_provider
427+
)
428+
response = app(self.environ, self.start_response)
429+
while True:
430+
try:
431+
value = next(response)
432+
self.assertEqual(value, b"*")
433+
except StopIteration:
434+
break
435+
436+
span_list = exporter.get_finished_spans()
437+
438+
self.assertEqual(trace_api.SpanKind.INTERNAL, span_list[0].kind)
439+
self.assertEqual(trace_api.SpanKind.SERVER, parent_span.kind)
440+
441+
# internal span should be child of the parent span we have provided
442+
self.assertEqual(
443+
parent_span.context.span_id, span_list[0].parent.span_id
444+
)
445+
446+
417447
if __name__ == "__main__":
418448
unittest.main()

0 commit comments

Comments
 (0)