From 25307db47a6f9e115d99fab9878133cb4921b2b8 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Fri, 19 Jul 2024 11:26:25 +0200 Subject: [PATCH 1/6] WIP tag tests --- .../integrations/opentelemetry/test_potel.py | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/integrations/opentelemetry/test_potel.py b/tests/integrations/opentelemetry/test_potel.py index 1d315b9974..31e5a52e65 100644 --- a/tests/integrations/opentelemetry/test_potel.py +++ b/tests/integrations/opentelemetry/test_potel.py @@ -250,3 +250,65 @@ def test_span_data_started_with_sentry(capture_envelopes): "sentry.description": "statement", "sentry.op": "db", } + + +def test_transaction_tags_started_with_otel(capture_envelopes): + envelopes = capture_envelopes() + + sentry_sdk.set_tag("tag.global", 99) + with tracer.start_as_current_span("request"): + sentry_sdk.set_tag("tag.inner", "foo") + + (envelope,) = envelopes + (item,) = envelope.items + payload = item.payload.json + + assert payload["tags"] == {"tag.global": 99, "tag.inner": "foo"} + + +def test_transaction_tags_started_with_sentry(capture_envelopes): + envelopes = capture_envelopes() + + sentry_sdk.set_tag("tag.global", 99) + with sentry_sdk.start_span(description="request"): + sentry_sdk.set_tag("tag.inner", "foo") + + (envelope,) = envelopes + (item,) = envelope.items + payload = item.payload.json + + assert payload["tags"] == {"tag.global": 99, "tag.inner": "foo"} + + +def test_multiple_transaction_tags_isolation_scope_started_with_otel(capture_envelopes): + envelopes = capture_envelopes() + + sentry_sdk.set_tag("tag.global", 99) + with sentry_sdk.isolation_scope(): + with tracer.start_as_current_span("request a"): + sentry_sdk.set_tag("tag.inner.a", "a") + with sentry_sdk.isolation_scope(): + with tracer.start_as_current_span("request b"): + sentry_sdk.set_tag("tag.inner.b", "b") + + (payload_a, payload_b) = [envelope.items[0].payload.json for envelope in envelopes] + + assert payload_a["tags"] == {"tag.global": 99, "tag.inner.a": "a"} + assert payload_b["tags"] == {"tag.global": 99, "tag.inner.b": "b"} + + +def test_multiple_transaction_tags_isolation_scope_started_with_sentry(capture_envelopes): + envelopes = capture_envelopes() + + sentry_sdk.set_tag("tag.global", 99) + with sentry_sdk.isolation_scope(): + with sentry_sdk.start_span(description="request a"): + sentry_sdk.set_tag("tag.inner.a", "a") + with sentry_sdk.isolation_scope(): + with sentry_sdk.start_span(description="request b"): + sentry_sdk.set_tag("tag.inner.b", "b") + + (payload_a, payload_b) = [envelope.items[0].payload.json for envelope in envelopes] + + assert payload_a["tags"] == {"tag.global": 99, "tag.inner.a": "a"} + assert payload_b["tags"] == {"tag.global": 99, "tag.inner.b": "b"} From 934f4045509a365cfd93292c81d34f0550ee5e63 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Mon, 22 Jul 2024 17:52:23 +0200 Subject: [PATCH 2/6] wip scope overhaul --- .../integrations/opentelemetry/consts.py | 6 ++ .../opentelemetry/contextvars_context.py | 8 +- .../integrations/opentelemetry/scope.py | 95 +++++++++++++++++++ sentry_sdk/scope.py | 33 +++++-- 4 files changed, 129 insertions(+), 13 deletions(-) create mode 100644 sentry_sdk/integrations/opentelemetry/scope.py diff --git a/sentry_sdk/integrations/opentelemetry/consts.py b/sentry_sdk/integrations/opentelemetry/consts.py index a23f8d4c6e..3c5fc61cf6 100644 --- a/sentry_sdk/integrations/opentelemetry/consts.py +++ b/sentry_sdk/integrations/opentelemetry/consts.py @@ -1,8 +1,14 @@ from opentelemetry.context import create_key +# propagation keys SENTRY_TRACE_KEY = create_key("sentry-trace") SENTRY_BAGGAGE_KEY = create_key("sentry-baggage") + +# scope management keys +SENTRY_SCOPES_KEY = create_key("sentry_scopes") +SENTRY_FORK_ISOLATION_SCOPE_KEY = create_key("sentry_fork_isolation_scope") + OTEL_SENTRY_CONTEXT = "otel" SPAN_ORIGIN = "auto.otel" diff --git a/sentry_sdk/integrations/opentelemetry/contextvars_context.py b/sentry_sdk/integrations/opentelemetry/contextvars_context.py index 5e5eb9ba30..1bcaf462b5 100644 --- a/sentry_sdk/integrations/opentelemetry/contextvars_context.py +++ b/sentry_sdk/integrations/opentelemetry/contextvars_context.py @@ -2,15 +2,13 @@ from opentelemetry.context.contextvars_context import ContextVarsRuntimeContext from sentry_sdk.scope import Scope - - -_SCOPES_KEY = create_key("sentry_scopes") +from sentry_sdk.integrations.opentelemetry.consts import SENTRY_SCOPES_KEY class SentryContextVarsRuntimeContext(ContextVarsRuntimeContext): def attach(self, context): # type: (Context) -> object - scopes = get_value(_SCOPES_KEY, context) + scopes = get_value(SENTRY_SCOPES_KEY, context) if scopes and isinstance(scopes, tuple): (current_scope, isolation_scope) = scopes @@ -21,6 +19,6 @@ def attach(self, context): # TODO-neel-potel fork isolation_scope too like JS # once we setup our own apis to pass through to otel new_scopes = (current_scope.fork(), isolation_scope) - new_context = set_value(_SCOPES_KEY, new_scopes, context) + new_context = set_value(SENTRY_SCOPES_KEY, new_scopes, context) return super().attach(new_context) diff --git a/sentry_sdk/integrations/opentelemetry/scope.py b/sentry_sdk/integrations/opentelemetry/scope.py new file mode 100644 index 0000000000..21db4ed70d --- /dev/null +++ b/sentry_sdk/integrations/opentelemetry/scope.py @@ -0,0 +1,95 @@ +from typing import cast +from contextlib import contextmanager + +from opentelemetry.context import get_value, set_value, attach, detach + +from sentry_sdk.scope import Scope, ScopeType +from sentry_sdk.integrations.opentelemetry.consts import ( + SENTRY_SCOPES_KEY, + SENTRY_FORK_ISOLATION_SCOPE_KEY, +) + +from sentry_sdk._types import TYPE_CHECKING + +if TYPE_CHECKING: + from typing import Tuple, Optional, Generator + + +class PotelScope(Scope): + @classmethod + def _get_scopes(cls): + # type: () -> Optional[Tuple[Scope, Scope]] + """ + Returns the current scopes tuple on the otel context. Internal use only. + """ + return cast("Optional[Tuple[Scope, Scope]]", get_value(SENTRY_SCOPES_KEY)) + + @classmethod + def get_current_scope(cls): + # type: () -> Scope + """ + Returns the current scope. + """ + return cls._get_current_scope() or Scope(ty=ScopeType.CURRENT) + + @classmethod + def _get_current_scope(cls): + # type: () -> Optional[Scope] + """ + Returns the current scope without creating a new one. Internal use only. + """ + scopes = cls._get_scopes() + return scopes[0] if scopes else None + + @classmethod + def get_isolation_scope(cls): + """ + Returns the isolation scope. + """ + # type: () -> Scope + return cls._get_isolation_scope() or Scope(ty=ScopeType.ISOLATION) + + @classmethod + def _get_isolation_scope(cls): + # type: () -> Optional[Scope] + """ + Returns the isolation scope without creating a new one. Internal use only. + """ + scopes = cls._get_scopes() + return scopes[1] if scopes else None + + +@contextmanager +def _otel_context(key, value): + token = attach(set_value(key, value)) + try: + yield + finally: + detach(token) + + +@contextmanager +def isolation_scope(): + # type: () -> Generator[Scope, None, None] + """ + .. versionadded:: 2.0.0 + + Context manager that forks the current isolation scope and runs the wrapped code in it. + The current scope is also forked to not bleed data into the existing current scope. + After the wrapped code is executed, the original scopes are restored. + + Example Usage: + + .. code-block:: python + + import sentry_sdk + + with sentry_sdk.isolation_scope() as scope: + scope.set_tag("color", "green") + sentry_sdk.capture_message("hello") # will include `color` tag. + + sentry_sdk.capture_message("hello, again") # will NOT include `color` tag. + + """ + with _otel_context(SENTRY_FORK_ISOLATION_SCOPE_KEY, True): + yield PotelScope.get_isolation_scope() diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index ac47445e17..5e8b9780b9 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -255,13 +255,21 @@ def get_current_scope(cls): Returns the current scope. """ - current_scope = _current_scope.get() + current_scope = cls._get_current_scope() if current_scope is None: current_scope = Scope(ty=ScopeType.CURRENT) _current_scope.set(current_scope) return current_scope + @classmethod + def _get_current_scope(cls): + # type: () -> Optional[Scope] + """ + Returns the current scope without creating a new one. Internal use only. + """ + return _current_scope.get() + @classmethod def set_current_scope(cls, new_current_scope): # type: (Scope) -> None @@ -281,13 +289,22 @@ def get_isolation_scope(cls): Returns the isolation scope. """ - isolation_scope = _isolation_scope.get() + isolation_scope = cls._get_isolation_scope() if isolation_scope is None: isolation_scope = Scope(ty=ScopeType.ISOLATION) _isolation_scope.set(isolation_scope) return isolation_scope + @classmethod + def _get_isolation_scope(cls): + # type: () -> Optional[Scope] + """ + Returns the isolation scope without creating a new one. Internal use only. + """ + return _isolation_scope.get() + + @classmethod def set_isolation_scope(cls, new_isolation_scope): # type: (Scope) -> None @@ -342,11 +359,11 @@ def _merge_scopes(self, additional_scope=None, additional_scope_kwargs=None): final_scope = copy(_global_scope) if _global_scope is not None else Scope() final_scope._type = ScopeType.MERGED - isolation_scope = _isolation_scope.get() + isolation_scope = self._get_isolation_scope() if isolation_scope is not None: final_scope.update_from_scope(isolation_scope) - current_scope = _current_scope.get() + current_scope = self._get_current_scope() if current_scope is not None: final_scope.update_from_scope(current_scope) @@ -374,7 +391,7 @@ def get_client(cls): This checks the current scope, the isolation scope and the global scope for a client. If no client is available a :py:class:`sentry_sdk.client.NonRecordingClient` is returned. """ - current_scope = _current_scope.get() + current_scope = cls._get_current_scope() try: client = current_scope.client except AttributeError: @@ -383,7 +400,7 @@ def get_client(cls): if client is not None and client.is_active(): return client - isolation_scope = _isolation_scope.get() + isolation_scope = cls._get_isolation_scope() try: client = isolation_scope.client except AttributeError: @@ -1361,8 +1378,8 @@ def run_event_processors(self, event, hint): if not is_check_in: # Get scopes without creating them to prevent infinite recursion - isolation_scope = _isolation_scope.get() - current_scope = _current_scope.get() + isolation_scope = self._get_isolation_scope() + current_scope = self._get_current_scope() event_processors = chain( global_event_processors, From 95de20b55d57a623294d93e78e793cafa0b64a1b Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Mon, 22 Jul 2024 17:52:23 +0200 Subject: [PATCH 3/6] wip scope overhaul --- sentry_sdk/api.py | 3 +- .../integrations/opentelemetry/__init__.py | 13 ++++--- .../opentelemetry/contextvars_context.py | 17 ++++---- .../integrations/opentelemetry/scope.py | 39 ++++++------------- 4 files changed, 30 insertions(+), 42 deletions(-) diff --git a/sentry_sdk/api.py b/sentry_sdk/api.py index 4c3104f35f..5ba4816e30 100644 --- a/sentry_sdk/api.py +++ b/sentry_sdk/api.py @@ -4,9 +4,10 @@ from sentry_sdk import tracing, tracing_utils, Client from sentry_sdk._init_implementation import init -from sentry_sdk.scope import Scope, _ScopeManager, new_scope, isolation_scope from sentry_sdk.tracing import POTelSpan, Transaction, trace from sentry_sdk.crons import monitor +# TODO-neel-potel make 2 scope strategies/impls and switch +from sentry_sdk.integrations.opentelemetry.scope import PotelScope as Scope, new_scope, isolation_scope from sentry_sdk._types import TYPE_CHECKING diff --git a/sentry_sdk/integrations/opentelemetry/__init__.py b/sentry_sdk/integrations/opentelemetry/__init__.py index e0020204d5..43587f2e01 100644 --- a/sentry_sdk/integrations/opentelemetry/__init__.py +++ b/sentry_sdk/integrations/opentelemetry/__init__.py @@ -1,7 +1,8 @@ -from sentry_sdk.integrations.opentelemetry.span_processor import ( # noqa: F401 - SentrySpanProcessor, -) +# TODO-neel-potel fix circular imports +# from sentry_sdk.integrations.opentelemetry.span_processor import ( # noqa: F401 +# SentrySpanProcessor, +# ) -from sentry_sdk.integrations.opentelemetry.propagator import ( # noqa: F401 - SentryPropagator, -) +# from sentry_sdk.integrations.opentelemetry.propagator import ( # noqa: F401 +# SentryPropagator, +# ) diff --git a/sentry_sdk/integrations/opentelemetry/contextvars_context.py b/sentry_sdk/integrations/opentelemetry/contextvars_context.py index 1bcaf462b5..12b42303a1 100644 --- a/sentry_sdk/integrations/opentelemetry/contextvars_context.py +++ b/sentry_sdk/integrations/opentelemetry/contextvars_context.py @@ -1,24 +1,25 @@ from opentelemetry.context import Context, create_key, get_value, set_value from opentelemetry.context.contextvars_context import ContextVarsRuntimeContext -from sentry_sdk.scope import Scope -from sentry_sdk.integrations.opentelemetry.consts import SENTRY_SCOPES_KEY +from sentry_sdk.integrations.opentelemetry.scope import PotelScope +from sentry_sdk.integrations.opentelemetry.consts import SENTRY_SCOPES_KEY, SENTRY_FORK_ISOLATION_SCOPE_KEY class SentryContextVarsRuntimeContext(ContextVarsRuntimeContext): def attach(self, context): # type: (Context) -> object scopes = get_value(SENTRY_SCOPES_KEY, context) + should_fork_isolation_scope = context.pop(SENTRY_FORK_ISOLATION_SCOPE_KEY, False) if scopes and isinstance(scopes, tuple): (current_scope, isolation_scope) = scopes else: - current_scope = Scope.get_current_scope() - isolation_scope = Scope.get_isolation_scope() + current_scope = PotelScope.get_current_scope() + isolation_scope = PotelScope.get_isolation_scope() - # TODO-neel-potel fork isolation_scope too like JS - # once we setup our own apis to pass through to otel - new_scopes = (current_scope.fork(), isolation_scope) - new_context = set_value(SENTRY_SCOPES_KEY, new_scopes, context) + new_scope = current_scope.fork() + new_isolation_scope = isolation_scope.fork() if should_fork_isolation_scope else isolation_scope + new_scopes = (new_scope, new_isolation_scope) + new_context = set_value(SENTRY_SCOPES_KEY, new_scopes, context) return super().attach(new_context) diff --git a/sentry_sdk/integrations/opentelemetry/scope.py b/sentry_sdk/integrations/opentelemetry/scope.py index 21db4ed70d..c5634433c0 100644 --- a/sentry_sdk/integrations/opentelemetry/scope.py +++ b/sentry_sdk/integrations/opentelemetry/scope.py @@ -1,7 +1,7 @@ from typing import cast from contextlib import contextmanager -from opentelemetry.context import get_value, set_value, attach, detach +from opentelemetry.context import get_value, set_value, attach, detach, get_current from sentry_sdk.scope import Scope, ScopeType from sentry_sdk.integrations.opentelemetry.consts import ( @@ -60,36 +60,21 @@ def _get_isolation_scope(cls): @contextmanager -def _otel_context(key, value): - token = attach(set_value(key, value)) +def isolation_scope(): + # type: () -> Generator[Scope, None, None] + context = set_value(SENTRY_FORK_ISOLATION_SCOPE_KEY, True) + token = attach(context) try: - yield + yield PotelScope.get_isolation_scope() finally: detach(token) @contextmanager -def isolation_scope(): +def new_scope(): # type: () -> Generator[Scope, None, None] - """ - .. versionadded:: 2.0.0 - - Context manager that forks the current isolation scope and runs the wrapped code in it. - The current scope is also forked to not bleed data into the existing current scope. - After the wrapped code is executed, the original scopes are restored. - - Example Usage: - - .. code-block:: python - - import sentry_sdk - - with sentry_sdk.isolation_scope() as scope: - scope.set_tag("color", "green") - sentry_sdk.capture_message("hello") # will include `color` tag. - - sentry_sdk.capture_message("hello, again") # will NOT include `color` tag. - - """ - with _otel_context(SENTRY_FORK_ISOLATION_SCOPE_KEY, True): - yield PotelScope.get_isolation_scope() + token = attach(get_current()) + try: + yield PotelScope.get_current_scope() + finally: + detach(token) From 52cf4fa6e15c156c993514ef41cafdc19d29a773 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Wed, 31 Jul 2024 17:20:13 +0200 Subject: [PATCH 4/6] Fix setup after rebase --- sentry_sdk/integrations/opentelemetry/integration.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/integrations/opentelemetry/integration.py b/sentry_sdk/integrations/opentelemetry/integration.py index 43e0396c16..af16f53de9 100644 --- a/sentry_sdk/integrations/opentelemetry/integration.py +++ b/sentry_sdk/integrations/opentelemetry/integration.py @@ -6,7 +6,8 @@ from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.integrations.opentelemetry.propagator import SentryPropagator -from sentry_sdk.integrations.opentelemetry.span_processor import SentrySpanProcessor +from sentry_sdk.integrations.opentelemetry.potel_span_processor import PotelSentrySpanProcessor +from sentry_sdk.integrations.opentelemetry.contextvars_context import SentryContextVarsRuntimeContext from sentry_sdk.utils import logger try: @@ -46,9 +47,13 @@ def setup_once(): def _setup_sentry_tracing(): # type: () -> None + from opentelemetry.context import _RUNTIME_CONTEXT + _RUNTIME_CONTEXT = SentryContextVarsRuntimeContext() + provider = TracerProvider() - provider.add_span_processor(SentrySpanProcessor()) + provider.add_span_processor(PotelSentrySpanProcessor()) trace.set_tracer_provider(provider) + set_global_textmap(SentryPropagator()) From 4505cb845123f3526689db657f5a11e9c29b3c53 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Thu, 1 Aug 2024 14:46:10 +0200 Subject: [PATCH 5/6] More scope stuff wip --- .../opentelemetry/contextvars_context.py | 21 ++++++++++++------- .../integrations/opentelemetry/integration.py | 13 ++++++++---- .../integrations/opentelemetry/scope.py | 8 +++++-- sentry_sdk/scope.py | 11 ++++------ tests/conftest.py | 4 ++++ .../integrations/opentelemetry/test_potel.py | 5 ++++- 6 files changed, 41 insertions(+), 21 deletions(-) diff --git a/sentry_sdk/integrations/opentelemetry/contextvars_context.py b/sentry_sdk/integrations/opentelemetry/contextvars_context.py index 12b42303a1..86fc253af8 100644 --- a/sentry_sdk/integrations/opentelemetry/contextvars_context.py +++ b/sentry_sdk/integrations/opentelemetry/contextvars_context.py @@ -1,24 +1,31 @@ -from opentelemetry.context import Context, create_key, get_value, set_value +from opentelemetry.context import Context, get_value, set_value from opentelemetry.context.contextvars_context import ContextVarsRuntimeContext -from sentry_sdk.integrations.opentelemetry.scope import PotelScope -from sentry_sdk.integrations.opentelemetry.consts import SENTRY_SCOPES_KEY, SENTRY_FORK_ISOLATION_SCOPE_KEY +import sentry_sdk +from sentry_sdk.integrations.opentelemetry.consts import ( + SENTRY_SCOPES_KEY, + SENTRY_FORK_ISOLATION_SCOPE_KEY, +) class SentryContextVarsRuntimeContext(ContextVarsRuntimeContext): def attach(self, context): # type: (Context) -> object scopes = get_value(SENTRY_SCOPES_KEY, context) - should_fork_isolation_scope = context.pop(SENTRY_FORK_ISOLATION_SCOPE_KEY, False) + should_fork_isolation_scope = context.pop( + SENTRY_FORK_ISOLATION_SCOPE_KEY, False + ) if scopes and isinstance(scopes, tuple): (current_scope, isolation_scope) = scopes else: - current_scope = PotelScope.get_current_scope() - isolation_scope = PotelScope.get_isolation_scope() + current_scope = sentry_sdk.get_current_scope() + isolation_scope = sentry_sdk.get_isolation_scope() new_scope = current_scope.fork() - new_isolation_scope = isolation_scope.fork() if should_fork_isolation_scope else isolation_scope + new_isolation_scope = ( + isolation_scope.fork() if should_fork_isolation_scope else isolation_scope + ) new_scopes = (new_scope, new_isolation_scope) new_context = set_value(SENTRY_SCOPES_KEY, new_scopes, context) diff --git a/sentry_sdk/integrations/opentelemetry/integration.py b/sentry_sdk/integrations/opentelemetry/integration.py index af16f53de9..4cd969f0e0 100644 --- a/sentry_sdk/integrations/opentelemetry/integration.py +++ b/sentry_sdk/integrations/opentelemetry/integration.py @@ -6,8 +6,12 @@ from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.integrations.opentelemetry.propagator import SentryPropagator -from sentry_sdk.integrations.opentelemetry.potel_span_processor import PotelSentrySpanProcessor -from sentry_sdk.integrations.opentelemetry.contextvars_context import SentryContextVarsRuntimeContext +from sentry_sdk.integrations.opentelemetry.potel_span_processor import ( + PotelSentrySpanProcessor, +) +from sentry_sdk.integrations.opentelemetry.contextvars_context import ( + SentryContextVarsRuntimeContext, +) from sentry_sdk.utils import logger try: @@ -47,8 +51,9 @@ def setup_once(): def _setup_sentry_tracing(): # type: () -> None - from opentelemetry.context import _RUNTIME_CONTEXT - _RUNTIME_CONTEXT = SentryContextVarsRuntimeContext() + import opentelemetry.context + + opentelemetry.context._RUNTIME_CONTEXT = SentryContextVarsRuntimeContext() provider = TracerProvider() provider.add_span_processor(PotelSentrySpanProcessor()) diff --git a/sentry_sdk/integrations/opentelemetry/scope.py b/sentry_sdk/integrations/opentelemetry/scope.py index c5634433c0..6d6f8f6acf 100644 --- a/sentry_sdk/integrations/opentelemetry/scope.py +++ b/sentry_sdk/integrations/opentelemetry/scope.py @@ -30,7 +30,7 @@ def get_current_scope(cls): """ Returns the current scope. """ - return cls._get_current_scope() or Scope(ty=ScopeType.CURRENT) + return cls._get_current_scope() or _INITIAL_CURRENT_SCOPE @classmethod def _get_current_scope(cls): @@ -47,7 +47,7 @@ def get_isolation_scope(cls): Returns the isolation scope. """ # type: () -> Scope - return cls._get_isolation_scope() or Scope(ty=ScopeType.ISOLATION) + return cls._get_isolation_scope() or _INITIAL_ISOLATION_SCOPE @classmethod def _get_isolation_scope(cls): @@ -59,6 +59,10 @@ def _get_isolation_scope(cls): return scopes[1] if scopes else None +_INITIAL_CURRENT_SCOPE = PotelScope(ty=ScopeType.CURRENT) +_INITIAL_ISOLATION_SCOPE = PotelScope(ty=ScopeType.ISOLATION) + + @contextmanager def isolation_scope(): # type: () -> Generator[Scope, None, None] diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index 5e8b9780b9..a4c7510faa 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -304,7 +304,6 @@ def _get_isolation_scope(cls): """ return _isolation_scope.get() - @classmethod def set_isolation_scope(cls, new_isolation_scope): # type: (Scope) -> None @@ -359,13 +358,11 @@ def _merge_scopes(self, additional_scope=None, additional_scope_kwargs=None): final_scope = copy(_global_scope) if _global_scope is not None else Scope() final_scope._type = ScopeType.MERGED - isolation_scope = self._get_isolation_scope() - if isolation_scope is not None: - final_scope.update_from_scope(isolation_scope) + isolation_scope = self.get_isolation_scope() + final_scope.update_from_scope(isolation_scope) - current_scope = self._get_current_scope() - if current_scope is not None: - final_scope.update_from_scope(current_scope) + current_scope = self.get_current_scope() + final_scope.update_from_scope(current_scope) if self != current_scope and self != isolation_scope: final_scope.update_from_scope(self) diff --git a/tests/conftest.py b/tests/conftest.py index c31a394fb5..46f08a0232 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -63,6 +63,7 @@ def benchmark(): from sentry_sdk import scope +import sentry_sdk.integrations.opentelemetry.scope as potel_scope @pytest.fixture(autouse=True) @@ -74,6 +75,9 @@ def clean_scopes(): scope._isolation_scope.set(None) scope._current_scope.set(None) + potel_scope._INITIAL_CURRENT_SCOPE.clear() + potel_scope._INITIAL_ISOLATION_SCOPE.clear() + @pytest.fixture(autouse=True) def internal_exceptions(request): diff --git a/tests/integrations/opentelemetry/test_potel.py b/tests/integrations/opentelemetry/test_potel.py index 31e5a52e65..0f609ceb50 100644 --- a/tests/integrations/opentelemetry/test_potel.py +++ b/tests/integrations/opentelemetry/test_potel.py @@ -258,6 +258,7 @@ def test_transaction_tags_started_with_otel(capture_envelopes): sentry_sdk.set_tag("tag.global", 99) with tracer.start_as_current_span("request"): sentry_sdk.set_tag("tag.inner", "foo") + print(sentry_sdk.get_isolation_scope()) (envelope,) = envelopes (item,) = envelope.items @@ -297,7 +298,9 @@ def test_multiple_transaction_tags_isolation_scope_started_with_otel(capture_env assert payload_b["tags"] == {"tag.global": 99, "tag.inner.b": "b"} -def test_multiple_transaction_tags_isolation_scope_started_with_sentry(capture_envelopes): +def test_multiple_transaction_tags_isolation_scope_started_with_sentry( + capture_envelopes, +): envelopes = capture_envelopes() sentry_sdk.set_tag("tag.global", 99) From bbbef7158db0e547410f98ffe3450672a679980c Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Mon, 5 Aug 2024 13:14:01 +0200 Subject: [PATCH 6/6] Update tests/integrations/opentelemetry/test_potel.py Co-authored-by: Ivana Kellyer --- tests/integrations/opentelemetry/test_potel.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/integrations/opentelemetry/test_potel.py b/tests/integrations/opentelemetry/test_potel.py index 0f609ceb50..2e094b41b5 100644 --- a/tests/integrations/opentelemetry/test_potel.py +++ b/tests/integrations/opentelemetry/test_potel.py @@ -258,7 +258,6 @@ def test_transaction_tags_started_with_otel(capture_envelopes): sentry_sdk.set_tag("tag.global", 99) with tracer.start_as_current_span("request"): sentry_sdk.set_tag("tag.inner", "foo") - print(sentry_sdk.get_isolation_scope()) (envelope,) = envelopes (item,) = envelope.items