Skip to content

Commit 90d7400

Browse files
authored
Add support for OTEL_PROPAGATORS (#1123)
Fixes #1058
1 parent b8a8016 commit 90d7400

File tree

6 files changed

+135
-11
lines changed

6 files changed

+135
-11
lines changed

opentelemetry-api/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- Add support for `OTEL_PROPAGATORS`
6+
([#1123](https://github.com/open-telemetry/opentelemetry-python/pull/1123))
57
- Store `int`s as `int`s in the global Configuration object
68
([#1118](https://github.com/open-telemetry/opentelemetry-python/pull/1118))
79

opentelemetry-api/setup.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ opentelemetry_meter_provider =
5555
default_meter_provider = opentelemetry.metrics:DefaultMeterProvider
5656
opentelemetry_tracer_provider =
5757
default_tracer_provider = opentelemetry.trace:DefaultTracerProvider
58+
opentelemetry_propagator =
59+
tracecontext = opentelemetry.trace.propagation.tracecontext:TraceContextTextMapPropagator
60+
baggage = opentelemetry.baggage.propagation:BaggagePropagator
5861

5962
[options.extras_require]
6063
test =

opentelemetry-api/src/opentelemetry/propagators/__init__.py

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,21 @@
1515
"""
1616
API for propagation of context.
1717
18+
The propagators for the
19+
``opentelemetry.propagators.composite.CompositeHTTPPropagator`` can be defined
20+
via configuration in the ``OTEL_PROPAGATORS`` environment variable. This
21+
variable should be set to a comma-separated string of names of values for the
22+
``opentelemetry_propagator`` entry point. For example, setting
23+
``OTEL_PROPAGATORS`` to ``tracecontext,baggage`` (which is the default value)
24+
would instantiate
25+
``opentelemetry.propagators.composite.CompositeHTTPPropagator`` with 2
26+
propagators, one of type
27+
``opentelemetry.trace.propagation.tracecontext.TraceContextTextMapPropagator``
28+
and other of type ``opentelemetry.baggage.propagation.BaggagePropagator``.
29+
Notice that these propagator classes are defined as
30+
``opentelemetry_propagator`` entry points in the ``setup.cfg`` file of
31+
``opentelemetry``.
32+
1833
Example::
1934
2035
import flask
@@ -54,14 +69,16 @@ def example_route():
5469
"""
5570

5671
import typing
72+
from logging import getLogger
73+
74+
from pkg_resources import iter_entry_points
5775

58-
from opentelemetry.baggage.propagation import BaggagePropagator
76+
from opentelemetry.configuration import Configuration
5977
from opentelemetry.context.context import Context
6078
from opentelemetry.propagators import composite
6179
from opentelemetry.trace.propagation import textmap
62-
from opentelemetry.trace.propagation.tracecontext import (
63-
TraceContextTextMapPropagator,
64-
)
80+
81+
logger = getLogger(__name__)
6582

6683

6784
def extract(
@@ -104,9 +121,25 @@ def inject(
104121
get_global_textmap().inject(set_in_carrier, carrier, context)
105122

106123

107-
_HTTP_TEXT_FORMAT = composite.CompositeHTTPPropagator(
108-
[TraceContextTextMapPropagator(), BaggagePropagator()],
109-
) # type: textmap.TextMapPropagator
124+
try:
125+
126+
propagators = []
127+
128+
for propagator in ( # type: ignore
129+
Configuration().get("PROPAGATORS", "tracecontext,baggage").split(",") # type: ignore
130+
):
131+
132+
propagators.append( # type: ignore
133+
next( # type: ignore
134+
iter_entry_points("opentelemetry_propagator", propagator) # type: ignore
135+
).load()()
136+
)
137+
138+
except Exception: # pylint: disable=broad-except
139+
logger.exception("Failed to load configured propagators")
140+
raise
141+
142+
_HTTP_TEXT_FORMAT = composite.CompositeHTTPPropagator(propagators) # type: ignore
110143

111144

112145
def get_global_textmap() -> textmap.TextMapPropagator:
@@ -115,4 +148,4 @@ def get_global_textmap() -> textmap.TextMapPropagator:
115148

116149
def set_global_textmap(http_text_format: textmap.TextMapPropagator,) -> None:
117150
global _HTTP_TEXT_FORMAT # pylint:disable=global-statement
118-
_HTTP_TEXT_FORMAT = http_text_format
151+
_HTTP_TEXT_FORMAT = http_text_format # type: ignore

opentelemetry-api/tests/configuration/test_configuration.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@
2020

2121

2222
class TestConfiguration(TestCase):
23-
def tearDown(self) -> None:
24-
# This call resets the attributes of the Configuration class so that
25-
# each test is executed in the same conditions.
23+
24+
# These calls reset the attributes of the Configuration class so that each
25+
# test is executed in the same conditions.
26+
def setUp(self) -> None:
2627
Configuration._reset()
2728

2829
def test_singleton(self) -> None:
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Copyright The OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from importlib import reload
16+
from os import environ
17+
from unittest import TestCase
18+
from unittest.mock import Mock, patch
19+
20+
from opentelemetry.baggage.propagation import BaggagePropagator
21+
from opentelemetry.configuration import Configuration
22+
from opentelemetry.trace.propagation.tracecontext import (
23+
TraceContextTextMapPropagator,
24+
)
25+
26+
27+
class TestPropagators(TestCase):
28+
@patch("opentelemetry.propagators.composite.CompositeHTTPPropagator")
29+
def test_default_composite_propagators(self, mock_compositehttppropagator):
30+
def test_propagators(propagators):
31+
32+
propagators = {propagator.__class__ for propagator in propagators}
33+
34+
self.assertEqual(len(propagators), 2)
35+
self.assertEqual(
36+
propagators, {TraceContextTextMapPropagator, BaggagePropagator}
37+
)
38+
39+
mock_compositehttppropagator.configure_mock(
40+
**{"side_effect": test_propagators}
41+
)
42+
43+
import opentelemetry.propagators
44+
45+
reload(opentelemetry.propagators)
46+
47+
@patch.dict(environ, {"OTEL_PROPAGATORS": "a,b,c"})
48+
@patch("opentelemetry.propagators.composite.CompositeHTTPPropagator")
49+
@patch("pkg_resources.iter_entry_points")
50+
def test_non_default_propagators(
51+
self, mock_iter_entry_points, mock_compositehttppropagator
52+
):
53+
54+
Configuration._reset()
55+
56+
def iter_entry_points_mock(_, propagator):
57+
return iter(
58+
[
59+
Mock(
60+
**{
61+
"load.side_effect": [
62+
Mock(**{"side_effect": [propagator]})
63+
]
64+
}
65+
)
66+
]
67+
)
68+
69+
mock_iter_entry_points.configure_mock(
70+
**{"side_effect": iter_entry_points_mock}
71+
)
72+
73+
def test_propagators(propagators):
74+
75+
self.assertEqual(propagators, ["a", "b", "c"])
76+
77+
mock_compositehttppropagator.configure_mock(
78+
**{"side_effect": test_propagators}
79+
)
80+
81+
import opentelemetry.propagators
82+
83+
reload(opentelemetry.propagators)

opentelemetry-sdk/setup.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ opentelemetry_meter_provider =
5151
sdk_meter_provider = opentelemetry.sdk.metrics:MeterProvider
5252
opentelemetry_tracer_provider =
5353
sdk_tracer_provider = opentelemetry.sdk.trace:TracerProvider
54+
opentelemetry_propagator =
55+
b3 = opentelemetry.sdk.trace.propagation.b3_format.B3Format
5456

5557
[options.extras_require]
5658
test =

0 commit comments

Comments
 (0)