-
-
Save xrmx/fc81e710e7a860ca229839b10e780dfd to your computer and use it in GitHub Desktop.
opentelementry api context change hook
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/opentelemetry-api/src/opentelemetry/context/__init__.py b/opentelemetry-api/src/opentelemetry/context/__init__.py | |
index 0a2785ab..7243eb59 100644 | |
--- a/opentelemetry-api/src/opentelemetry/context/__init__.py | |
+++ b/opentelemetry-api/src/opentelemetry/context/__init__.py | |
@@ -14,6 +14,7 @@ | |
import logging | |
import typing | |
+from importlib import import_module | |
from os import environ | |
from uuid import uuid4 | |
@@ -25,6 +26,38 @@ from opentelemetry.util._importlib_metadata import entry_points | |
logger = logging.getLogger(__name__) | |
+def import_string(dotted_path: string) -> object: | |
+ try: | |
+ module_path, class_name = dotted_path.rsplit(".", 1) | |
+ except ValueError: | |
+ msg = f'"{dotted_path}" doesn\'t look like a module path' | |
+ raise ImportError(msg) | |
+ | |
+ module = import_module(module_path) | |
+ | |
+ try: | |
+ return getattr(module, class_name) | |
+ except AttributeError: | |
+ msg = f'Module "{module_path}" does not define a "{class_name}" attribute/class' | |
+ raise ImportError(msg) | |
+ | |
+class DefaultHookHandler: | |
+ def send(self, context): | |
+ pass | |
+ | |
+def _load_context_change_hook() -> None: | |
+ # FIXME: should I just use an entry point instead? | |
+ context_change_hook = environ.get(OTEL_PYTHON_CONTEXT_CHANGE_HOOK) | |
+ if context_change_hook: | |
+ try: | |
+ return import_string(context_change_hooks)() | |
+ except ImportError: | |
+ logger.exception( | |
+ "Failed to load context change hook", | |
+ ) | |
+ return DefaultHookHandler() | |
+ | |
+ | |
def _load_runtime_context() -> _RuntimeContext: | |
"""Initialize the RuntimeContext | |
@@ -67,6 +100,7 @@ def _load_runtime_context() -> _RuntimeContext: | |
_RUNTIME_CONTEXT = _load_runtime_context() | |
+_CONTEXT_CHANGE_HOOK = _load_context_change_hook() | |
def create_key(keyname: str) -> str: | |
@@ -140,7 +174,9 @@ def attach(context: Context) -> object: | |
Returns: | |
A token that can be used with `detach` to reset the context. | |
""" | |
- return _RUNTIME_CONTEXT.attach(context) | |
+ token = _RUNTIME_CONTEXT.attach(context) | |
+ _CONTEXT_CHANGE_HOOK.send(context) | |
+ return token | |
def detach(token: object) -> None: | |
@@ -154,6 +190,8 @@ def detach(token: object) -> None: | |
_RUNTIME_CONTEXT.detach(token) | |
except Exception: # pylint: disable=broad-except | |
logger.exception("Failed to detach context") | |
+ else: | |
+ _CONTEXT_CHANGE_HOOK.send(get_current()) | |
# FIXME This is a temporary location for the suppress instrumentation key. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment