From 8c75df6987253581c7803d1620ae8c350603ab71 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 19 Mar 2024 16:14:35 +0100 Subject: [PATCH 01/14] Updated atexit integration --- sentry_sdk/integrations/atexit.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/sentry_sdk/integrations/atexit.py b/sentry_sdk/integrations/atexit.py index 32bb312195..c3139e3b28 100644 --- a/sentry_sdk/integrations/atexit.py +++ b/sentry_sdk/integrations/atexit.py @@ -2,7 +2,8 @@ import sys import atexit -from sentry_sdk.hub import Hub +import sentry_sdk +from sentry_sdk import Scope from sentry_sdk.utils import logger from sentry_sdk.integrations import Integration @@ -46,14 +47,10 @@ def setup_once(): def _shutdown(): # type: () -> None logger.debug("atexit: got shutdown signal") - hub = Hub.main - integration = hub.get_integration(AtexitIntegration) + client = sentry_sdk.get_client() + integration = client.get_integration(AtexitIntegration) if integration is not None: logger.debug("atexit: shutting down client") - # If there is a session on the hub, close it now. - hub.end_session() - - # If an integration is there, a client has to be there. - client = hub.client # type: Any + Scope.get_isolation_scope().end_session() client.close(callback=integration.callback) From 0d2881c6c68842be53566d1264ed89ea9082031a Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 19 Mar 2024 16:16:05 +0100 Subject: [PATCH 02/14] Updated excepthook integration --- sentry_sdk/integrations/excepthook.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/sentry_sdk/integrations/excepthook.py b/sentry_sdk/integrations/excepthook.py index 514e082b31..a2146bee9e 100644 --- a/sentry_sdk/integrations/excepthook.py +++ b/sentry_sdk/integrations/excepthook.py @@ -1,6 +1,6 @@ import sys -from sentry_sdk.hub import Hub +import sentry_sdk from sentry_sdk.utils import capture_internal_exceptions, event_from_exception from sentry_sdk.integrations import Integration @@ -45,20 +45,16 @@ def _make_excepthook(old_excepthook): # type: (Excepthook) -> Excepthook def sentry_sdk_excepthook(type_, value, traceback): # type: (Type[BaseException], BaseException, Optional[TracebackType]) -> None - hub = Hub.current - integration = hub.get_integration(ExcepthookIntegration) + integration = sentry_sdk.get_client().get_integration(ExcepthookIntegration) if integration is not None and _should_send(integration.always_run): - # If an integration is there, a client has to be there. - client = hub.client # type: Any - with capture_internal_exceptions(): event, hint = event_from_exception( (type_, value, traceback), - client_options=client.options, + client_options=sentry_sdk.get_client().options, mechanism={"type": "excepthook", "handled": False}, ) - hub.capture_event(event, hint=hint) + sentry_sdk.capture_event(event, hint=hint) return old_excepthook(type_, value, traceback) From 1143e3c39c1fc8bbb1d20b9119d347c60fe3d7b2 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 19 Mar 2024 16:17:22 +0100 Subject: [PATCH 03/14] Updated dedupe integration --- sentry_sdk/integrations/dedupe.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sentry_sdk/integrations/dedupe.py b/sentry_sdk/integrations/dedupe.py index 04208f608a..02469b6911 100644 --- a/sentry_sdk/integrations/dedupe.py +++ b/sentry_sdk/integrations/dedupe.py @@ -1,4 +1,4 @@ -from sentry_sdk.hub import Hub +import sentry_sdk from sentry_sdk.utils import ContextVar from sentry_sdk.integrations import Integration from sentry_sdk.scope import add_global_event_processor @@ -27,8 +27,7 @@ def processor(event, hint): if hint is None: return event - integration = Hub.current.get_integration(DedupeIntegration) - + integration = sentry_sdk.get_client().get_integration(DedupeIntegration) if integration is None: return event From 41558a4dbfb7e83bbe903722677dab34f8c72eaa Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 19 Mar 2024 16:36:30 +0100 Subject: [PATCH 04/14] Updated stdlib integration --- sentry_sdk/integrations/stdlib.py | 48 +++++++++++++------------------ sentry_sdk/tracing_utils.py | 7 ++--- sentry_sdk/utils.py | 12 ++++---- tests/test_utils.py | 25 +++++++--------- tests/tracing/test_misc.py | 18 ++++++------ 5 files changed, 49 insertions(+), 61 deletions(-) diff --git a/sentry_sdk/integrations/stdlib.py b/sentry_sdk/integrations/stdlib.py index 289d75b306..fc04f4789f 100644 --- a/sentry_sdk/integrations/stdlib.py +++ b/sentry_sdk/integrations/stdlib.py @@ -4,14 +4,15 @@ import platform from http.client import HTTPConnection +import sentry_sdk from sentry_sdk.consts import OP, SPANDATA -from sentry_sdk.hub import Hub from sentry_sdk.integrations import Integration -from sentry_sdk.scope import add_global_event_processor +from sentry_sdk.scope import Scope, add_global_event_processor from sentry_sdk.tracing_utils import EnvironHeaders, should_propagate_trace from sentry_sdk.utils import ( SENSITIVE_DATA_SUBSTITUTE, capture_internal_exceptions, + ensure_integration_enabled, is_sentry_url, logger, safe_repr, @@ -48,7 +49,7 @@ def setup_once(): @add_global_event_processor def add_python_runtime_context(event, hint): # type: (Event, Hint) -> Optional[Event] - if Hub.current.get_integration(StdlibIntegration) is not None: + if sentry_sdk.get_client().get_integration(StdlibIntegration) is not None: contexts = event.setdefault("contexts", {}) if isinstance(contexts, dict) and "runtime" not in contexts: contexts["runtime"] = _RUNTIME_CONTEXT @@ -63,13 +64,14 @@ def _install_httplib(): def putrequest(self, method, url, *args, **kwargs): # type: (HTTPConnection, str, str, *Any, **Any) -> Any - hub = Hub.current - host = self.host port = self.port default_port = self.default_port - if hub.get_integration(StdlibIntegration) is None or is_sentry_url(hub, host): + client = sentry_sdk.get_client() + if client.get_integration(StdlibIntegration) is None or is_sentry_url( + client, host + ): return real_putrequest(self, method, url, *args, **kwargs) real_url = url @@ -85,7 +87,7 @@ def putrequest(self, method, url, *args, **kwargs): with capture_internal_exceptions(): parsed_url = parse_url(real_url, sanitize=False) - span = hub.start_span( + span = sentry_sdk.start_span( op=OP.HTTP_CLIENT, description="%s %s" % (method, parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE), @@ -99,8 +101,10 @@ def putrequest(self, method, url, *args, **kwargs): rv = real_putrequest(self, method, url, *args, **kwargs) - if should_propagate_trace(hub, real_url): - for key, value in hub.iter_trace_propagation_headers(span): + if should_propagate_trace(client, real_url): + for key, value in Scope.get_current_scope().iter_trace_propagation_headers( + span + ): logger.debug( "[Tracing] Adding `{key}` header {value} to outgoing request to {real_url}.".format( key=key, value=value, real_url=real_url @@ -166,13 +170,9 @@ def _install_subprocess(): # type: () -> None old_popen_init = subprocess.Popen.__init__ + @ensure_integration_enabled(StdlibIntegration, old_popen_init) def sentry_patched_popen_init(self, *a, **kw): # type: (subprocess.Popen[Any], *Any, **Any) -> None - - hub = Hub.current - if hub.get_integration(StdlibIntegration) is None: - return old_popen_init(self, *a, **kw) - # Convert from tuple to list to be able to set values. a = list(a) @@ -197,8 +197,8 @@ def sentry_patched_popen_init(self, *a, **kw): env = None - with hub.start_span(op=OP.SUBPROCESS, description=description) as span: - for k, v in hub.iter_trace_propagation_headers(span): + with sentry_sdk.start_span(op=OP.SUBPROCESS, description=description) as span: + for k, v in Scope.get_current_scope().iter_trace_propagation_headers(span): if env is None: env = _init_argument( a, kw, "env", 10, lambda x: dict(x or os.environ) @@ -217,14 +217,10 @@ def sentry_patched_popen_init(self, *a, **kw): old_popen_wait = subprocess.Popen.wait + @ensure_integration_enabled(StdlibIntegration, old_popen_wait) def sentry_patched_popen_wait(self, *a, **kw): # type: (subprocess.Popen[Any], *Any, **Any) -> Any - hub = Hub.current - - if hub.get_integration(StdlibIntegration) is None: - return old_popen_wait(self, *a, **kw) - - with hub.start_span(op=OP.SUBPROCESS_WAIT) as span: + with sentry_sdk.start_span(op=OP.SUBPROCESS_WAIT) as span: span.set_tag("subprocess.pid", self.pid) return old_popen_wait(self, *a, **kw) @@ -232,14 +228,10 @@ def sentry_patched_popen_wait(self, *a, **kw): old_popen_communicate = subprocess.Popen.communicate + @ensure_integration_enabled(StdlibIntegration, old_popen_communicate) def sentry_patched_popen_communicate(self, *a, **kw): # type: (subprocess.Popen[Any], *Any, **Any) -> Any - hub = Hub.current - - if hub.get_integration(StdlibIntegration) is None: - return old_popen_communicate(self, *a, **kw) - - with hub.start_span(op=OP.SUBPROCESS_COMMUNICATE) as span: + with sentry_sdk.start_span(op=OP.SUBPROCESS_COMMUNICATE) as span: span.set_tag("subprocess.pid", self.pid) return old_popen_communicate(self, *a, **kw) diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py index b2df88479a..1486850f74 100644 --- a/sentry_sdk/tracing_utils.py +++ b/sentry_sdk/tracing_utils.py @@ -475,15 +475,14 @@ def serialize(self, include_third_party=False): return ",".join(items) -def should_propagate_trace(hub, url): - # type: (sentry_sdk.Hub, str) -> bool +def should_propagate_trace(client, url): + # type: (sentry_sdk.client.BaseClient, str) -> bool """ Returns True if url matches trace_propagation_targets configured in the given hub. Otherwise, returns False. """ - client = hub.client # type: Any trace_propagation_targets = client.options["trace_propagation_targets"] - if is_sentry_url(hub, url): + if is_sentry_url(client, url): return False return match_regex_list(url, trace_propagation_targets, substring_matching=True) diff --git a/sentry_sdk/utils.py b/sentry_sdk/utils.py index f170e97b7e..da1d5b9e06 100644 --- a/sentry_sdk/utils.py +++ b/sentry_sdk/utils.py @@ -1558,16 +1558,16 @@ def match_regex_list(item, regex_list=None, substring_matching=False): return False -def is_sentry_url(hub, url): - # type: (sentry_sdk.Hub, str) -> bool +def is_sentry_url(client, url): + # type: (sentry_sdk.client.BaseClient, str) -> bool """ Determines whether the given URL matches the Sentry DSN. """ return ( - hub.client is not None - and hub.client.transport is not None - and hub.client.transport.parsed_dsn is not None - and hub.client.transport.parsed_dsn.netloc in url + client is not None + and client.transport is not None + and client.transport.parsed_dsn is not None + and client.transport.parsed_dsn.netloc in url ) diff --git a/tests/test_utils.py b/tests/test_utils.py index e5dda7d57e..ef7ec89e1c 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -441,19 +441,17 @@ def test_parse_version(version, expected_result): @pytest.fixture -def mock_hub_with_dsn_netloc(): +def mock_client_with_dsn_netloc(): """ Returns a mocked hub with a DSN netloc of "abcd1234.ingest.sentry.io". """ + mock_client = mock.Mock(spec=sentry_sdk.Client) + mock_client.transport = mock.Mock(spec=sentry_sdk.Transport) + mock_client.transport.parsed_dsn = mock.Mock(spec=Dsn) - mock_hub = mock.Mock(spec=sentry_sdk.Hub) - mock_hub.client = mock.Mock(spec=sentry_sdk.Client) - mock_hub.client.transport = mock.Mock(spec=sentry_sdk.Transport) - mock_hub.client.transport.parsed_dsn = mock.Mock(spec=Dsn) + mock_client.transport.parsed_dsn.netloc = "abcd1234.ingest.sentry.io" - mock_hub.client.transport.parsed_dsn.netloc = "abcd1234.ingest.sentry.io" - - return mock_hub + return mock_client @pytest.mark.parametrize( @@ -463,19 +461,18 @@ def mock_hub_with_dsn_netloc(): ["https://asdf@abcd1234.ingest.notsentry.io/123456789", False], ], ) -def test_is_sentry_url_true(test_url, is_sentry_url_expected, mock_hub_with_dsn_netloc): - ret_val = is_sentry_url(mock_hub_with_dsn_netloc, test_url) +def test_is_sentry_url_true( + test_url, is_sentry_url_expected, mock_client_with_dsn_netloc +): + ret_val = is_sentry_url(mock_client_with_dsn_netloc, test_url) assert ret_val == is_sentry_url_expected def test_is_sentry_url_no_client(): - hub = mock.Mock() - hub.client = None - test_url = "https://asdf@abcd1234.ingest.sentry.io/123456789" - ret_val = is_sentry_url(hub, test_url) + ret_val = is_sentry_url(None, test_url) assert not ret_val diff --git a/tests/tracing/test_misc.py b/tests/tracing/test_misc.py index 7b024871e4..426043cb07 100644 --- a/tests/tracing/test_misc.py +++ b/tests/tracing/test_misc.py @@ -298,17 +298,16 @@ def test_set_meaurement_public_api(sentry_init, capture_events): def test_should_propagate_trace( trace_propagation_targets, url, expected_propagation_decision ): - hub = MagicMock() - hub.client = MagicMock() + client = MagicMock() # This test assumes the urls are not Sentry URLs. Use test_should_propagate_trace_to_sentry for sentry URLs. - hub.is_sentry_url = lambda _: False + client.is_sentry_url = lambda _: False - hub.client.options = {"trace_propagation_targets": trace_propagation_targets} - hub.client.transport = MagicMock() - hub.client.transport.parsed_dsn = Dsn("https://bla@xxx.sentry.io/12312012") + client.options = {"trace_propagation_targets": trace_propagation_targets} + client.transport = MagicMock() + client.transport.parsed_dsn = Dsn("https://bla@xxx.sentry.io/12312012") - assert should_propagate_trace(hub, url) == expected_propagation_decision + assert should_propagate_trace(client, url) == expected_propagation_decision @pytest.mark.parametrize( @@ -349,9 +348,10 @@ def test_should_propagate_trace_to_sentry( traces_sample_rate=1.0, ) - Hub.current.client.transport.parsed_dsn = Dsn(dsn) + client = sentry_sdk.get_client() + client.transport.parsed_dsn = Dsn(dsn) - assert should_propagate_trace(Hub.current, url) == expected_propagation_decision + assert should_propagate_trace(client, url) == expected_propagation_decision def test_start_transaction_updates_scope_name_source(sentry_init): From adf5288083308d6d2c4c6deb25b53f64c6e42d73 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 19 Mar 2024 16:37:29 +0100 Subject: [PATCH 05/14] Updated modules integration --- sentry_sdk/integrations/modules.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/integrations/modules.py b/sentry_sdk/integrations/modules.py index 9ec1f7e98f..6376d25a30 100644 --- a/sentry_sdk/integrations/modules.py +++ b/sentry_sdk/integrations/modules.py @@ -1,4 +1,4 @@ -from sentry_sdk.hub import Hub +import sentry_sdk from sentry_sdk.integrations import Integration from sentry_sdk.scope import add_global_event_processor from sentry_sdk.utils import _get_installed_modules @@ -22,7 +22,7 @@ def processor(event, hint): if event.get("type") == "transaction": return event - if Hub.current.get_integration(ModulesIntegration) is None: + if sentry_sdk.get_client().get_integration(ModulesIntegration) is None: return event event["modules"] = _get_installed_modules() From 432d2e598b9f00cc4eb80d051bbe022e4aaeafe1 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Tue, 19 Mar 2024 16:38:24 +0100 Subject: [PATCH 06/14] Updated argv integration --- sentry_sdk/integrations/argv.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/integrations/argv.py b/sentry_sdk/integrations/argv.py index ea2c007e7e..3154f0c431 100644 --- a/sentry_sdk/integrations/argv.py +++ b/sentry_sdk/integrations/argv.py @@ -1,6 +1,6 @@ import sys -from sentry_sdk.hub import Hub +import sentry_sdk from sentry_sdk.integrations import Integration from sentry_sdk.scope import add_global_event_processor @@ -21,7 +21,7 @@ def setup_once(): @add_global_event_processor def processor(event, hint): # type: (Event, Optional[Hint]) -> Optional[Event] - if Hub.current.get_integration(ArgvIntegration) is not None: + if sentry_sdk.get_client().get_integration(ArgvIntegration) is not None: extra = event.setdefault("extra", {}) # If some event processor decided to set extra to e.g. an # `int`, don't crash. Not here. From 04bc5d7eef7172c6fcac9ab3f18272a312f9e835 Mon Sep 17 00:00:00 2001 From: Ivana Kellyerova Date: Tue, 19 Mar 2024 16:58:11 +0100 Subject: [PATCH 07/14] Update aiohttp --- sentry_sdk/integrations/aiohttp.py | 61 ++++++++++++++---------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py index 57051ffa6c..d81088669e 100644 --- a/sentry_sdk/integrations/aiohttp.py +++ b/sentry_sdk/integrations/aiohttp.py @@ -1,9 +1,9 @@ import sys import weakref +import sentry_sdk from sentry_sdk.api import continue_trace from sentry_sdk.consts import OP, SPANDATA -from sentry_sdk.hub import Hub from sentry_sdk.integrations import Integration, DidNotEnable from sentry_sdk.integrations.logging import ignore_logger from sentry_sdk.scope import Scope @@ -20,6 +20,8 @@ from sentry_sdk.tracing_utils import should_propagate_trace from sentry_sdk.utils import ( capture_internal_exceptions, + ensure_integration_enabled, + ensure_integration_enabled_async, event_from_exception, logger, parse_url, @@ -96,21 +98,17 @@ def setup_once(): old_handle = Application._handle + @ensure_integration_enabled_async(AioHttpIntegration, old_handle) async def sentry_app_handle(self, request, *args, **kwargs): # type: (Any, Request, *Any, **Any) -> Any - hub = Hub.current - if hub.get_integration(AioHttpIntegration) is None: - return await old_handle(self, request, *args, **kwargs) - weak_request = weakref.ref(request) - with Hub(hub) as hub: - with auto_session_tracking(hub, session_mode="request"): + with sentry_sdk.isolation_scope() as scope: + with auto_session_tracking(scope, session_mode="request"): # Scope data will not leak between requests because aiohttp # create a task to wrap each request. - with hub.configure_scope() as scope: - scope.clear_breadcrumbs() - scope.add_event_processor(_make_request_processor(weak_request)) + scope.clear_breadcrumbs() + scope.add_event_processor(_make_request_processor(weak_request)) headers = dict(request.headers) transaction = continue_trace( @@ -121,7 +119,7 @@ async def sentry_app_handle(self, request, *args, **kwargs): name="generic AIOHTTP request", source=TRANSACTION_SOURCE_ROUTE, ) - with hub.start_transaction( + with sentry_sdk.start_transaction( transaction, custom_sampling_context={"aiohttp_request": request}, ): @@ -136,7 +134,7 @@ async def sentry_app_handle(self, request, *args, **kwargs): except Exception: # This will probably map to a 500 but seems like we # have no way to tell. Do not set span status. - reraise(*_capture_exception(hub)) + reraise(*_capture_exception()) transaction.set_http_status(response.status) return response @@ -149,8 +147,7 @@ async def sentry_urldispatcher_resolve(self, request): # type: (UrlDispatcher, Request) -> UrlMappingMatchInfo rv = await old_urldispatcher_resolve(self, request) - hub = Hub.current - integration = hub.get_integration(AioHttpIntegration) + integration = sentry_sdk.get_client().get_integration(AioHttpIntegration) name = None @@ -176,12 +173,9 @@ async def sentry_urldispatcher_resolve(self, request): old_client_session_init = ClientSession.__init__ + @ensure_integration_enabled(AioHttpIntegration, old_client_session_init) def init(*args, **kwargs): # type: (Any, Any) -> None - hub = Hub.current - if hub.get_integration(AioHttpIntegration) is None: - return old_client_session_init(*args, **kwargs) - client_trace_configs = list(kwargs.get("trace_configs") or ()) trace_config = create_trace_config() client_trace_configs.append(trace_config) @@ -194,10 +188,11 @@ def init(*args, **kwargs): def create_trace_config(): # type: () -> TraceConfig + async def on_request_start(session, trace_config_ctx, params): # type: (ClientSession, SimpleNamespace, TraceRequestStartParams) -> None - hub = Hub.current - if hub.get_integration(AioHttpIntegration) is None: + client = sentry_sdk.get_client() + if client.get_integration(AioHttpIntegration) is None: return method = params.method.upper() @@ -206,7 +201,7 @@ async def on_request_start(session, trace_config_ctx, params): with capture_internal_exceptions(): parsed_url = parse_url(str(params.url), sanitize=False) - span = hub.start_span( + span = sentry_sdk.start_span( op=OP.HTTP_CLIENT, description="%s %s" % (method, parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE), @@ -217,8 +212,10 @@ async def on_request_start(session, trace_config_ctx, params): span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) - if should_propagate_trace(hub, str(params.url)): - for key, value in hub.iter_trace_propagation_headers(span): + if should_propagate_trace(client, str(params.url)): + for key, value in Scope.get_current_scope().iter_trace_propagation_headers( + span + ): logger.debug( "[Tracing] Adding `{key}` header {value} to outgoing request to {url}.".format( key=key, value=value, url=params.url @@ -275,42 +272,40 @@ def aiohttp_processor( request_info["query_string"] = request.query_string request_info["method"] = request.method request_info["env"] = {"REMOTE_ADDR": request.remote} - - hub = Hub.current request_info["headers"] = _filter_headers(dict(request.headers)) # Just attach raw data here if it is within bounds, if available. # Unfortunately there's no way to get structured data from aiohttp # without awaiting on some coroutine. - request_info["data"] = get_aiohttp_request_data(hub, request) + request_info["data"] = get_aiohttp_request_data(request) return event return aiohttp_processor -def _capture_exception(hub): - # type: (Hub) -> ExcInfo +def _capture_exception(): + # type: () -> ExcInfo exc_info = sys.exc_info() event, hint = event_from_exception( exc_info, - client_options=hub.client.options, # type: ignore + client_options=sentry_sdk.get_client().options, mechanism={"type": "aiohttp", "handled": False}, ) - hub.capture_event(event, hint=hint) + sentry_sdk.capture_event(event, hint=hint) return exc_info BODY_NOT_READ_MESSAGE = "[Can't show request body due to implementation details.]" -def get_aiohttp_request_data(hub, request): - # type: (Hub, Request) -> Union[Optional[str], AnnotatedValue] +def get_aiohttp_request_data(request): + # type: (Request) -> Union[Optional[str], AnnotatedValue] bytes_body = request._read_bytes if bytes_body is not None: # we have body to show - if not request_body_within_bounds(hub.client, len(bytes_body)): + if not request_body_within_bounds(sentry_sdk.get_client(), len(bytes_body)): return AnnotatedValue.removed_because_over_size_limit() encoding = request.charset or "utf-8" From 3ea0654aaf317084ebf7a4806d9a173f55df2db2 Mon Sep 17 00:00:00 2001 From: Daniel Szoke Date: Tue, 19 Mar 2024 16:57:22 +0100 Subject: [PATCH 08/14] update httpx integration --- sentry_sdk/integrations/httpx.py | 33 +++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/sentry_sdk/integrations/httpx.py b/sentry_sdk/integrations/httpx.py index 04db5047b4..3845591d95 100644 --- a/sentry_sdk/integrations/httpx.py +++ b/sentry_sdk/integrations/httpx.py @@ -1,11 +1,14 @@ -from sentry_sdk import Hub +import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import Integration, DidNotEnable +from sentry_sdk.scope import Scope from sentry_sdk.tracing import BAGGAGE_HEADER_NAME from sentry_sdk.tracing_utils import should_propagate_trace from sentry_sdk.utils import ( SENSITIVE_DATA_SUBSTITUTE, capture_internal_exceptions, + ensure_integration_enabled, + ensure_integration_enabled_async, logger, parse_url, ) @@ -42,17 +45,14 @@ def _install_httpx_client(): # type: () -> None real_send = Client.send + @ensure_integration_enabled(HttpxIntegration, real_send) def send(self, request, **kwargs): # type: (Client, Request, **Any) -> Response - hub = Hub.current - if hub.get_integration(HttpxIntegration) is None: - return real_send(self, request, **kwargs) - parsed_url = None with capture_internal_exceptions(): parsed_url = parse_url(str(request.url), sanitize=False) - with hub.start_span( + with sentry_sdk.start_span( op=OP.HTTP_CLIENT, description="%s %s" % ( @@ -66,8 +66,11 @@ def send(self, request, **kwargs): span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) - if should_propagate_trace(hub, str(request.url)): - for key, value in hub.iter_trace_propagation_headers(): + if should_propagate_trace(sentry_sdk.get_client(), str(request.url)): + for ( + key, + value, + ) in Scope.get_current_scope().iter_trace_propagation_headers(): logger.debug( "[Tracing] Adding `{key}` header {value} to outgoing request to {url}.".format( key=key, value=value, url=request.url @@ -95,17 +98,14 @@ def _install_httpx_async_client(): # type: () -> None real_send = AsyncClient.send + @ensure_integration_enabled_async(HttpxIntegration, real_send) async def send(self, request, **kwargs): # type: (AsyncClient, Request, **Any) -> Response - hub = Hub.current - if hub.get_integration(HttpxIntegration) is None: - return await real_send(self, request, **kwargs) - parsed_url = None with capture_internal_exceptions(): parsed_url = parse_url(str(request.url), sanitize=False) - with hub.start_span( + with sentry_sdk.start_span( op=OP.HTTP_CLIENT, description="%s %s" % ( @@ -119,8 +119,11 @@ async def send(self, request, **kwargs): span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) - if should_propagate_trace(hub, str(request.url)): - for key, value in hub.iter_trace_propagation_headers(): + if should_propagate_trace(sentry_sdk.get_client(), str(request.url)): + for ( + key, + value, + ) in Scope.get_current_scope().iter_trace_propagation_headers(): logger.debug( "[Tracing] Adding `{key}` header {value} to outgoing request to {url}.".format( key=key, value=value, url=request.url From e60dda3580948db2741e4a0a6e60dba09c5383e4 Mon Sep 17 00:00:00 2001 From: Ivana Kellyerova Date: Tue, 19 Mar 2024 17:03:18 +0100 Subject: [PATCH 09/14] aiohttp: fix auto_session_tracking --- sentry_sdk/integrations/aiohttp.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py index d81088669e..cdb05facad 100644 --- a/sentry_sdk/integrations/aiohttp.py +++ b/sentry_sdk/integrations/aiohttp.py @@ -7,7 +7,7 @@ from sentry_sdk.integrations import Integration, DidNotEnable from sentry_sdk.integrations.logging import ignore_logger from sentry_sdk.scope import Scope -from sentry_sdk.sessions import auto_session_tracking +from sentry_sdk.sessions import auto_session_tracking_scope from sentry_sdk.integrations._wsgi_common import ( _filter_headers, request_body_within_bounds, @@ -104,7 +104,7 @@ async def sentry_app_handle(self, request, *args, **kwargs): weak_request = weakref.ref(request) with sentry_sdk.isolation_scope() as scope: - with auto_session_tracking(scope, session_mode="request"): + with auto_session_tracking_scope(scope, session_mode="request"): # Scope data will not leak between requests because aiohttp # create a task to wrap each request. scope.clear_breadcrumbs() From 27d2e8183e4c4390719a9bbfef39bb1d48b7cf8c Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 20 Mar 2024 12:45:52 +0100 Subject: [PATCH 10/14] Update sentry_sdk/tracing_utils.py Co-authored-by: Daniel Szoke --- sentry_sdk/tracing_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py index 1486850f74..a272efef82 100644 --- a/sentry_sdk/tracing_utils.py +++ b/sentry_sdk/tracing_utils.py @@ -478,7 +478,7 @@ def serialize(self, include_third_party=False): def should_propagate_trace(client, url): # type: (sentry_sdk.client.BaseClient, str) -> bool """ - Returns True if url matches trace_propagation_targets configured in the given hub. Otherwise, returns False. + Returns True if url matches trace_propagation_targets configured in the given client. Otherwise, returns False. """ trace_propagation_targets = client.options["trace_propagation_targets"] From e8f05944e6db6a200ede1a32f1ebc7733565e6fd Mon Sep 17 00:00:00 2001 From: Ivana Kellyerova Date: Wed, 20 Mar 2024 12:52:14 +0100 Subject: [PATCH 11/14] aiohttp fix? --- sentry_sdk/integrations/aiohttp.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py index cdb05facad..7da2cf33f2 100644 --- a/sentry_sdk/integrations/aiohttp.py +++ b/sentry_sdk/integrations/aiohttp.py @@ -107,6 +107,7 @@ async def sentry_app_handle(self, request, *args, **kwargs): with auto_session_tracking_scope(scope, session_mode="request"): # Scope data will not leak between requests because aiohttp # create a task to wrap each request. + scope.generate_propagation_context() scope.clear_breadcrumbs() scope.add_event_processor(_make_request_processor(weak_request)) From f155b266e77a70fa91f41c3baf38304e05f5b1fd Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 20 Mar 2024 14:36:49 +0100 Subject: [PATCH 12/14] Fixed span propagation --- sentry_sdk/integrations/stdlib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/integrations/stdlib.py b/sentry_sdk/integrations/stdlib.py index fc04f4789f..6e35f8a52c 100644 --- a/sentry_sdk/integrations/stdlib.py +++ b/sentry_sdk/integrations/stdlib.py @@ -103,7 +103,7 @@ def putrequest(self, method, url, *args, **kwargs): if should_propagate_trace(client, real_url): for key, value in Scope.get_current_scope().iter_trace_propagation_headers( - span + span=span ): logger.debug( "[Tracing] Adding `{key}` header {value} to outgoing request to {real_url}.".format( @@ -198,7 +198,7 @@ def sentry_patched_popen_init(self, *a, **kw): env = None with sentry_sdk.start_span(op=OP.SUBPROCESS, description=description) as span: - for k, v in Scope.get_current_scope().iter_trace_propagation_headers(span): + for k, v in Scope.get_current_scope().iter_trace_propagation_headers(span=span): if env is None: env = _init_argument( a, kw, "env", 10, lambda x: dict(x or os.environ) From 92624c3c78fc2c3fe55e2fa996e0e9519bc24a6f Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 20 Mar 2024 14:39:01 +0100 Subject: [PATCH 13/14] linting --- sentry_sdk/integrations/stdlib.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sentry_sdk/integrations/stdlib.py b/sentry_sdk/integrations/stdlib.py index 6e35f8a52c..62899e9a1b 100644 --- a/sentry_sdk/integrations/stdlib.py +++ b/sentry_sdk/integrations/stdlib.py @@ -198,7 +198,9 @@ def sentry_patched_popen_init(self, *a, **kw): env = None with sentry_sdk.start_span(op=OP.SUBPROCESS, description=description) as span: - for k, v in Scope.get_current_scope().iter_trace_propagation_headers(span=span): + for k, v in Scope.get_current_scope().iter_trace_propagation_headers( + span=span + ): if env is None: env = _init_argument( a, kw, "env", 10, lambda x: dict(x or os.environ) From 26641467137b554303c120d6f3bad0ce7cd6995b Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Wed, 20 Mar 2024 14:43:27 +0100 Subject: [PATCH 14/14] Fixed trace propagation headers in aiohttp --- sentry_sdk/integrations/aiohttp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py index 7da2cf33f2..bfdd4e5472 100644 --- a/sentry_sdk/integrations/aiohttp.py +++ b/sentry_sdk/integrations/aiohttp.py @@ -215,7 +215,7 @@ async def on_request_start(session, trace_config_ctx, params): if should_propagate_trace(client, str(params.url)): for key, value in Scope.get_current_scope().iter_trace_propagation_headers( - span + span=span ): logger.debug( "[Tracing] Adding `{key}` header {value} to outgoing request to {url}.".format(