diff --git a/CHANGELOG.md b/CHANGELOG.md index 39eca9b5c2..16a3072db5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## 2.0.1 + +### Various fixes & improvements + +- Fix: Do not use convenience decorator (#3022) by @sentrivana +- Refactoring propagation context (#2970) by @antonpirker +- Use `pid` for test database name in Django tests (#2998) by @antonpirker +- Remove outdated RC mention in docs (#3018) by @sentrivana +- Delete inaccurate comment from docs (#3002) by @szokeasaurusrex +- Add Lambda function that deletes test Lambda functions (#2960) by @antonpirker +- Correct discarded transaction debug message (#3002) by @szokeasaurusrex +- Add tests for discarded transaction debug messages (#3002) by @szokeasaurusrex +- Fix comment typo in metrics (#2992) by @szokeasaurusrex +- build(deps): bump actions/checkout from 4.1.1 to 4.1.4 (#3011) by @dependabot +- build(deps): bump checkouts/data-schemas from `1e17eb5` to `4aa14a7` (#2997) by @dependabot + ## 2.0.0 This is the first major update in a *long* time! diff --git a/docs/conf.py b/docs/conf.py index ed934f8b34..ae1ab934b3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -28,7 +28,7 @@ copyright = "2019-{}, Sentry Team and Contributors".format(datetime.now().year) author = "Sentry Team and Contributors" -release = "2.0.0" +release = "2.0.1" version = ".".join(release.split(".")[:2]) # The short X.Y version. diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py index 1be6536ca5..19595ed7fa 100644 --- a/sentry_sdk/consts.py +++ b/sentry_sdk/consts.py @@ -429,4 +429,4 @@ def _get_default_options(): del _get_default_options -VERSION = "2.0.0" +VERSION = "2.0.1" diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py index 91d812369c..9edaaf5cc9 100644 --- a/sentry_sdk/integrations/aiohttp.py +++ b/sentry_sdk/integrations/aiohttp.py @@ -21,7 +21,6 @@ from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, - ensure_integration_enabled_async, event_from_exception, logger, parse_url, @@ -98,9 +97,11 @@ 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 + if sentry_sdk.get_client().get_integration(AioHttpIntegration) is None: + return await old_handle(self, request, *args, **kwargs) + weak_request = weakref.ref(request) with sentry_sdk.isolation_scope() as scope: @@ -190,9 +191,11 @@ def init(*args, **kwargs): def create_trace_config(): # type: () -> TraceConfig - @ensure_integration_enabled_async(AioHttpIntegration) async def on_request_start(session, trace_config_ctx, params): # type: (ClientSession, SimpleNamespace, TraceRequestStartParams) -> None + if sentry_sdk.get_client().get_integration(AioHttpIntegration) is None: + return + method = params.method.upper() parsed_url = None diff --git a/sentry_sdk/integrations/arq.py b/sentry_sdk/integrations/arq.py index 384d2e03d0..12f73aa95f 100644 --- a/sentry_sdk/integrations/arq.py +++ b/sentry_sdk/integrations/arq.py @@ -10,7 +10,6 @@ from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, - ensure_integration_enabled_async, event_from_exception, SENSITIVE_DATA_SUBSTITUTE, parse_version, @@ -71,9 +70,12 @@ def patch_enqueue_job(): # type: () -> None old_enqueue_job = ArqRedis.enqueue_job - @ensure_integration_enabled_async(ArqIntegration, old_enqueue_job) async def _sentry_enqueue_job(self, function, *args, **kwargs): # type: (ArqRedis, str, *Any, **Any) -> Optional[Job] + integration = sentry_sdk.get_client().get_integration(ArqIntegration) + if integration is None: + return await old_enqueue_job(self, function, *args, **kwargs) + with sentry_sdk.start_span(op=OP.QUEUE_SUBMIT_ARQ, description=function): return await old_enqueue_job(self, function, *args, **kwargs) @@ -84,9 +86,12 @@ def patch_run_job(): # type: () -> None old_run_job = Worker.run_job - @ensure_integration_enabled_async(ArqIntegration, old_run_job) async def _sentry_run_job(self, job_id, score): # type: (Worker, str, int) -> None + integration = sentry_sdk.get_client().get_integration(ArqIntegration) + if integration is None: + return await old_run_job(self, job_id, score) + with sentry_sdk.isolation_scope() as scope: scope._name = "arq" scope.clear_breadcrumbs() @@ -157,9 +162,12 @@ def event_processor(event, hint): def _wrap_coroutine(name, coroutine): # type: (str, WorkerCoroutine) -> WorkerCoroutine - @ensure_integration_enabled_async(ArqIntegration, coroutine) async def _sentry_coroutine(ctx, *args, **kwargs): # type: (Dict[Any, Any], *Any, **Any) -> Any + integration = sentry_sdk.get_client().get_integration(ArqIntegration) + if integration is None: + return await coroutine(ctx, *args, **kwargs) + Scope.get_isolation_scope().add_event_processor( _make_event_processor({**ctx, "job_name": name}, *args, **kwargs) ) diff --git a/sentry_sdk/integrations/asyncpg.py b/sentry_sdk/integrations/asyncpg.py index f538934bc2..cfcb8a0528 100644 --- a/sentry_sdk/integrations/asyncpg.py +++ b/sentry_sdk/integrations/asyncpg.py @@ -9,7 +9,6 @@ from sentry_sdk.tracing_utils import add_query_source, record_sql_queries from sentry_sdk.utils import ( ensure_integration_enabled, - ensure_integration_enabled_async, parse_version, capture_internal_exceptions, ) @@ -58,8 +57,10 @@ def setup_once() -> None: def _wrap_execute(f: Callable[..., Awaitable[T]]) -> Callable[..., Awaitable[T]]: - @ensure_integration_enabled_async(AsyncPGIntegration, f) async def _inner(*args: Any, **kwargs: Any) -> T: + if sentry_sdk.get_client().get_integration(AsyncPGIntegration) is None: + return await f(*args, **kwargs) + # Avoid recording calls to _execute twice. # Calls to Connection.execute with args also call # Connection._execute, which is recorded separately @@ -110,8 +111,9 @@ def _record( def _wrap_connection_method( f: Callable[..., Awaitable[T]], *, executemany: bool = False ) -> Callable[..., Awaitable[T]]: - @ensure_integration_enabled_async(AsyncPGIntegration, f) async def _inner(*args: Any, **kwargs: Any) -> T: + if sentry_sdk.get_client().get_integration(AsyncPGIntegration) is None: + return await f(*args, **kwargs) query = args[1] params_list = args[2] if len(args) > 2 else None with _record(None, query, params_list, executemany=executemany) as span: @@ -145,8 +147,10 @@ def _inner(*args: Any, **kwargs: Any) -> T: # noqa: N807 def _wrap_connect_addr(f: Callable[..., Awaitable[T]]) -> Callable[..., Awaitable[T]]: - @ensure_integration_enabled_async(AsyncPGIntegration, f) async def _inner(*args: Any, **kwargs: Any) -> T: + if sentry_sdk.get_client().get_integration(AsyncPGIntegration) is None: + return await f(*args, **kwargs) + user = kwargs["params"].user database = kwargs["params"].database diff --git a/sentry_sdk/integrations/django/asgi.py b/sentry_sdk/integrations/django/asgi.py index bb060b1de2..b52ca6dd33 100644 --- a/sentry_sdk/integrations/django/asgi.py +++ b/sentry_sdk/integrations/django/asgi.py @@ -21,7 +21,6 @@ from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, - ensure_integration_enabled_async, ) @@ -72,9 +71,11 @@ def patch_django_asgi_handler_impl(cls): old_app = cls.__call__ - @ensure_integration_enabled_async(DjangoIntegration, old_app) async def sentry_patched_asgi_handler(self, scope, receive, send): # type: (Any, Any, Any, Any) -> Any + if sentry_sdk.get_client().get_integration(DjangoIntegration) is None: + return await old_app(self, scope, receive, send) + middleware = SentryAsgiMiddleware( old_app.__get__(self, cls), unsafe_context_data=True )._run_asgi3 @@ -120,9 +121,11 @@ def patch_channels_asgi_handler_impl(cls): if channels.__version__ < "3.0.0": old_app = cls.__call__ - @ensure_integration_enabled_async(DjangoIntegration, old_app) async def sentry_patched_asgi_handler(self, receive, send): # type: (Any, Any, Any) -> Any + if sentry_sdk.get_client().get_integration(DjangoIntegration) is None: + return await old_app(self, receive, send) + middleware = SentryAsgiMiddleware( lambda _scope: old_app.__get__(self, cls), unsafe_context_data=True ) diff --git a/sentry_sdk/integrations/fastapi.py b/sentry_sdk/integrations/fastapi.py index a6fed8f620..8fd18fef96 100644 --- a/sentry_sdk/integrations/fastapi.py +++ b/sentry_sdk/integrations/fastapi.py @@ -10,7 +10,6 @@ from sentry_sdk.utils import ( transaction_from_function, logger, - ensure_integration_enabled_async, ) if TYPE_CHECKING: @@ -97,9 +96,11 @@ def _sentry_call(*args, **kwargs): old_app = old_get_request_handler(*args, **kwargs) - @ensure_integration_enabled_async(FastApiIntegration, old_app) async def _sentry_app(*args, **kwargs): # type: (*Any, **Any) -> Any + if sentry_sdk.get_client().get_integration(FastApiIntegration) is None: + return await old_app(*args, **kwargs) + integration = sentry_sdk.get_client().get_integration(FastApiIntegration) request = args[0] diff --git a/sentry_sdk/integrations/graphene.py b/sentry_sdk/integrations/graphene.py index 1931b12a71..5b8c393743 100644 --- a/sentry_sdk/integrations/graphene.py +++ b/sentry_sdk/integrations/graphene.py @@ -4,7 +4,6 @@ from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, - ensure_integration_enabled_async, event_from_exception, package_version, ) @@ -69,9 +68,11 @@ def _sentry_patched_graphql_sync(schema, source, *args, **kwargs): return result - @ensure_integration_enabled_async(GrapheneIntegration, old_graphql_async) async def _sentry_patched_graphql_async(schema, source, *args, **kwargs): # type: (GraphQLSchema, Union[str, Source], Any, Any) -> ExecutionResult + if sentry_sdk.get_client().get_integration(GrapheneIntegration) is None: + return await old_graphql_async(schema, source, *args, **kwargs) + scope = Scope.get_isolation_scope() scope.add_event_processor(_event_processor) diff --git a/sentry_sdk/integrations/httpx.py b/sentry_sdk/integrations/httpx.py index 3845591d95..fa75d1440b 100644 --- a/sentry_sdk/integrations/httpx.py +++ b/sentry_sdk/integrations/httpx.py @@ -8,7 +8,6 @@ SENSITIVE_DATA_SUBSTITUTE, capture_internal_exceptions, ensure_integration_enabled, - ensure_integration_enabled_async, logger, parse_url, ) @@ -98,9 +97,11 @@ 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 + if sentry_sdk.get_client().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) diff --git a/sentry_sdk/integrations/quart.py b/sentry_sdk/integrations/quart.py index 21a0fc3fd9..7c2f4ade70 100644 --- a/sentry_sdk/integrations/quart.py +++ b/sentry_sdk/integrations/quart.py @@ -12,7 +12,6 @@ from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, - ensure_integration_enabled_async, event_from_exception, ) from sentry_sdk._types import TYPE_CHECKING @@ -150,10 +149,11 @@ def _set_transaction_name_and_source(scope, transaction_style, request): pass -@ensure_integration_enabled_async(QuartIntegration) async def _request_websocket_started(app, **kwargs): # type: (Quart, **Any) -> None integration = sentry_sdk.get_client().get_integration(QuartIntegration) + if integration is None: + return if has_request_context(): request_websocket = request._get_current_object() @@ -200,9 +200,12 @@ def inner(event, hint): return inner -@ensure_integration_enabled_async(QuartIntegration) async def _capture_exception(sender, exception, **kwargs): # type: (Quart, Union[ValueError, BaseException], **Any) -> None + integration = sentry_sdk.get_client().get_integration(QuartIntegration) + if integration is None: + return + event, hint = event_from_exception( exception, client_options=sentry_sdk.get_client().options, diff --git a/sentry_sdk/integrations/redis/asyncio.py b/sentry_sdk/integrations/redis/asyncio.py index 227e3fa85c..6cb12b0d51 100644 --- a/sentry_sdk/integrations/redis/asyncio.py +++ b/sentry_sdk/integrations/redis/asyncio.py @@ -10,7 +10,6 @@ from sentry_sdk.tracing import Span from sentry_sdk.utils import ( capture_internal_exceptions, - ensure_integration_enabled_async, ) if TYPE_CHECKING: @@ -26,9 +25,11 @@ def patch_redis_async_pipeline( # type: (Union[type[Pipeline[Any]], type[ClusterPipeline[Any]]], bool, Any, Callable[[Span, Any], None]) -> None old_execute = pipeline_cls.execute - @ensure_integration_enabled_async(RedisIntegration, old_execute) async def _sentry_execute(self, *args, **kwargs): # type: (Any, *Any, **Any) -> Any + if sentry_sdk.get_client().get_integration(RedisIntegration) is None: + return await old_execute(self, *args, **kwargs) + with sentry_sdk.start_span( op=OP.DB_REDIS, description="redis.pipeline.execute" ) as span: @@ -51,9 +52,11 @@ def patch_redis_async_client(cls, is_cluster, set_db_data_fn): # type: (Union[type[StrictRedis[Any]], type[RedisCluster[Any]]], bool, Callable[[Span, Any], None]) -> None old_execute_command = cls.execute_command - @ensure_integration_enabled_async(RedisIntegration, old_execute_command) # type: ignore async def _sentry_execute_command(self, name, *args, **kwargs): # type: (Any, str, *Any, **Any) -> Any + if sentry_sdk.get_client().get_integration(RedisIntegration) is None: + return await old_execute_command(self, name, *args, **kwargs) + description = _get_span_description(name, *args) with sentry_sdk.start_span(op=OP.DB_REDIS, description=description) as span: diff --git a/sentry_sdk/integrations/sanic.py b/sentry_sdk/integrations/sanic.py index bb9008032e..fac0991381 100644 --- a/sentry_sdk/integrations/sanic.py +++ b/sentry_sdk/integrations/sanic.py @@ -14,7 +14,6 @@ from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, - ensure_integration_enabled_async, event_from_exception, HAS_REAL_CONTEXTVARS, CONTEXTVARS_ERROR_MESSAGE, @@ -274,9 +273,11 @@ async def sentry_wrapped_error_handler(request, exception): return sentry_wrapped_error_handler -@ensure_integration_enabled_async(SanicIntegration, old_handle_request) async def _legacy_handle_request(self, request, *args, **kwargs): # type: (Any, Request, *Any, **Any) -> Any + if sentry_sdk.get_client().get_integration(SanicIntegration) is None: + return await old_handle_request(self, request, *args, **kwargs) + weak_request = weakref.ref(request) with sentry_sdk.isolation_scope() as scope: diff --git a/sentry_sdk/integrations/starlette.py b/sentry_sdk/integrations/starlette.py index eafc82f6ed..cb0f977d99 100644 --- a/sentry_sdk/integrations/starlette.py +++ b/sentry_sdk/integrations/starlette.py @@ -21,7 +21,6 @@ AnnotatedValue, capture_internal_exceptions, ensure_integration_enabled, - ensure_integration_enabled_async, event_from_exception, logger, parse_version, @@ -337,10 +336,11 @@ def patch_asgi_app(): """ old_app = Starlette.__call__ - @ensure_integration_enabled_async(StarletteIntegration, old_app) async def _sentry_patched_asgi_app(self, scope, receive, send): # type: (Starlette, StarletteScope, Receive, Send) -> None integration = sentry_sdk.get_client().get_integration(StarletteIntegration) + if integration is None: + return await old_app(self, scope, receive, send) middleware = SentryAsgiMiddleware( lambda *a, **kw: old_app(self, *a, **kw), @@ -377,12 +377,13 @@ def _sentry_request_response(func): is_coroutine = _is_async_callable(old_func) if is_coroutine: - @ensure_integration_enabled_async(StarletteIntegration, old_func) async def _sentry_async_func(*args, **kwargs): # type: (*Any, **Any) -> Any integration = sentry_sdk.get_client().get_integration( StarletteIntegration ) + if integration is None: + return await old_func(*args, **kwargs) request = args[0] diff --git a/sentry_sdk/integrations/starlite.py b/sentry_sdk/integrations/starlite.py index fdfe21d8ff..9ef7329fd9 100644 --- a/sentry_sdk/integrations/starlite.py +++ b/sentry_sdk/integrations/starlite.py @@ -8,7 +8,6 @@ from sentry_sdk.tracing import SOURCE_FOR_STYLE, TRANSACTION_SOURCE_ROUTE from sentry_sdk.utils import ( ensure_integration_enabled, - ensure_integration_enabled_async, event_from_exception, transaction_from_function, ) @@ -179,10 +178,11 @@ async def _sentry_send(message: "Message") -> None: def patch_http_route_handle() -> None: old_handle = HTTPRoute.handle - @ensure_integration_enabled_async(StarliteIntegration, old_handle) async def handle_wrapper( self: "HTTPRoute", scope: "HTTPScope", receive: "Receive", send: "Send" ) -> None: + if sentry_sdk.get_client().get_integration(StarliteIntegration) is None: + return await old_handle(self, scope, receive, send) sentry_scope = SentryScope.get_isolation_scope() request: "Request[Any, Any]" = scope["app"].request_class( diff --git a/sentry_sdk/integrations/strawberry.py b/sentry_sdk/integrations/strawberry.py index 7e9d940aea..024907ab7b 100644 --- a/sentry_sdk/integrations/strawberry.py +++ b/sentry_sdk/integrations/strawberry.py @@ -9,7 +9,6 @@ from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, - ensure_integration_enabled_async, event_from_exception, logger, package_version, @@ -266,11 +265,13 @@ def _patch_execute(): old_execute_async = strawberry_schema.execute old_execute_sync = strawberry_schema.execute_sync - @ensure_integration_enabled_async(StrawberryIntegration, old_execute_async) async def _sentry_patched_execute_async(*args, **kwargs): # type: (Any, Any) -> ExecutionResult result = await old_execute_async(*args, **kwargs) + if sentry_sdk.get_client().get_integration(StrawberryIntegration) is None: + return result + if "execution_context" in kwargs and result.errors: scope = Scope.get_isolation_scope() event_processor = _make_request_event_processor(kwargs["execution_context"]) diff --git a/setup.py b/setup.py index 0f1db0c818..bef9842119 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ def get_file_text(file_name): setup( name="sentry-sdk", - version="2.0.0", + version="2.0.1", author="Sentry Team and Contributors", author_email="hello@sentry.io", url="https://github.com/getsentry/sentry-python",