|
25 | 25 | _RUNTIME_CONTEXT = None # type: typing.Optional[RuntimeContext]
|
26 | 26 |
|
27 | 27 |
|
| 28 | +_F = typing.TypeVar("_F", bound=typing.Callable[..., typing.Any]) |
| 29 | + |
| 30 | + |
| 31 | +def _load_runtime_context(func: _F) -> _F: |
| 32 | + """Initializes the global RuntimeContext |
| 33 | + """ |
| 34 | + |
| 35 | + def wrapper( |
| 36 | + *args: typing.Tuple[typing.Any, typing.Any], |
| 37 | + **kwargs: typing.Dict[typing.Any, typing.Any], |
| 38 | + ) -> typing.Optional[typing.Any]: |
| 39 | + global _RUNTIME_CONTEXT # pylint: disable=global-statement |
| 40 | + if _RUNTIME_CONTEXT is None: |
| 41 | + # FIXME use a better implementation of a configuration manager to avoid having |
| 42 | + # to get configuration values straight from environment variables |
| 43 | + if version_info < (3, 5): |
| 44 | + # contextvars are not supported in 3.4, use thread-local storage |
| 45 | + default_context = "threadlocal_context" |
| 46 | + else: |
| 47 | + default_context = "contextvars_context" |
| 48 | + |
| 49 | + configured_context = environ.get( |
| 50 | + "OPENTELEMETRY_CONTEXT", default_context |
| 51 | + ) # type: str |
| 52 | + try: |
| 53 | + _RUNTIME_CONTEXT = next( |
| 54 | + iter_entry_points( |
| 55 | + "opentelemetry_context", configured_context |
| 56 | + ) |
| 57 | + ).load()() |
| 58 | + except Exception: # pylint: disable=broad-except |
| 59 | + logger.error("Failed to load context: %s", configured_context) |
| 60 | + return func(*args, **kwargs) # type: ignore |
| 61 | + |
| 62 | + return wrapper # type:ignore |
| 63 | + |
| 64 | + |
28 | 65 | def get_value(key: str, context: typing.Optional[Context] = None) -> "object":
|
29 | 66 | """To access the local state of a concern, the RuntimeContext API
|
30 | 67 | provides a function which takes a context and a key as input,
|
@@ -57,47 +94,27 @@ def set_value(
|
57 | 94 | return Context(new_values)
|
58 | 95 |
|
59 | 96 |
|
| 97 | +@_load_runtime_context # type: ignore |
60 | 98 | def get_current() -> Context:
|
61 | 99 | """To access the context associated with program execution,
|
62 | 100 | the RuntimeContext API provides a function which takes no arguments
|
63 | 101 | and returns a RuntimeContext.
|
64 | 102 | """
|
65 |
| - |
66 |
| - global _RUNTIME_CONTEXT # pylint: disable=global-statement |
67 |
| - if _RUNTIME_CONTEXT is None: |
68 |
| - # FIXME use a better implementation of a configuration manager to avoid having |
69 |
| - # to get configuration values straight from environment variables |
70 |
| - if version_info < (3, 5): |
71 |
| - # contextvars are not supported in 3.4, use thread-local storage |
72 |
| - default_context = "threadlocal_context" |
73 |
| - else: |
74 |
| - default_context = "contextvars_context" |
75 |
| - |
76 |
| - configured_context = environ.get( |
77 |
| - "OPENTELEMETRY_CONTEXT", default_context |
78 |
| - ) # type: str |
79 |
| - try: |
80 |
| - _RUNTIME_CONTEXT = next( |
81 |
| - iter_entry_points("opentelemetry_context", configured_context) |
82 |
| - ).load()() |
83 |
| - except Exception: # pylint: disable=broad-except |
84 |
| - logger.error("Failed to load context: %s", configured_context) |
85 |
| - |
86 | 103 | return _RUNTIME_CONTEXT.get_current() # type:ignore
|
87 | 104 |
|
88 | 105 |
|
| 106 | +@_load_runtime_context # type: ignore |
89 | 107 | def attach(context: Context) -> object:
|
90 | 108 | """Associates a Context with the caller's current execution unit. Returns
|
91 | 109 | a token that can be used to restore the previous Context.
|
92 | 110 |
|
93 | 111 | Args:
|
94 | 112 | context: The Context to set as current.
|
95 | 113 | """
|
96 |
| - get_current() |
97 |
| - |
98 | 114 | return _RUNTIME_CONTEXT.attach(context) # type:ignore
|
99 | 115 |
|
100 | 116 |
|
| 117 | +@_load_runtime_context # type: ignore |
101 | 118 | def detach(token: object) -> None:
|
102 | 119 | """Resets the Context associated with the caller's current execution unit
|
103 | 120 | to the value it had before attaching a specified Context.
|
|
0 commit comments