Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Scope tests #3593

Draft
wants to merge 3 commits into
base: potel-base
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions sentry_sdk/integrations/opentelemetry/scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use_span,
)

from sentry_sdk.client import NonRecordingClient
from sentry_sdk.integrations.opentelemetry.consts import (
SENTRY_SCOPES_KEY,
SENTRY_FORK_ISOLATION_SCOPE_KEY,
Expand All @@ -26,10 +27,18 @@
from typing import Tuple, Optional, Generator, Dict, Any
from typing_extensions import Unpack

import sentry_sdk
from sentry_sdk._types import SamplingContext
from sentry_sdk.tracing import TransactionKwargs


# Holds data that will be added to **all** events sent by this process.
# In case this is a http server (think web framework) with multiple users
# the data will be added to events of all users.
# Typically this is used for process wide data such as the release.
_global_scope = None # type: Optional[Scope]


class PotelScope(Scope):
@classmethod
def _get_scopes(cls):
Expand Down Expand Up @@ -73,6 +82,59 @@ def _get_isolation_scope(cls):
scopes = cls._get_scopes()
return scopes[1] if scopes else None

@classmethod
def get_global_scope(cls):
# type: () -> Scope
"""
.. versionadded:: 2.0.0

Returns the global scope.
"""
global _global_scope
if _global_scope is None:
_global_scope = PotelScope(ty=ScopeType.GLOBAL)

return _global_scope

@classmethod
def get_client(cls):
# type: () -> sentry_sdk.client.BaseClient
"""
.. versionadded:: 2.0.0

Returns the currently used :py:class:`sentry_sdk.Client`.
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.
"""
scopes = cls._get_scopes()
if scopes:
current_scope, isolation_scope = scopes
try:
client = current_scope.client
except AttributeError:
client = None

if client is not None and client.is_active():
return client

try:
client = isolation_scope.client
except AttributeError:
client = None

if client is not None and client.is_active():
return client

try:
client = _global_scope.client # type: ignore
except AttributeError:
client = None

if client is not None and client.is_active():
return client

return NonRecordingClient()

@contextmanager
def continue_trace(self, environ_or_headers):
# type: (Dict[str, Any]) -> Generator[None, None, None]
Expand Down
52 changes: 26 additions & 26 deletions tests/test_scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
new_scope,
)
from sentry_sdk.client import Client, NonRecordingClient
from sentry_sdk.integrations.opentelemetry.scope import PotelScope as Scope
from sentry_sdk.scope import (
Scope,
ScopeType,
use_isolation_scope,
use_scope,
Expand Down Expand Up @@ -198,21 +198,18 @@ def test_scope_client():
def test_get_current_scope():
scope = Scope.get_current_scope()
assert scope is not None
assert scope.__class__ == Scope
assert scope._type == ScopeType.CURRENT


def test_get_isolation_scope():
scope = Scope.get_isolation_scope()
assert scope is not None
assert scope.__class__ == Scope
assert scope._type == ScopeType.ISOLATION


def test_get_global_scope():
scope = Scope.get_global_scope()
assert scope is not None
assert scope.__class__ == Scope
assert scope._type == ScopeType.GLOBAL


Expand All @@ -223,35 +220,38 @@ def test_get_client():
assert not client.is_active()


def test_set_client():
client1 = Client()
client2 = Client()
client3 = Client()
def test_set_client(sentry_init):
sentry_init()

current_scope = Scope.get_current_scope()
isolation_scope = Scope.get_isolation_scope()
global_scope = Scope.get_global_scope()
current_client = mock.MagicMock()
isolation_client = mock.MagicMock()
global_client = mock.MagicMock()

current_scope.set_client(client1)
isolation_scope.set_client(client2)
global_scope.set_client(client3)
with sentry_sdk.start_span():
current_scope = sentry_sdk.get_current_scope()
isolation_scope = sentry_sdk.get_isolation_scope()
global_scope = sentry_sdk.get_global_scope()

client = Scope.get_client()
assert client == client1
current_scope.set_client(current_client)
isolation_scope.set_client(isolation_client)
global_scope.set_client(global_client)

current_scope.set_client(None)
isolation_scope.set_client(client2)
global_scope.set_client(client3)
client = sentry_sdk.get_client()
assert client == current_client

client = Scope.get_client()
assert client == client2
current_scope.set_client(None)
isolation_scope.set_client(isolation_client)
global_scope.set_client(global_client)

current_scope.set_client(None)
isolation_scope.set_client(None)
global_scope.set_client(client3)
client = sentry_sdk.get_client()
assert client == isolation_client

client = Scope.get_client()
assert client == client3
current_scope.set_client(None)
isolation_scope.set_client(None)
global_scope.set_client(global_client)

client = sentry_sdk.get_client()
assert client == global_client


def test_fork():
Expand Down
Loading