diff --git a/.changelog/5144.changed b/.changelog/5144.changed new file mode 100644 index 00000000000..dee40b7472d --- /dev/null +++ b/.changelog/5144.changed @@ -0,0 +1 @@ +`opentelemetry-api`: conditionally import entrypoints for `opentelemetry_context` only if the `OTEL_PYTHON_CONTEXT` env variable is defined, return `ContextVarsRuntimeContext` otherwise diff --git a/opentelemetry-api/src/opentelemetry/context/__init__.py b/opentelemetry-api/src/opentelemetry/context/__init__.py index 6518f03835c..80174f66b5e 100644 --- a/opentelemetry-api/src/opentelemetry/context/__init__.py +++ b/opentelemetry-api/src/opentelemetry/context/__init__.py @@ -4,14 +4,14 @@ from __future__ import annotations import logging +import os from contextvars import Token -from os import environ from uuid import uuid4 # pylint: disable=wrong-import-position from opentelemetry.context.context import Context, _RuntimeContext # noqa +from opentelemetry.context.contextvars_context import ContextVarsRuntimeContext from opentelemetry.environment_variables import OTEL_PYTHON_CONTEXT -from opentelemetry.util._importlib_metadata import entry_points logger = logging.getLogger(__name__) @@ -22,37 +22,29 @@ def _load_runtime_context() -> _RuntimeContext: Returns: An instance of RuntimeContext. """ + configured_context = os.environ.get(OTEL_PYTHON_CONTEXT) + if not configured_context: + return ContextVarsRuntimeContext() - # FIXME use a better implementation of a configuration manager - # to avoid having to get configuration values straight from - # environment variables - default_context = "contextvars_context" - - configured_context = environ.get(OTEL_PYTHON_CONTEXT, default_context) # type: str + # pylint: disable=import-outside-toplevel,no-name-in-module + from opentelemetry.util._importlib_metadata import ( # noqa: PLC0415 + entry_points, + ) try: - return next( # type: ignore - iter( # type: ignore - entry_points( # type: ignore - group="opentelemetry_context", - name=configured_context, + return next( + iter( + entry_points( + group="opentelemetry_context", name=configured_context ) ) ).load()() except Exception: # pylint: disable=broad-exception-caught logger.exception( - "Failed to load context: %s, fallback to %s", + "Failed to load context: %s, falling back to contextvars_context", configured_context, - default_context, ) - return next( # type: ignore - iter( # type: ignore - entry_points( # type: ignore - group="opentelemetry_context", - name=default_context, - ) - ) - ).load()() + return ContextVarsRuntimeContext() _RUNTIME_CONTEXT = _load_runtime_context() diff --git a/opentelemetry-api/src/opentelemetry/propagate/__init__.py b/opentelemetry-api/src/opentelemetry/propagate/__init__.py index 207f639a3f4..d53a1b91d30 100644 --- a/opentelemetry-api/src/opentelemetry/propagate/__init__.py +++ b/opentelemetry-api/src/opentelemetry/propagate/__init__.py @@ -63,7 +63,6 @@ def example_route(): from opentelemetry.context.context import Context from opentelemetry.environment_variables import OTEL_PROPAGATORS from opentelemetry.propagators import composite, textmap -from opentelemetry.util._importlib_metadata import entry_points logger = getLogger(__name__) @@ -109,46 +108,66 @@ def inject( get_global_textmap().inject(carrier, context=context, setter=setter) -propagators: list[textmap.TextMapPropagator] = [] - -# Single use variable here to hack black and make lint pass -environ_propagators = environ.get( - OTEL_PROPAGATORS, - "tracecontext,baggage", -) +def _load_propagators() -> textmap.TextMapPropagator: + configured = environ.get(OTEL_PROPAGATORS) + if not configured: + # pylint: disable=import-outside-toplevel,no-name-in-module + from opentelemetry.baggage.propagation import ( # noqa: PLC0415 + W3CBaggagePropagator, + ) + # pylint: disable=import-outside-toplevel,no-name-in-module + from opentelemetry.trace.propagation.tracecontext import ( # noqa: PLC0415 + TraceContextTextMapPropagator, + ) -for propagator in environ_propagators.split(","): - propagator = propagator.strip() - if propagator.lower() == "none": - logger.debug( - "OTEL_PROPAGATORS environment variable contains none, removing all propagators" + return composite.CompositePropagator( + [TraceContextTextMapPropagator(), W3CBaggagePropagator()] ) - propagators = [] - break - try: - propagators.append( - next( # type: ignore - iter( # type: ignore - entry_points( # type: ignore[misc] - group="opentelemetry_propagator", - name=propagator, + + # pylint: disable=import-outside-toplevel,no-name-in-module + from opentelemetry.util._importlib_metadata import ( # noqa: PLC0415 + entry_points, + ) + + _propagators: list[textmap.TextMapPropagator] = [] + for _propagator in configured.split(","): + _propagator = _propagator.strip() + if _propagator.lower() == "none": + logger.debug( + "OTEL_PROPAGATORS environment variable contains none, removing all propagators" + ) + return composite.CompositePropagator([]) + try: + _propagators.append( + next( # type: ignore + iter( # type: ignore + entry_points( # type: ignore[misc] + group="opentelemetry_propagator", + name=_propagator, + ) ) - ) - ).load()() - ) - except StopIteration: - raise ValueError( - f"Propagator {propagator} not found. It is either misspelled or not installed." - ) - except Exception: # pylint: disable=broad-exception-caught - logger.exception("Failed to load propagator: %s", propagator) - raise + ).load()() + ) + except StopIteration: + raise ValueError( + f"Propagator {_propagator} not found. It is either misspelled or not installed." + ) + except Exception: # pylint: disable=broad-exception-caught + logger.exception("Failed to load propagator: %s", _propagator) + raise + return composite.CompositePropagator(_propagators) + + +_HTTP_TEXT_FORMAT: textmap.TextMapPropagator = _load_propagators() +# Deprecated: propagators, environ_propagators and propagator names were never intendended to be part of the public API. +propagators: list[textmap.TextMapPropagator] = [] + +environ_propagators = environ.get(OTEL_PROPAGATORS, "tracecontext,baggage") -_HTTP_TEXT_FORMAT: textmap.TextMapPropagator = composite.CompositePropagator( - propagators -) +for propagator in environ_propagators.split(","): # type: ignore[assignment] + propagator = propagator.strip() def get_global_textmap() -> textmap.TextMapPropagator: diff --git a/opentelemetry-api/src/opentelemetry/util/_providers.py b/opentelemetry-api/src/opentelemetry/util/_providers.py index ac801ba3eba..37cc823e395 100644 --- a/opentelemetry-api/src/opentelemetry/util/_providers.py +++ b/opentelemetry-api/src/opentelemetry/util/_providers.py @@ -5,8 +5,6 @@ from os import environ from typing import TYPE_CHECKING, TypeVar, cast -from opentelemetry.util._importlib_metadata import entry_points - if TYPE_CHECKING: from opentelemetry.metrics import MeterProvider from opentelemetry.trace import TracerProvider @@ -19,6 +17,11 @@ def _load_provider( provider_environment_variable: str, provider: str ) -> Provider: # type: ignore[type-var] + # pylint: disable=import-outside-toplevel,no-name-in-module + from opentelemetry.util._importlib_metadata import ( # noqa: PLC0415 + entry_points, + ) + try: provider_name = cast( str,