Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/opentelemetry/context/__init__.py: 57%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

44 statements  

1# Copyright The OpenTelemetry Authors 

2# SPDX-License-Identifier: Apache-2.0 

3 

4from __future__ import annotations 

5 

6import logging 

7import os 

8from contextvars import Token 

9from uuid import uuid4 

10 

11# pylint: disable=wrong-import-position 

12from opentelemetry.context.context import Context, _RuntimeContext # noqa 

13from opentelemetry.context.contextvars_context import ContextVarsRuntimeContext 

14from opentelemetry.environment_variables import OTEL_PYTHON_CONTEXT 

15 

16logger = logging.getLogger(__name__) 

17 

18 

19def _load_runtime_context() -> _RuntimeContext: 

20 """Initialize the RuntimeContext 

21 

22 Returns: 

23 An instance of RuntimeContext. 

24 """ 

25 configured_context = os.environ.get(OTEL_PYTHON_CONTEXT) 

26 if not configured_context: 

27 return ContextVarsRuntimeContext() 

28 

29 # pylint: disable=import-outside-toplevel,no-name-in-module 

30 from opentelemetry.util._importlib_metadata import ( # noqa: PLC0415 

31 entry_points, 

32 ) 

33 

34 try: 

35 return next( 

36 iter( 

37 entry_points( 

38 group="opentelemetry_context", name=configured_context 

39 ) 

40 ) 

41 ).load()() 

42 except Exception: # pylint: disable=broad-exception-caught 

43 logger.exception( 

44 "Failed to load context: %s, falling back to contextvars_context", 

45 configured_context, 

46 ) 

47 return ContextVarsRuntimeContext() 

48 

49 

50_RUNTIME_CONTEXT = _load_runtime_context() 

51 

52 

53def create_key(keyname: str) -> str: 

54 """To allow cross-cutting concern to control access to their local state, 

55 the RuntimeContext API provides a function which takes a keyname as input, 

56 and returns a unique key. 

57 Args: 

58 keyname: The key name is for debugging purposes and is not required to be unique. 

59 Returns: 

60 A unique string representing the newly created key. 

61 """ 

62 return keyname + "-" + str(uuid4()) 

63 

64 

65def get_value(key: str, context: Context | None = None) -> object: 

66 """To access the local state of a concern, the RuntimeContext API 

67 provides a function which takes a context and a key as input, 

68 and returns a value. 

69 

70 Args: 

71 key: The key of the value to retrieve. 

72 context: The context from which to retrieve the value, if None, the current context is used. 

73 

74 Returns: 

75 The value associated with the key. 

76 """ 

77 return context.get(key) if context is not None else get_current().get(key) 

78 

79 

80def set_value( 

81 key: str, value: object, context: Context | None = None 

82) -> Context: 

83 """To record the local state of a cross-cutting concern, the 

84 RuntimeContext API provides a function which takes a context, a 

85 key, and a value as input, and returns an updated context 

86 which contains the new value. 

87 

88 Args: 

89 key: The key of the entry to set. 

90 value: The value of the entry to set. 

91 context: The context to copy, if None, the current context is used. 

92 

93 Returns: 

94 A new `Context` containing the value set. 

95 """ 

96 if context is None: 

97 context = get_current() 

98 new_values = context.copy() 

99 new_values[key] = value 

100 return Context(new_values) 

101 

102 

103def get_current() -> Context: 

104 """To access the context associated with program execution, 

105 the Context API provides a function which takes no arguments 

106 and returns a Context. 

107 

108 Returns: 

109 The current `Context` object. 

110 """ 

111 return _RUNTIME_CONTEXT.get_current() 

112 

113 

114def attach(context: Context) -> Token[Context]: 

115 """Associates a Context with the caller's current execution unit. Returns 

116 a token that can be used to restore the previous Context. 

117 

118 Args: 

119 context: The Context to set as current. 

120 

121 Returns: 

122 A token that can be used with `detach` to reset the context. 

123 """ 

124 return _RUNTIME_CONTEXT.attach(context) 

125 

126 

127def detach(token: Token[Context]) -> None: 

128 """Resets the Context associated with the caller's current execution unit 

129 to the value it had before attaching a specified Context. 

130 

131 Args: 

132 token: The Token that was returned by a previous call to attach a Context. 

133 """ 

134 try: 

135 _RUNTIME_CONTEXT.detach(token) 

136 except Exception: # pylint: disable=broad-exception-caught 

137 logger.exception("Failed to detach context") 

138 

139 

140# FIXME This is a temporary location for the suppress instrumentation key. 

141# Once the decision around how to suppress instrumentation is made in the 

142# spec, this key should be moved accordingly. 

143_ON_EMIT_RECURSION_COUNT_KEY = create_key("on_emit_recursion_count") 

144_SUPPRESS_INSTRUMENTATION_KEY = create_key("suppress_instrumentation") 

145_SUPPRESS_HTTP_INSTRUMENTATION_KEY = create_key( 

146 "suppress_http_instrumentation" 

147) 

148 

149__all__ = [ 

150 "Context", 

151 "attach", 

152 "create_key", 

153 "detach", 

154 "get_current", 

155 "get_value", 

156 "set_value", 

157]