Skip to content

Commit cc6c06a

Browse files
author
Andres Beck-Ruiz
committed
Fixed context extraction and activation logic.
1 parent c5c6977 commit cc6c06a

File tree

8 files changed

+91
-27
lines changed
  • instrumentation
    • opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi
    • opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django
    • opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon
    • opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask
    • opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid
    • opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado
    • opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi

8 files changed

+91
-27
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
`opentelemetry-instrumentation-starlette`, `opentelemetry-instrumentation-urllib`, `opentelemetry-instrumentation-urllib3` Added `request_hook` and `response_hook` callbacks
1515
([#576](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/576))
1616

17+
### Changed
18+
- Server instrumentations now look for parent spans in current context before extracting context from carriers. ([#544](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/544))
19+
1720
## [1.4.0-0.23b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.4.0-0.23b0) - 2021-07-21
1821

1922
### Removed

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

+9-2
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,14 @@ async def __call__(self, scope, receive, send):
219219
span_name, additional_attributes = self.default_span_details(scope)
220220

221221
try:
222+
token = ctx = span_kind = None
223+
if trace.get_current_span() is trace.INVALID_SPAN:
224+
ctx = extract(scope, getter=asgi_getter)
225+
token = context.attach(ctx)
226+
span_kind = trace.SpanKind.SERVER
227+
222228
with self.tracer.start_as_current_span(
223-
span_name, kind=trace.SpanKind.SERVER,
229+
span_name, ctx, kind=span_kind
224230
) as span:
225231
if span.is_recording():
226232
attributes = collect_request_attributes(scope)
@@ -265,4 +271,5 @@ async def wrapped_send(message):
265271

266272
await self.app(scope, wrapped_receive, wrapped_send)
267273
finally:
268-
context.detach(token)
274+
if token is not None:
275+
context.detach(token)

instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py

+18-5
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,13 @@
3232
)
3333
from opentelemetry.propagate import extract
3434
from opentelemetry.semconv.trace import SpanAttributes
35-
from opentelemetry.trace import Span, SpanKind, use_span
35+
from opentelemetry.trace import (
36+
INVALID_SPAN,
37+
Span,
38+
SpanKind,
39+
get_current_span,
40+
use_span,
41+
)
3642
from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs
3743

3844
try:
@@ -146,11 +152,17 @@ def process_request(self, request):
146152

147153
request_meta = request.META
148154

149-
token = attach(extract(request_meta, getter=wsgi_getter))
155+
token = context = span_kind = None
156+
157+
if get_current_span() is INVALID_SPAN:
158+
context = extract(request_meta, getter=wsgi_getter)
159+
token = attach(context)
160+
span_kind = SpanKind.SERVER
150161

151162
span = self._tracer.start_span(
152163
self._get_span_name(request),
153-
kind=SpanKind.SERVER,
164+
context,
165+
kind=span_kind,
154166
start_time=request_meta.get(
155167
"opentelemetry-instrumentor-django.starttime_key"
156168
),
@@ -170,7 +182,8 @@ def process_request(self, request):
170182

171183
request.META[self._environ_activation_key] = activation
172184
request.META[self._environ_span_key] = span
173-
request.META[self._environ_token] = token
185+
if token is not None:
186+
request.META[self._environ_token] = token
174187

175188
if _DjangoMiddleware._otel_request_hook:
176189
_DjangoMiddleware._otel_request_hook( # pylint: disable=not-callable
@@ -238,7 +251,7 @@ def process_response(self, request, response):
238251
else:
239252
activation.__exit__(None, None, None)
240253

241-
if self._environ_token in request.META.keys():
254+
if request.META.get(self._environ_token, None) is not None:
242255
detach(request.environ.get(self._environ_token))
243256
request.META.pop(self._environ_token)
244257

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

+14-4
Original file line numberDiff line numberDiff line change
@@ -174,12 +174,20 @@ def __call__(self, env, start_response):
174174

175175
start_time = _time_ns()
176176

177-
token = context.attach(extract(env, getter=otel_wsgi.wsgi_getter))
177+
token = ctx = span_kind = None
178+
179+
if trace.get_current_span() is trace.INVALID_SPAN:
180+
ctx = extract(env, getter=otel_wsgi.wsgi_getter)
181+
token = context.attach(ctx)
182+
span_kind = trace.SpanKind.SERVER
183+
178184
span = self._tracer.start_span(
179185
otel_wsgi.get_default_span_name(env),
180-
kind=trace.SpanKind.SERVER,
186+
ctx,
187+
kind=span_kind,
181188
start_time=start_time,
182189
)
190+
183191
if span.is_recording():
184192
attributes = otel_wsgi.collect_request_attributes(env)
185193
for key, value in attributes.items():
@@ -196,7 +204,8 @@ def _start_response(status, response_headers, *args, **kwargs):
196204
status, response_headers, *args, **kwargs
197205
)
198206
activation.__exit__(None, None, None)
199-
context.detach(token)
207+
if token is not None:
208+
context.detach(token)
200209
return response
201210

202211
try:
@@ -205,7 +214,8 @@ def _start_response(status, response_headers, *args, **kwargs):
205214
activation.__exit__(
206215
type(exc), exc, getattr(exc, "__traceback__", None),
207216
)
208-
context.detach(token)
217+
if token is not None:
218+
context.detach(token)
209219
raise
210220

211221

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

+12-5
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,21 @@ def _before_request():
129129
return
130130
flask_request_environ = flask.request.environ
131131
span_name = get_default_span_name()
132-
token = context.attach(
133-
extract(flask_request_environ, getter=otel_wsgi.wsgi_getter)
134-
)
132+
133+
token = ctx = span_kind = None
134+
135+
if trace.get_current_span() is trace.INVALID_SPAN:
136+
ctx = extract(flask_request_environ, getter=otel_wsgi.wsgi_getter)
137+
token = context.attach(ctx)
138+
span_kind = trace.SpanKind.SERVER
135139

136140
span = tracer.start_span(
137141
span_name,
138-
kind=trace.SpanKind.SERVER,
142+
ctx,
143+
kind=span_kind,
139144
start_time=flask_request_environ.get(_ENVIRON_STARTTIME_KEY),
140145
)
146+
141147
if request_hook:
142148
request_hook(span, flask_request_environ)
143149

@@ -181,7 +187,8 @@ def _teardown_request(exc):
181187
activation.__exit__(
182188
type(exc), exc, getattr(exc, "__traceback__", None)
183189
)
184-
context.detach(flask.request.environ.get(_ENVIRON_TOKEN))
190+
if flask.request.environ.get(_ENVIRON_TOKEN, None) is not None:
191+
context.detach(flask.request.environ.get(_ENVIRON_TOKEN))
185192

186193

187194
class _InstrumentedFlask(flask.Flask):

instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,15 @@ def _before_traversal(event):
9292
else:
9393
span_name = otel_wsgi.get_default_span_name(request_environ)
9494

95+
token = ctx = span_kind = None
96+
97+
if trace.get_current_span() is trace.INVALID_SPAN:
98+
ctx = extract(request_environ, getter=otel_wsgi.wsgi_getter)
99+
token = context.attach(ctx)
100+
span_kind = trace.SpanKind.SERVER
101+
95102
span = tracer.start_span(
96-
span_name, kind=trace.SpanKind.SERVER, start_time=start_time,
103+
span_name, ctx, kind=span_kind, start_time=start_time,
97104
)
98105

99106
if span.is_recording():
@@ -109,7 +116,8 @@ def _before_traversal(event):
109116
activation.__enter__() # pylint: disable=E1101
110117
request_environ[_ENVIRON_ACTIVATION_KEY] = activation
111118
request_environ[_ENVIRON_SPAN_KEY] = span
112-
request_environ[_ENVIRON_TOKEN] = token
119+
if token is not None:
120+
request_environ[_ENVIRON_TOKEN] = token
113121

114122

115123
def trace_tween_factory(handler, registry):
@@ -177,8 +185,8 @@ def trace_tween(request):
177185
)
178186
else:
179187
activation.__exit__(None, None, None)
180-
181-
context.detach(request.environ.get(_ENVIRON_TOKEN))
188+
if request.environ.get(_ENVIRON_TOKEN, None) is not None:
189+
context.detach(request.environ.get(_ENVIRON_TOKEN))
182190

183191
return response
184192

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

+11-3
Original file line numberDiff line numberDiff line change
@@ -253,13 +253,20 @@ def _get_operation_name(handler, request):
253253

254254

255255
def _start_span(tracer, handler, start_time) -> _TraceContext:
256-
token = context.attach(extract(handler.request.headers))
256+
token = ctx = span_kind = None
257+
258+
if trace.get_current_span() is trace.INVALID_SPAN:
259+
ctx = extract(handler.request.headers)
260+
token = context.attach(ctx)
261+
span_kind = trace.SpanKind.SERVER
257262

258263
span = tracer.start_span(
259264
_get_operation_name(handler, handler.request),
260-
kind=trace.SpanKind.SERVER,
265+
ctx,
266+
kind=span_kind,
261267
start_time=start_time,
262268
)
269+
263270
if span.is_recording():
264271
attributes = _get_attributes_from_request(handler.request)
265272
for key, value in attributes.items():
@@ -317,5 +324,6 @@ def _finish_span(tracer, handler, error=None):
317324
)
318325

319326
ctx.activation.__exit__(*finish_args) # pylint: disable=E1101
320-
context.detach(ctx.token)
327+
if ctx.token is not None:
328+
context.detach(ctx.token)
321329
delattr(handler, _HANDLER_CONTEXT_KEY)

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

+12-4
Original file line numberDiff line numberDiff line change
@@ -257,11 +257,17 @@ def __call__(self, environ, start_response):
257257
start_response: The WSGI start_response callable.
258258
"""
259259

260-
token = context.attach(extract(environ, getter=wsgi_getter))
260+
token = ctx = span_kind = None
261+
262+
if trace.get_current_span() is trace.INVALID_SPAN:
263+
ctx = extract(environ, getter=wsgi_getter)
264+
token = context.attach(ctx)
265+
span_kind = trace.SpanKind.SERVER
261266

262267
span = self.tracer.start_span(
263268
get_default_span_name(environ),
264-
kind=trace.SpanKind.SERVER,
269+
ctx,
270+
kind=span_kind,
265271
attributes=collect_request_attributes(environ),
266272
)
267273

@@ -285,7 +291,8 @@ def __call__(self, environ, start_response):
285291
if span.is_recording():
286292
span.set_status(Status(StatusCode.ERROR, str(ex)))
287293
span.end()
288-
context.detach(token)
294+
if token is not None:
295+
context.detach(token)
289296
raise
290297

291298

@@ -302,7 +309,8 @@ def _end_span_after_iterating(iterable, span, tracer, token):
302309
if close:
303310
close()
304311
span.end()
305-
context.detach(token)
312+
if token is not None:
313+
context.detach(token)
306314

307315

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

0 commit comments

Comments
 (0)