add
This commit is contained in:
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -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`.
|
||||
"""
|
||||
Reference in New Issue
Block a user