Skip to content

Commit f5300b3

Browse files
committed
Remove thread lock by loading RuntimeContext explicitly.
1 parent d213e02 commit f5300b3

File tree

1 file changed

+26
-46
lines changed

1 file changed

+26
-46
lines changed

opentelemetry-api/src/opentelemetry/context/__init__.py

Lines changed: 26 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -25,55 +25,38 @@
2525
from opentelemetry.util._importlib_metadata import entry_points
2626

2727
logger = logging.getLogger(__name__)
28-
_RUNTIME_CONTEXT = None # type: typing.Optional[_RuntimeContext]
29-
_RUNTIME_CONTEXT_LOCK = threading.Lock()
3028

31-
_F = typing.TypeVar("_F", bound=typing.Callable[..., typing.Any])
32-
33-
34-
def _load_runtime_context(func: _F) -> _F:
35-
"""A decorator used to initialize the global RuntimeContext
29+
def _load_runtime_context() -> typing.Optional[_RuntimeContext]:
30+
"""Initialize the RuntimeContext
3631
3732
Returns:
38-
A wrapper of the decorated method.
33+
An instance of RuntimeContext.
3934
"""
4035

41-
@wraps(func) # type: ignore[misc]
42-
def wrapper(
43-
*args: typing.Tuple[typing.Any, typing.Any],
44-
**kwargs: typing.Dict[typing.Any, typing.Any],
45-
) -> typing.Optional[typing.Any]:
46-
global _RUNTIME_CONTEXT # pylint: disable=global-statement
47-
48-
with _RUNTIME_CONTEXT_LOCK:
49-
if _RUNTIME_CONTEXT is None:
50-
# FIXME use a better implementation of a configuration manager
51-
# to avoid having to get configuration values straight from
52-
# environment variables
53-
default_context = "contextvars_context"
54-
55-
configured_context = environ.get(
56-
OTEL_PYTHON_CONTEXT, default_context
57-
) # type: str
58-
try:
59-
60-
_RUNTIME_CONTEXT = next( # type: ignore
61-
iter( # type: ignore
62-
entry_points( # type: ignore
63-
group="opentelemetry_context",
64-
name=configured_context,
65-
)
66-
)
67-
).load()()
68-
69-
except Exception: # pylint: disable=broad-except
70-
logger.exception(
71-
"Failed to load context: %s", configured_context
72-
)
73-
return func(*args, **kwargs) # type: ignore[misc]
74-
75-
return typing.cast(_F, wrapper) # type: ignore[misc]
36+
# FIXME use a better implementation of a configuration manager
37+
# to avoid having to get configuration values straight from
38+
# environment variables
39+
default_context = "contextvars_context"
40+
41+
configured_context = environ.get(
42+
OTEL_PYTHON_CONTEXT, default_context
43+
) # type: str
44+
45+
try:
46+
return next( # type: ignore
47+
iter( # type: ignore
48+
entry_points( # type: ignore
49+
group="opentelemetry_context",
50+
name=configured_context,
51+
)
52+
)
53+
).load()()
54+
except Exception: # pylint: disable=broad-except
55+
logger.exception(
56+
"Failed to load context: %s", configured_context
57+
)
7658

59+
_RUNTIME_CONTEXT = _load_runtime_context()
7760

7861
def create_key(keyname: str) -> str:
7962
"""To allow cross-cutting concern to control access to their local state,
@@ -125,7 +108,6 @@ def set_value(
125108
return Context(new_values)
126109

127110

128-
@_load_runtime_context # type: ignore
129111
def get_current() -> Context:
130112
"""To access the context associated with program execution,
131113
the Context API provides a function which takes no arguments
@@ -137,7 +119,6 @@ def get_current() -> Context:
137119
return _RUNTIME_CONTEXT.get_current() # type:ignore
138120

139121

140-
@_load_runtime_context # type: ignore
141122
def attach(context: Context) -> object:
142123
"""Associates a Context with the caller's current execution unit. Returns
143124
a token that can be used to restore the previous Context.
@@ -151,7 +132,6 @@ def attach(context: Context) -> object:
151132
return _RUNTIME_CONTEXT.attach(context) # type:ignore
152133

153134

154-
@_load_runtime_context # type: ignore
155135
def detach(token: object) -> None:
156136
"""Resets the Context associated with the caller's current execution unit
157137
to the value it had before attaching a specified Context.

0 commit comments

Comments
 (0)