Skip to content

Commit 9ed98eb

Browse files
api: Implementing Propagators API to use Context (open-telemetry#446)
Implementing Propagators API to use Context. Moving tracecontexthttptextformat to trace/propagation, as TraceContext is specific to trace rather that broader context propagation. Using attach/detach for wsgi and flask extensions, enabling activation of the full context rather that activating of a sub component such as traces. Adding a composite propagator. Co-authored-by: Mauricio Vásquez <mauricio@kinvolk.io>
1 parent a7535a1 commit 9ed98eb

File tree

20 files changed

+533
-511
lines changed

20 files changed

+533
-511
lines changed

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@
66
from flask import request as flask_request
77

88
import opentelemetry.ext.wsgi as otel_wsgi
9-
from opentelemetry import propagators, trace
9+
from opentelemetry import context, propagators, trace
1010
from opentelemetry.ext.flask.version import __version__
11+
from opentelemetry.trace.propagation import get_span_from_context
1112
from opentelemetry.util import time_ns
1213

1314
logger = logging.getLogger(__name__)
1415

1516
_ENVIRON_STARTTIME_KEY = "opentelemetry-flask.starttime_key"
1617
_ENVIRON_SPAN_KEY = "opentelemetry-flask.span_key"
1718
_ENVIRON_ACTIVATION_KEY = "opentelemetry-flask.activation_key"
19+
_ENVIRON_TOKEN = "opentelemetry-flask.token"
1820

1921

2022
def instrument_app(flask):
@@ -57,8 +59,8 @@ def _before_flask_request():
5759
span_name = flask_request.endpoint or otel_wsgi.get_default_span_name(
5860
environ
5961
)
60-
parent_span = propagators.extract(
61-
otel_wsgi.get_header_from_environ, environ
62+
token = context.attach(
63+
propagators.extract(otel_wsgi.get_header_from_environ, environ)
6264
)
6365

6466
tracer = trace.get_tracer(__name__, __version__)
@@ -69,7 +71,6 @@ def _before_flask_request():
6971
attributes["http.route"] = flask_request.url_rule.rule
7072
span = tracer.start_span(
7173
span_name,
72-
parent_span,
7374
kind=trace.SpanKind.SERVER,
7475
attributes=attributes,
7576
start_time=environ.get(_ENVIRON_STARTTIME_KEY),
@@ -78,6 +79,7 @@ def _before_flask_request():
7879
activation.__enter__()
7980
environ[_ENVIRON_ACTIVATION_KEY] = activation
8081
environ[_ENVIRON_SPAN_KEY] = span
82+
environ[_ENVIRON_TOKEN] = token
8183

8284

8385
def _teardown_flask_request(exc):
@@ -95,3 +97,4 @@ def _teardown_flask_request(exc):
9597
activation.__exit__(
9698
type(exc), exc, getattr(exc, "__traceback__", None)
9799
)
100+
context.detach(flask_request.environ.get(_ENVIRON_TOKEN))

ext/opentelemetry-ext-http-requests/src/opentelemetry/ext/http_requests/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def instrumented_request(self, method, url, *args, **kwargs):
7676
# to access propagators.
7777

7878
headers = kwargs.setdefault("headers", {})
79-
propagators.inject(tracer, type(headers).__setitem__, headers)
79+
propagators.inject(type(headers).__setitem__, headers)
8080
result = wrapped(self, method, url, *args, **kwargs) # *** PROCEED
8181

8282
span.set_attribute("http.status_code", result.status_code)

ext/opentelemetry-ext-http-requests/tests/test_requests_integration.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def setUp(self):
4141
self.get_tracer = self.get_tracer_patcher.start()
4242
self.span_context_manager = mock.MagicMock()
4343
self.span = mock.create_autospec(trace.Span, spec_set=True)
44+
self.span.get_context.return_value = trace.INVALID_SPAN_CONTEXT
4445
self.span_context_manager.__enter__.return_value = self.span
4546

4647
def setspanattr(key, value):

ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/__init__.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@
9393
from opentelemetry.ext.opentracing_shim import util
9494
from opentelemetry.ext.opentracing_shim.version import __version__
9595
from opentelemetry.trace import DefaultSpan
96+
from opentelemetry.trace.propagation import (
97+
get_span_from_context,
98+
set_span_in_context,
99+
)
96100

97101
logger = logging.getLogger(__name__)
98102

@@ -677,11 +681,8 @@ def inject(self, span_context, format, carrier):
677681

678682
propagator = propagators.get_global_httptextformat()
679683

680-
propagator.inject(
681-
DefaultSpan(span_context.unwrap()),
682-
type(carrier).__setitem__,
683-
carrier,
684-
)
684+
ctx = set_span_in_context(DefaultSpan(span_context.unwrap()))
685+
propagator.inject(type(carrier).__setitem__, carrier, context=ctx)
685686

686687
def extract(self, format, carrier):
687688
"""Implements the ``extract`` method from the base class."""
@@ -700,6 +701,7 @@ def get_as_list(dict_object, key):
700701
return [value] if value is not None else []
701702

702703
propagator = propagators.get_global_httptextformat()
703-
otel_context = propagator.extract(get_as_list, carrier)
704+
ctx = propagator.extract(get_as_list, carrier)
705+
otel_context = get_span_from_context(ctx).get_context()
704706

705707
return SpanContextShim(otel_context)

ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,26 @@
1616
# pylint:disable=no-member
1717

1818
import time
19+
import typing
1920
from unittest import TestCase
2021

2122
import opentracing
2223

2324
import opentelemetry.ext.opentracing_shim as opentracingshim
2425
from opentelemetry import propagators, trace
25-
from opentelemetry.context.propagation.httptextformat import HTTPTextFormat
26+
from opentelemetry.context import Context
2627
from opentelemetry.ext.opentracing_shim import util
2728
from opentelemetry.sdk.trace import TracerProvider
29+
from opentelemetry.trace.propagation import (
30+
get_span_from_context,
31+
set_span_in_context,
32+
)
33+
from opentelemetry.trace.propagation.httptextformat import (
34+
Getter,
35+
HTTPTextFormat,
36+
HTTPTextFormatT,
37+
Setter,
38+
)
2839

2940

3041
class TestShim(TestCase):
@@ -49,7 +60,7 @@ def setUpClass(cls):
4960
cls._previous_propagator = propagators.get_global_httptextformat()
5061

5162
# Set mock propagator for testing.
52-
propagators.set_global_httptextformat(MockHTTPTextFormat)
63+
propagators.set_global_httptextformat(MockHTTPTextFormat())
5364

5465
@classmethod
5566
def tearDownClass(cls):
@@ -541,23 +552,37 @@ class MockHTTPTextFormat(HTTPTextFormat):
541552
TRACE_ID_KEY = "mock-traceid"
542553
SPAN_ID_KEY = "mock-spanid"
543554

544-
@classmethod
545-
def extract(cls, get_from_carrier, carrier):
546-
trace_id_list = get_from_carrier(carrier, cls.TRACE_ID_KEY)
547-
span_id_list = get_from_carrier(carrier, cls.SPAN_ID_KEY)
555+
def extract(
556+
self,
557+
get_from_carrier: Getter[HTTPTextFormatT],
558+
carrier: HTTPTextFormatT,
559+
context: typing.Optional[Context] = None,
560+
) -> Context:
561+
trace_id_list = get_from_carrier(carrier, self.TRACE_ID_KEY)
562+
span_id_list = get_from_carrier(carrier, self.SPAN_ID_KEY)
548563

549564
if not trace_id_list or not span_id_list:
550-
return trace.INVALID_SPAN_CONTEXT
565+
return set_span_in_context(trace.INVALID_SPAN)
551566

552-
return trace.SpanContext(
553-
trace_id=int(trace_id_list[0]), span_id=int(span_id_list[0])
567+
return set_span_in_context(
568+
trace.DefaultSpan(
569+
trace.SpanContext(
570+
trace_id=int(trace_id_list[0]),
571+
span_id=int(span_id_list[0]),
572+
)
573+
)
554574
)
555575

556-
@classmethod
557-
def inject(cls, span, set_in_carrier, carrier):
576+
def inject(
577+
self,
578+
set_in_carrier: Setter[HTTPTextFormatT],
579+
carrier: HTTPTextFormatT,
580+
context: typing.Optional[Context] = None,
581+
) -> None:
582+
span = get_span_from_context(context)
558583
set_in_carrier(
559-
carrier, cls.TRACE_ID_KEY, str(span.get_context().trace_id)
584+
carrier, self.TRACE_ID_KEY, str(span.get_context().trace_id)
560585
)
561586
set_in_carrier(
562-
carrier, cls.SPAN_ID_KEY, str(span.get_context().span_id)
587+
carrier, self.SPAN_ID_KEY, str(span.get_context().span_id)
563588
)

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@
2222
import typing
2323
import wsgiref.util as wsgiref_util
2424

25-
from opentelemetry import propagators, trace
25+
from opentelemetry import context, propagators, trace
2626
from opentelemetry.ext.wsgi.version import __version__
27+
from opentelemetry.trace.propagation import get_span_from_context
2728
from opentelemetry.trace.status import Status, StatusCanonicalCode
2829

2930
_HTTP_VERSION_PREFIX = "HTTP/"
@@ -181,12 +182,13 @@ def __call__(self, environ, start_response):
181182
start_response: The WSGI start_response callable.
182183
"""
183184

184-
parent_span = propagators.extract(get_header_from_environ, environ)
185+
token = context.attach(
186+
propagators.extract(get_header_from_environ, environ)
187+
)
185188
span_name = get_default_span_name(environ)
186189

187190
span = self.tracer.start_span(
188191
span_name,
189-
parent_span,
190192
kind=trace.SpanKind.SERVER,
191193
attributes=collect_request_attributes(environ),
192194
)
@@ -197,17 +199,20 @@ def __call__(self, environ, start_response):
197199
span, start_response
198200
)
199201
iterable = self.wsgi(environ, start_response)
200-
return _end_span_after_iterating(iterable, span, self.tracer)
202+
return _end_span_after_iterating(
203+
iterable, span, self.tracer, token
204+
)
201205
except: # noqa
202206
# TODO Set span status (cf. https://github.com/open-telemetry/opentelemetry-python/issues/292)
203207
span.end()
208+
context.detach(token)
204209
raise
205210

206211

207212
# Put this in a subfunction to not delay the call to the wrapped
208213
# WSGI application (instrumentation should change the application
209214
# behavior as little as possible).
210-
def _end_span_after_iterating(iterable, span, tracer):
215+
def _end_span_after_iterating(iterable, span, tracer, token):
211216
try:
212217
with tracer.use_span(span):
213218
for yielded in iterable:
@@ -217,3 +222,4 @@ def _end_span_after_iterating(iterable, span, tracer):
217222
if close:
218223
close()
219224
span.end()
225+
context.detach(token)

opentelemetry-api/src/opentelemetry/context/propagation/__init__.py

Lines changed: 0 additions & 18 deletions
This file was deleted.

opentelemetry-api/src/opentelemetry/context/propagation/binaryformat.py

Lines changed: 0 additions & 60 deletions
This file was deleted.

opentelemetry-api/src/opentelemetry/distributedcontext/propagation/__init__.py

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)