This commit is contained in:
macbook_max
2026-10-15 20:36:59 +08:00
commit 6bf949949c
7923 changed files with 1369582 additions and 0 deletions
@@ -0,0 +1,94 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
"""Environment variable carriers for text map propagators.
Use :class:`EnvironmentGetter` with the environment mapping to extract from,
usually ``os.environ`` during application or child-process initialization.
Use :class:`EnvironmentSetter` with a mutable environment copy when preparing
the environment for a child process.
"""
import re
from collections.abc import Mapping, MutableMapping
from opentelemetry.propagators.textmap import Getter, Setter
def _normalize_key(key: str) -> str:
if not key:
return "_"
result = re.sub(r"[^A-Za-z0-9_]", "_", key).upper()
if result and result[0].isdigit():
result = "_" + result
return result
def _is_normalized_key(key: str) -> bool:
if not key:
return False
if "0" <= key[0] <= "9":
return False
return all("A" <= char <= "Z" or "0" <= char <= "9" or char == "_" for char in key)
class EnvironmentGetter(Getter[Mapping[str, str]]):
"""Getter implementation for extracting context and baggage from environment variables.
EnvironmentGetter reads from the mapping provided as the carrier, normalizes
requested keys, and provides simple data access without validation.
Example usage:
getter = EnvironmentGetter()
traceparent = getter.get(os.environ, "traceparent")
"""
def get(self, carrier: Mapping[str, str], key: str) -> list[str] | None:
"""Get a value from the environment carrier for the given key.
Args:
carrier: Mapping to read environment variables from
key: The key to look up (will be normalized)
Returns:
A list with a single string value if the key exists, None otherwise.
"""
val = carrier.get(_normalize_key(key))
if val is None:
return None
return [val]
def keys(self, carrier: Mapping[str, str]) -> list[str]:
"""Get all keys from the environment carrier.
Args:
carrier: Mapping to read environment variable keys from
Returns:
List of all already-normalized environment variable keys.
"""
return [key for key in carrier.keys() if _is_normalized_key(key)]
class EnvironmentSetter(Setter[MutableMapping[str, str]]):
"""Setter implementation for building environment variable dictionaries.
EnvironmentSetter builds a dictionary of environment variables that
can be passed to utilities like subprocess.run()
Example usage:
setter = EnvironmentSetter()
env_vars = {}
setter.set(env_vars, "traceparent", "00-trace-id-span-id-01")
subprocess.run(myCommand, env=env_vars)
"""
def set(self, carrier: MutableMapping[str, str], key: str, value: str) -> None:
"""Set a value in the carrier dictionary for the given key.
Args:
carrier: Dictionary to store environment variables
key: The key to set (normalized)
value: The value to set
"""
carrier[_normalize_key(key)] = value
@@ -0,0 +1,78 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
import collections.abc
import logging
from typing_extensions import deprecated
from opentelemetry.context.context import Context
from opentelemetry.propagators import textmap
logger = logging.getLogger(__name__)
class CompositePropagator(textmap.TextMapPropagator):
"""CompositePropagator provides a mechanism for combining multiple
propagators into a single one.
Args:
propagators: the list of propagators to use
"""
def __init__(self, propagators: collections.abc.Sequence[textmap.TextMapPropagator]) -> None:
self._propagators = propagators
def extract(
self,
carrier: textmap.CarrierT,
context: Context | None = None,
getter: textmap.Getter[textmap.CarrierT] = textmap.default_getter,
) -> Context:
"""Run each of the configured propagators with the given context and carrier.
Propagators are run in the order they are configured, if multiple
propagators write the same context key, the propagator later in the list
will override previous propagators.
See `opentelemetry.propagators.textmap.TextMapPropagator.extract`
"""
for propagator in self._propagators:
context = propagator.extract(carrier, context, getter=getter)
return context # type: ignore
def inject(
self,
carrier: textmap.CarrierT,
context: Context | None = None,
setter: textmap.Setter[textmap.CarrierT] = textmap.default_setter,
) -> None:
"""Run each of the configured propagators with the given context and carrier.
Propagators are run in the order they are configured, if multiple
propagators write the same carrier key, the propagator later in the list
will override previous propagators.
See `opentelemetry.propagators.textmap.TextMapPropagator.inject`
"""
for propagator in self._propagators:
propagator.inject(carrier, context, setter=setter)
@property
def fields(self) -> set[str]:
"""Returns a set with the fields set in `inject`.
See
`opentelemetry.propagators.textmap.TextMapPropagator.fields`
"""
composite_fields = set()
for propagator in self._propagators:
for field in propagator.fields:
composite_fields.add(field)
return composite_fields
@deprecated("You should use CompositePropagator. Deprecated since version 1.2.0.")
class CompositeHTTPPropagator(CompositePropagator):
"""CompositeHTTPPropagator provides a mechanism for combining multiple
propagators into a single one.
"""
@@ -0,0 +1,181 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
import abc
import typing
from collections.abc import Iterable, Mapping, MutableMapping
from opentelemetry.context.context import Context
CarrierT = typing.TypeVar("CarrierT")
# pylint: disable=invalid-name
CarrierValT = list[str] | str
class Getter(abc.ABC, typing.Generic[CarrierT]):
"""This class implements a Getter that enables extracting propagated
fields from a carrier.
"""
@abc.abstractmethod
def get(self, carrier: CarrierT, key: str) -> list[str] | None:
"""Function that can retrieve zero
or more values from the carrier. In the case that
the value does not exist, returns None.
Args:
carrier: An object which contains values that are used to
construct a Context.
key: key of a field in carrier.
Returns: first value of the propagation key or None if the key doesn't
exist.
"""
@abc.abstractmethod
def keys(self, carrier: CarrierT) -> list[str]:
"""Function that can retrieve all the keys in a carrier object.
Args:
carrier: An object which contains values that are
used to construct a Context.
Returns:
list of keys from the carrier.
"""
class Setter(abc.ABC, typing.Generic[CarrierT]):
"""This class implements a Setter that enables injecting propagated
fields into a carrier.
"""
@abc.abstractmethod
def set(self, carrier: CarrierT, key: str, value: str) -> None:
"""Function that can set a value into a carrier""
Args:
carrier: An object which contains values that are used to
construct a Context.
key: key of a field in carrier.
value: value for a field in carrier.
"""
class DefaultGetter(Getter[Mapping[str, CarrierValT]]):
def get(self, carrier: Mapping[str, CarrierValT], key: str) -> list[str] | None:
"""Getter implementation to retrieve a value from a dictionary.
Args:
carrier: dictionary in which to get value
key: the key used to get the value
Returns:
A list with a single string with the value if it exists, else None.
"""
val = carrier.get(key, None)
if val is None:
return None
if isinstance(val, Iterable) and not isinstance(val, str):
return list(val)
return [val]
def keys(self, carrier: Mapping[str, CarrierValT]) -> list[str]:
"""Keys implementation that returns all keys from a dictionary."""
return list(carrier.keys())
default_getter: Getter[CarrierT] = DefaultGetter() # type: ignore
class DefaultSetter(Setter[MutableMapping[str, CarrierValT]]):
def set(
self,
carrier: MutableMapping[str, CarrierValT],
key: str,
value: CarrierValT,
) -> None:
"""Setter implementation to set a value into a dictionary.
Args:
carrier: dictionary in which to set value
key: the key used to set the value
value: the value to set
"""
carrier[key] = value
default_setter: Setter[CarrierT] = DefaultSetter() # type: ignore
class TextMapPropagator(abc.ABC):
"""This class provides an interface that enables extracting and injecting
context into headers of HTTP requests. HTTP frameworks and clients
can integrate with TextMapPropagator by providing the object containing the
headers, and a getter and setter function for the extraction and
injection of values, respectively.
"""
@abc.abstractmethod
def extract(
self,
carrier: CarrierT,
context: Context | None = None,
getter: Getter[CarrierT] = default_getter,
) -> Context:
"""Create a Context from values in the carrier.
The extract function should retrieve values from the carrier
object using getter, and use values to populate a
Context value and return it.
Args:
getter: a function that can retrieve zero
or more values from the carrier. In the case that
the value does not exist, return an empty list.
carrier: and object which contains values that are
used to construct a Context. This object
must be paired with an appropriate getter
which understands how to extract a value from it.
context: an optional Context to use. Defaults to root
context if not set.
Returns:
A Context with configuration found in the carrier.
"""
@abc.abstractmethod
def inject(
self,
carrier: CarrierT,
context: Context | None = None,
setter: Setter[CarrierT] = default_setter,
) -> None:
"""Inject values from a Context into a carrier.
inject enables the propagation of values into HTTP clients or
other objects which perform an HTTP request. Implementations
should use the `Setter` 's set method to set values on the
carrier.
Args:
carrier: An object that a place to define HTTP headers.
Should be paired with setter, which should
know how to set header values on the carrier.
context: an optional Context to use. Defaults to current
context if not set.
setter: An optional `Setter` object that can set values
on the carrier.
"""
@property
@abc.abstractmethod
def fields(self) -> set[str]:
"""
Gets the fields set in the carrier by the `inject` method.
If the carrier is reused, its fields that correspond with the ones
present in this attribute should be deleted before calling `inject`.
Returns:
A set with the fields set in `inject`.
"""