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 
    15import abc 
    16import typing 
    17 
    18from opentelemetry.context.context import Context 
    19 
    20CarrierT = typing.TypeVar("CarrierT") 
    21# pylint: disable=invalid-name 
    22CarrierValT = typing.Union[typing.List[str], str] 
    23 
    24 
    25class Getter(abc.ABC, typing.Generic[CarrierT]): 
    26    """This class implements a Getter that enables extracting propagated 
    27    fields from a carrier. 
    28    """ 
    29 
    30    @abc.abstractmethod 
    31    def get( 
    32        self, carrier: CarrierT, key: str 
    33    ) -> typing.Optional[typing.List[str]]: 
    34        """Function that can retrieve zero 
    35        or more values from the carrier. In the case that 
    36        the value does not exist, returns None. 
    37 
    38        Args: 
    39            carrier: An object which contains values that are used to 
    40                    construct a Context. 
    41            key: key of a field in carrier. 
    42        Returns: first value of the propagation key or None if the key doesn't 
    43                exist. 
    44        """ 
    45 
    46    @abc.abstractmethod 
    47    def keys(self, carrier: CarrierT) -> typing.List[str]: 
    48        """Function that can retrieve all the keys in a carrier object. 
    49 
    50        Args: 
    51            carrier: An object which contains values that are 
    52                used to construct a Context. 
    53        Returns: 
    54            list of keys from the carrier. 
    55        """ 
    56 
    57 
    58class Setter(abc.ABC, typing.Generic[CarrierT]): 
    59    """This class implements a Setter that enables injecting propagated 
    60    fields into a carrier. 
    61    """ 
    62 
    63    @abc.abstractmethod 
    64    def set(self, carrier: CarrierT, key: str, value: str) -> None: 
    65        """Function that can set a value into a carrier"" 
    66 
    67        Args: 
    68            carrier: An object which contains values that are used to 
    69                    construct a Context. 
    70            key: key of a field in carrier. 
    71            value: value for a field in carrier. 
    72        """ 
    73 
    74 
    75class DefaultGetter(Getter[typing.Mapping[str, CarrierValT]]): 
    76    def get( 
    77        self, carrier: typing.Mapping[str, CarrierValT], key: str 
    78    ) -> typing.Optional[typing.List[str]]: 
    79        """Getter implementation to retrieve a value from a dictionary. 
    80 
    81        Args: 
    82            carrier: dictionary in which to get value 
    83            key: the key used to get the value 
    84        Returns: 
    85            A list with a single string with the value if it exists, else None. 
    86        """ 
    87        val = carrier.get(key, None) 
    88        if val is None: 
    89            return None 
    90        if isinstance(val, typing.Iterable) and not isinstance(val, str): 
    91            return list(val) 
    92        return [val] 
    93 
    94    def keys( 
    95        self, carrier: typing.Mapping[str, CarrierValT] 
    96    ) -> typing.List[str]: 
    97        """Keys implementation that returns all keys from a dictionary.""" 
    98        return list(carrier.keys()) 
    99 
    100 
    101default_getter: Getter[CarrierT] = DefaultGetter()  # type: ignore 
    102 
    103 
    104class DefaultSetter(Setter[typing.MutableMapping[str, CarrierValT]]): 
    105    def set( 
    106        self, 
    107        carrier: typing.MutableMapping[str, CarrierValT], 
    108        key: str, 
    109        value: CarrierValT, 
    110    ) -> None: 
    111        """Setter implementation to set a value into a dictionary. 
    112 
    113        Args: 
    114            carrier: dictionary in which to set value 
    115            key: the key used to set the value 
    116            value: the value to set 
    117        """ 
    118        carrier[key] = value 
    119 
    120 
    121default_setter: Setter[CarrierT] = DefaultSetter()  # type: ignore 
    122 
    123 
    124class TextMapPropagator(abc.ABC): 
    125    """This class provides an interface that enables extracting and injecting 
    126    context into headers of HTTP requests. HTTP frameworks and clients 
    127    can integrate with TextMapPropagator by providing the object containing the 
    128    headers, and a getter and setter function for the extraction and 
    129    injection of values, respectively. 
    130 
    131    """ 
    132 
    133    @abc.abstractmethod 
    134    def extract( 
    135        self, 
    136        carrier: CarrierT, 
    137        context: typing.Optional[Context] = None, 
    138        getter: Getter[CarrierT] = default_getter, 
    139    ) -> Context: 
    140        """Create a Context from values in the carrier. 
    141 
    142        The extract function should retrieve values from the carrier 
    143        object using getter, and use values to populate a 
    144        Context value and return it. 
    145 
    146        Args: 
    147            getter: a function that can retrieve zero 
    148                or more values from the carrier. In the case that 
    149                the value does not exist, return an empty list. 
    150            carrier: and object which contains values that are 
    151                used to construct a Context. This object 
    152                must be paired with an appropriate getter 
    153                which understands how to extract a value from it. 
    154            context: an optional Context to use. Defaults to root 
    155                context if not set. 
    156        Returns: 
    157            A Context with configuration found in the carrier. 
    158 
    159        """ 
    160 
    161    @abc.abstractmethod 
    162    def inject( 
    163        self, 
    164        carrier: CarrierT, 
    165        context: typing.Optional[Context] = None, 
    166        setter: Setter[CarrierT] = default_setter, 
    167    ) -> None: 
    168        """Inject values from a Context into a carrier. 
    169 
    170        inject enables the propagation of values into HTTP clients or 
    171        other objects which perform an HTTP request. Implementations 
    172        should use the `Setter` 's set method to set values on the 
    173        carrier. 
    174 
    175        Args: 
    176            carrier: An object that a place to define HTTP headers. 
    177                Should be paired with setter, which should 
    178                know how to set header values on the carrier. 
    179            context: an optional Context to use. Defaults to current 
    180                context if not set. 
    181            setter: An optional `Setter` object that can set values 
    182                on the carrier. 
    183 
    184        """ 
    185 
    186    @property 
    187    @abc.abstractmethod 
    188    def fields(self) -> typing.Set[str]: 
    189        """ 
    190        Gets the fields set in the carrier by the `inject` method. 
    191 
    192        If the carrier is reused, its fields that correspond with the ones 
    193        present in this attribute should be deleted before calling `inject`. 
    194 
    195        Returns: 
    196            A set with the fields set in `inject`. 
    197        """