Skip to content

Commit 454f4b1

Browse files
code changes to resolve conditional server span creation for WSGI and adding 'attributes' parameter to util function (#903)
* code changes to resolve conditional server span creation for WSGI (#454) * Adding entry to changelog.md * modifying _start_internal_or_server_span() to add attributes as a parameter. Also calling _start_internal_or_server_span() in WSGI instrumentation * resolving flake8 and typo issues
1 parent 0b9e96d commit 454f4b1

File tree

4 files changed

+55
-12
lines changed

4 files changed

+55
-12
lines changed

Diff for: CHANGELOG.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.9.1-0.28b1...HEAD)
99

10+
- `opentelemetry-instrumentation-wsgi` WSGI: Conditionally create SERVER spans
11+
([#903](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/903))
12+
1013
### Fixed
1114

1215
- `opentelemetry-instrumentation-logging` retrieves service name defensively.
@@ -21,7 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2124
- `opentelemetry-instrumentation-pika` requires `packaging` dependency
2225

2326
- `opentelemetry-instrumentation-tornado` Tornado: Conditionally create SERVER spans
24-
([#867](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/889))
27+
([#889](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/889))
2528

2629
## [1.9.0-0.28b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.9.0-0.28b0) - 2022-01-26
2730

Diff for: instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py

+14-10
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,11 @@ def response_hook(span: Span, environ: WSGIEnvironment, status: str, response_he
109109
import wsgiref.util as wsgiref_util
110110

111111
from opentelemetry import context, trace
112-
from opentelemetry.instrumentation.utils import http_status_to_status_code
112+
from opentelemetry.instrumentation.utils import (
113+
_start_internal_or_server_span,
114+
http_status_to_status_code,
115+
)
113116
from opentelemetry.instrumentation.wsgi.version import __version__
114-
from opentelemetry.propagate import extract
115117
from opentelemetry.propagators.textmap import Getter
116118
from opentelemetry.semconv.trace import SpanAttributes
117119
from opentelemetry.trace.status import Status, StatusCode
@@ -279,12 +281,12 @@ def __call__(self, environ, start_response):
279281
environ: A WSGI environment.
280282
start_response: The WSGI start_response callable.
281283
"""
282-
283-
token = context.attach(extract(environ, getter=wsgi_getter))
284-
285-
span = self.tracer.start_span(
286-
get_default_span_name(environ),
287-
kind=trace.SpanKind.SERVER,
284+
span, token = _start_internal_or_server_span(
285+
tracer=self.tracer,
286+
span_name=get_default_span_name(environ),
287+
start_time=None,
288+
context_carrier=environ,
289+
context_getter=wsgi_getter,
288290
attributes=collect_request_attributes(environ),
289291
)
290292

@@ -308,7 +310,8 @@ def __call__(self, environ, start_response):
308310
if span.is_recording():
309311
span.set_status(Status(StatusCode.ERROR, str(ex)))
310312
span.end()
311-
context.detach(token)
313+
if token is not None:
314+
context.detach(token)
312315
raise
313316

314317

@@ -324,7 +327,8 @@ def _end_span_after_iterating(iterable, span, tracer, token):
324327
if close:
325328
close()
326329
span.end()
327-
context.detach(token)
330+
if token is not None:
331+
context.detach(token)
328332

329333

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

Diff for: 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()

Diff for: opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,12 @@ def unwrap(obj, attr: str):
7676

7777

7878
def _start_internal_or_server_span(
79-
tracer, span_name, start_time, context_carrier, context_getter
79+
tracer,
80+
span_name,
81+
start_time,
82+
context_carrier,
83+
context_getter,
84+
attributes=None,
8085
):
8186
"""Returns internal or server span along with the token which can be used by caller to reset context
8287
@@ -107,5 +112,6 @@ def _start_internal_or_server_span(
107112
context=ctx,
108113
kind=span_kind,
109114
start_time=start_time,
115+
attributes=attributes,
110116
)
111117
return span, token

0 commit comments

Comments
 (0)