Skip to content

Commit

Permalink
Add support for OTEL_PROPAGATORS (#1123)
Browse files Browse the repository at this point in the history
Fixes #1058
  • Loading branch information
ocelotl authored Sep 23, 2020
1 parent b8a8016 commit 90d7400
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 11 deletions.
2 changes: 2 additions & 0 deletions opentelemetry-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

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

Expand Down
3 changes: 3 additions & 0 deletions opentelemetry-api/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ opentelemetry_meter_provider =
default_meter_provider = opentelemetry.metrics:DefaultMeterProvider
opentelemetry_tracer_provider =
default_tracer_provider = opentelemetry.trace:DefaultTracerProvider
opentelemetry_propagator =
tracecontext = opentelemetry.trace.propagation.tracecontext:TraceContextTextMapPropagator
baggage = opentelemetry.baggage.propagation:BaggagePropagator

[options.extras_require]
test =
49 changes: 41 additions & 8 deletions opentelemetry-api/src/opentelemetry/propagators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@
"""
API for propagation of context.
The propagators for the
``opentelemetry.propagators.composite.CompositeHTTPPropagator`` can be defined
via configuration in the ``OTEL_PROPAGATORS`` environment variable. This
variable should be set to a comma-separated string of names of values for the
``opentelemetry_propagator`` entry point. For example, setting
``OTEL_PROPAGATORS`` to ``tracecontext,baggage`` (which is the default value)
would instantiate
``opentelemetry.propagators.composite.CompositeHTTPPropagator`` with 2
propagators, one of type
``opentelemetry.trace.propagation.tracecontext.TraceContextTextMapPropagator``
and other of type ``opentelemetry.baggage.propagation.BaggagePropagator``.
Notice that these propagator classes are defined as
``opentelemetry_propagator`` entry points in the ``setup.cfg`` file of
``opentelemetry``.
Example::
import flask
Expand Down Expand Up @@ -54,14 +69,16 @@ def example_route():
"""

import typing
from logging import getLogger

from pkg_resources import iter_entry_points

from opentelemetry.baggage.propagation import BaggagePropagator
from opentelemetry.configuration import Configuration
from opentelemetry.context.context import Context
from opentelemetry.propagators import composite
from opentelemetry.trace.propagation import textmap
from opentelemetry.trace.propagation.tracecontext import (
TraceContextTextMapPropagator,
)

logger = getLogger(__name__)


def extract(
Expand Down Expand Up @@ -104,9 +121,25 @@ def inject(
get_global_textmap().inject(set_in_carrier, carrier, context)


_HTTP_TEXT_FORMAT = composite.CompositeHTTPPropagator(
[TraceContextTextMapPropagator(), BaggagePropagator()],
) # type: textmap.TextMapPropagator
try:

propagators = []

for propagator in ( # type: ignore
Configuration().get("PROPAGATORS", "tracecontext,baggage").split(",") # type: ignore
):

propagators.append( # type: ignore
next( # type: ignore
iter_entry_points("opentelemetry_propagator", propagator) # type: ignore
).load()()
)

except Exception: # pylint: disable=broad-except
logger.exception("Failed to load configured propagators")
raise

_HTTP_TEXT_FORMAT = composite.CompositeHTTPPropagator(propagators) # type: ignore


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

def set_global_textmap(http_text_format: textmap.TextMapPropagator,) -> None:
global _HTTP_TEXT_FORMAT # pylint:disable=global-statement
_HTTP_TEXT_FORMAT = http_text_format
_HTTP_TEXT_FORMAT = http_text_format # type: ignore
7 changes: 4 additions & 3 deletions opentelemetry-api/tests/configuration/test_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@


class TestConfiguration(TestCase):
def tearDown(self) -> None:
# This call resets the attributes of the Configuration class so that
# each test is executed in the same conditions.

# These calls reset the attributes of the Configuration class so that each
# test is executed in the same conditions.
def setUp(self) -> None:
Configuration._reset()

def test_singleton(self) -> None:
Expand Down
83 changes: 83 additions & 0 deletions opentelemetry-api/tests/propagators/test_propagators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from importlib import reload
from os import environ
from unittest import TestCase
from unittest.mock import Mock, patch

from opentelemetry.baggage.propagation import BaggagePropagator
from opentelemetry.configuration import Configuration
from opentelemetry.trace.propagation.tracecontext import (
TraceContextTextMapPropagator,
)


class TestPropagators(TestCase):
@patch("opentelemetry.propagators.composite.CompositeHTTPPropagator")
def test_default_composite_propagators(self, mock_compositehttppropagator):
def test_propagators(propagators):

propagators = {propagator.__class__ for propagator in propagators}

self.assertEqual(len(propagators), 2)
self.assertEqual(
propagators, {TraceContextTextMapPropagator, BaggagePropagator}
)

mock_compositehttppropagator.configure_mock(
**{"side_effect": test_propagators}
)

import opentelemetry.propagators

reload(opentelemetry.propagators)

@patch.dict(environ, {"OTEL_PROPAGATORS": "a,b,c"})
@patch("opentelemetry.propagators.composite.CompositeHTTPPropagator")
@patch("pkg_resources.iter_entry_points")
def test_non_default_propagators(
self, mock_iter_entry_points, mock_compositehttppropagator
):

Configuration._reset()

def iter_entry_points_mock(_, propagator):
return iter(
[
Mock(
**{
"load.side_effect": [
Mock(**{"side_effect": [propagator]})
]
}
)
]
)

mock_iter_entry_points.configure_mock(
**{"side_effect": iter_entry_points_mock}
)

def test_propagators(propagators):

self.assertEqual(propagators, ["a", "b", "c"])

mock_compositehttppropagator.configure_mock(
**{"side_effect": test_propagators}
)

import opentelemetry.propagators

reload(opentelemetry.propagators)
2 changes: 2 additions & 0 deletions opentelemetry-sdk/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ opentelemetry_meter_provider =
sdk_meter_provider = opentelemetry.sdk.metrics:MeterProvider
opentelemetry_tracer_provider =
sdk_tracer_provider = opentelemetry.sdk.trace:TracerProvider
opentelemetry_propagator =
b3 = opentelemetry.sdk.trace.propagation.b3_format.B3Format

[options.extras_require]
test =

0 comments on commit 90d7400

Please sign in to comment.