codekingpro/portable-devtools
114k
1# Copyright The OpenTelemetry Authors2#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 at6#7# http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# 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 and13# limitations under the License.14 15"""16API for propagation of context.17 18The propagators for the19``opentelemetry.propagators.composite.CompositePropagator`` can be defined20via configuration in the ``OTEL_PROPAGATORS`` environment variable. This21variable should be set to a comma-separated string of names of values for the22``opentelemetry_propagator`` entry point. For example, setting23``OTEL_PROPAGATORS`` to ``tracecontext,baggage`` (which is the default value)24would instantiate25``opentelemetry.propagators.composite.CompositePropagator`` with 226propagators, one of type27``opentelemetry.trace.propagation.tracecontext.TraceContextTextMapPropagator``28and other of type ``opentelemetry.baggage.propagation.W3CBaggagePropagator``.29Notice that these propagator classes are defined as30``opentelemetry_propagator`` entry points in the ``pyproject.toml`` file of31``opentelemetry``.32 33Example::34 35 import flask36 import requests37 from opentelemetry import propagate38 39 40 PROPAGATOR = propagate.get_global_textmap()41 42 43 def get_header_from_flask_request(request, key):44 return request.headers.get_all(key)45 46 def set_header_into_requests_request(request: requests.Request,47 key: str, value: str):48 request.headers[key] = value49 50 def example_route():51 context = PROPAGATOR.extract(52 get_header_from_flask_request,53 flask.request54 )55 request_to_downstream = requests.Request(56 "GET", "http://httpbin.org/get"57 )58 PROPAGATOR.inject(59 set_header_into_requests_request,60 request_to_downstream,61 context=context62 )63 session = requests.Session()64 session.send(request_to_downstream.prepare())65 66 67.. _Propagation API Specification:68 https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/api-propagators.md69"""70 71from logging import getLogger72from os import environ73from typing import List, Optional74 75from opentelemetry.context.context import Context76from opentelemetry.environment_variables import OTEL_PROPAGATORS77from opentelemetry.propagators import composite, textmap78from opentelemetry.util._importlib_metadata import entry_points79 80logger = getLogger(__name__)81 82 83def extract(84 carrier: textmap.CarrierT,85 context: Optional[Context] = None,86 getter: textmap.Getter[textmap.CarrierT] = textmap.default_getter,87) -> Context:88 """Uses the configured propagator to extract a Context from the carrier.89 90 Args:91 getter: an object which contains a get function that can retrieve zero92 or more values from the carrier and a keys function that can get all the keys93 from carrier.94 carrier: and object which contains values that are95 used to construct a Context. This object96 must be paired with an appropriate getter97 which understands how to extract a value from it.98 context: an optional Context to use. Defaults to root99 context if not set.100 """101 return get_global_textmap().extract(carrier, context, getter=getter)102 103 104def inject(105 carrier: textmap.CarrierT,106 context: Optional[Context] = None,107 setter: textmap.Setter[textmap.CarrierT] = textmap.default_setter,108) -> None:109 """Uses the configured propagator to inject a Context into the carrier.110 111 Args:112 carrier: the medium used by Propagators to read113 values from and write values to.114 Should be paired with setter, which115 should know how to set header values on the carrier.116 context: An optional Context to use. Defaults to current117 context if not set.118 setter: An optional `Setter` object that can set values119 on the carrier.120 """121 get_global_textmap().inject(carrier, context=context, setter=setter)122 123 124propagators: List[textmap.TextMapPropagator] = []125 126# Single use variable here to hack black and make lint pass127environ_propagators = environ.get(128 OTEL_PROPAGATORS,129 "tracecontext,baggage",130)131 132 133for propagator in environ_propagators.split(","):134 propagator = propagator.strip()135 if propagator.lower() == "none":136 logger.debug(137 "OTEL_PROPAGATORS environment variable contains none, removing all propagators"138 )139 propagators = []140 break141 try:142 propagators.append(143 next( # type: ignore144 iter( # type: ignore145 entry_points( # type: ignore[misc]146 group="opentelemetry_propagator",147 name=propagator,148 )149 )150 ).load()()151 )152 except StopIteration:153 raise ValueError(154 f"Propagator {propagator} not found. It is either misspelled or not installed."155 )156 except Exception: # pylint: disable=broad-exception-caught157 logger.exception("Failed to load propagator: %s", propagator)158 raise159 160 161_HTTP_TEXT_FORMAT: textmap.TextMapPropagator = composite.CompositePropagator(162 propagators163)164 165 166def get_global_textmap() -> textmap.TextMapPropagator:167 return _HTTP_TEXT_FORMAT168 169 170def set_global_textmap(171 http_text_format: textmap.TextMapPropagator,172) -> None:173 global _HTTP_TEXT_FORMAT # pylint:disable=global-statement174 _HTTP_TEXT_FORMAT = http_text_format175 