__init__.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. # Copyright The OpenTelemetry Authors
  2. # SPDX-License-Identifier: Apache-2.0
  3. from collections.abc import Mapping
  4. from logging import getLogger
  5. from re import compile
  6. from types import MappingProxyType
  7. from opentelemetry.context import create_key, get_value, set_value
  8. from opentelemetry.context.context import Context
  9. from opentelemetry.util.re import (
  10. _BAGGAGE_PROPERTY_FORMAT,
  11. _KEY_FORMAT,
  12. _VALUE_FORMAT,
  13. )
  14. _BAGGAGE_KEY = create_key("baggage")
  15. _logger = getLogger(__name__)
  16. _KEY_PATTERN = compile(_KEY_FORMAT)
  17. _VALUE_PATTERN = compile(_VALUE_FORMAT)
  18. _PROPERT_PATTERN = compile(_BAGGAGE_PROPERTY_FORMAT)
  19. def get_all(
  20. context: Context | None = None,
  21. ) -> Mapping[str, object]:
  22. """Returns the name/value pairs in the Baggage
  23. Args:
  24. context: The Context to use. If not set, uses current Context
  25. Returns:
  26. The name/value pairs in the Baggage
  27. """
  28. return MappingProxyType(_get_baggage_value(context=context))
  29. def get_baggage(name: str, context: Context | None = None) -> object | None:
  30. """Provides access to the value for a name/value pair in the
  31. Baggage
  32. Args:
  33. name: The name of the value to retrieve
  34. context: The Context to use. If not set, uses current Context
  35. Returns:
  36. The value associated with the given name, or null if the given name is
  37. not present.
  38. """
  39. return _get_baggage_value(context=context).get(name)
  40. def set_baggage(
  41. name: str, value: object, context: Context | None = None
  42. ) -> Context:
  43. """Sets a value in the Baggage
  44. Args:
  45. name: The name of the value to set
  46. value: The value to set
  47. context: The Context to use. If not set, uses current Context
  48. Returns:
  49. A Context with the value updated
  50. """
  51. baggage = _get_baggage_value(context=context).copy()
  52. baggage[name] = value
  53. return set_value(_BAGGAGE_KEY, baggage, context=context)
  54. def remove_baggage(name: str, context: Context | None = None) -> Context:
  55. """Removes a value from the Baggage
  56. Args:
  57. name: The name of the value to remove
  58. context: The Context to use. If not set, uses current Context
  59. Returns:
  60. A Context with the name/value removed
  61. """
  62. baggage = _get_baggage_value(context=context).copy()
  63. baggage.pop(name, None)
  64. return set_value(_BAGGAGE_KEY, baggage, context=context)
  65. def clear(context: Context | None = None) -> Context:
  66. """Removes all values from the Baggage
  67. Args:
  68. context: The Context to use. If not set, uses current Context
  69. Returns:
  70. A Context with all baggage entries removed
  71. """
  72. return set_value(_BAGGAGE_KEY, {}, context=context)
  73. def _get_baggage_value(context: Context | None = None) -> dict[str, object]:
  74. baggage = get_value(_BAGGAGE_KEY, context=context)
  75. if isinstance(baggage, dict):
  76. return baggage
  77. return {}
  78. def _is_valid_key(name: str) -> bool:
  79. return _KEY_PATTERN.fullmatch(str(name)) is not None
  80. def _is_valid_value(value: object) -> bool:
  81. parts = str(value).split(";")
  82. is_valid_value = _VALUE_PATTERN.fullmatch(parts[0]) is not None
  83. if len(parts) > 1: # one or more properties metadata
  84. for property in parts[1:]:
  85. if _PROPERT_PATTERN.fullmatch(property) is None:
  86. is_valid_value = False
  87. break
  88. return is_valid_value
  89. def _is_valid_pair(key: str, value: str) -> bool:
  90. return _is_valid_key(key) and _is_valid_value(value)