__init__.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. """
  15. API for propagation of context.
  16. The propagators for the
  17. ``opentelemetry.propagators.composite.CompositePropagator`` can be defined
  18. via configuration in the ``OTEL_PROPAGATORS`` environment variable. This
  19. variable should be set to a comma-separated string of names of values for the
  20. ``opentelemetry_propagator`` entry point. For example, setting
  21. ``OTEL_PROPAGATORS`` to ``tracecontext,baggage`` (which is the default value)
  22. would instantiate
  23. ``opentelemetry.propagators.composite.CompositePropagator`` with 2
  24. propagators, one of type
  25. ``opentelemetry.trace.propagation.tracecontext.TraceContextTextMapPropagator``
  26. and other of type ``opentelemetry.baggage.propagation.W3CBaggagePropagator``.
  27. Notice that these propagator classes are defined as
  28. ``opentelemetry_propagator`` entry points in the ``pyproject.toml`` file of
  29. ``opentelemetry``.
  30. Example::
  31. import flask
  32. import requests
  33. from opentelemetry import propagate
  34. PROPAGATOR = propagate.get_global_textmap()
  35. def get_header_from_flask_request(request, key):
  36. return request.headers.get_all(key)
  37. def set_header_into_requests_request(request: requests.Request,
  38. key: str, value: str):
  39. request.headers[key] = value
  40. def example_route():
  41. context = PROPAGATOR.extract(
  42. get_header_from_flask_request,
  43. flask.request
  44. )
  45. request_to_downstream = requests.Request(
  46. "GET", "http://httpbin.org/get"
  47. )
  48. PROPAGATOR.inject(
  49. set_header_into_requests_request,
  50. request_to_downstream,
  51. context=context
  52. )
  53. session = requests.Session()
  54. session.send(request_to_downstream.prepare())
  55. .. _Propagation API Specification:
  56. https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/api-propagators.md
  57. """
  58. from logging import getLogger
  59. from os import environ
  60. from typing import Optional
  61. from opentelemetry.context.context import Context
  62. from opentelemetry.environment_variables import OTEL_PROPAGATORS
  63. from opentelemetry.propagators import composite, textmap
  64. from opentelemetry.util._importlib_metadata import entry_points
  65. logger = getLogger(__name__)
  66. def extract(
  67. carrier: textmap.CarrierT,
  68. context: Optional[Context] = None,
  69. getter: textmap.Getter[textmap.CarrierT] = textmap.default_getter,
  70. ) -> Context:
  71. """Uses the configured propagator to extract a Context from the carrier.
  72. Args:
  73. getter: an object which contains a get function that can retrieve zero
  74. or more values from the carrier and a keys function that can get all the keys
  75. from carrier.
  76. carrier: and object which contains values that are
  77. used to construct a Context. This object
  78. must be paired with an appropriate getter
  79. which understands how to extract a value from it.
  80. context: an optional Context to use. Defaults to root
  81. context if not set.
  82. """
  83. return get_global_textmap().extract(carrier, context, getter=getter)
  84. def inject(
  85. carrier: textmap.CarrierT,
  86. context: Optional[Context] = None,
  87. setter: textmap.Setter[textmap.CarrierT] = textmap.default_setter,
  88. ) -> None:
  89. """Uses the configured propagator to inject a Context into the carrier.
  90. Args:
  91. carrier: the medium used by Propagators to read
  92. values from and write values to.
  93. Should be paired with setter, which
  94. should know how to set header values on the carrier.
  95. context: An optional Context to use. Defaults to current
  96. context if not set.
  97. setter: An optional `Setter` object that can set values
  98. on the carrier.
  99. """
  100. get_global_textmap().inject(carrier, context=context, setter=setter)
  101. propagators = []
  102. # Single use variable here to hack black and make lint pass
  103. environ_propagators = environ.get(
  104. OTEL_PROPAGATORS,
  105. "tracecontext,baggage",
  106. )
  107. for propagator in environ_propagators.split(","):
  108. propagator = propagator.strip()
  109. try:
  110. propagators.append( # type: ignore
  111. next( # type: ignore
  112. iter( # type: ignore
  113. entry_points( # type: ignore
  114. group="opentelemetry_propagator",
  115. name=propagator,
  116. )
  117. )
  118. ).load()()
  119. )
  120. except StopIteration:
  121. raise ValueError(
  122. f"Propagator {propagator} not found. It is either misspelled or not installed."
  123. )
  124. except Exception: # pylint: disable=broad-exception-caught
  125. logger.exception("Failed to load propagator: %s", propagator)
  126. raise
  127. _HTTP_TEXT_FORMAT = composite.CompositePropagator(propagators) # type: ignore
  128. def get_global_textmap() -> textmap.TextMapPropagator:
  129. return _HTTP_TEXT_FORMAT
  130. def set_global_textmap(
  131. http_text_format: textmap.TextMapPropagator,
  132. ) -> None:
  133. global _HTTP_TEXT_FORMAT # pylint:disable=global-statement
  134. _HTTP_TEXT_FORMAT = http_text_format # type: ignore