From e73ab4be9efd3ad1589d11d2501ef8849e07bec7 Mon Sep 17 00:00:00 2001 From: Anton Pirker Date: Mon, 24 Feb 2025 16:11:34 +0100 Subject: [PATCH] Merge master into potel-base (#4093) Co-authored-by: Andrew Liu <159852527+aliu39@users.noreply.github.com> Co-authored-by: Marcelo Galigniana --- .github/workflows/test-integrations-dbs.yml | 6 ++- CHANGELOG.md | 8 ++-- .../templates/test_group.jinja | 3 +- sentry_sdk/integrations/aiohttp.py | 4 +- sentry_sdk/integrations/arq.py | 6 +-- sentry_sdk/integrations/asgi.py | 17 +++---- sentry_sdk/integrations/aws_lambda.py | 6 +-- sentry_sdk/integrations/celery/__init__.py | 6 +-- sentry_sdk/integrations/chalice.py | 4 +- sentry_sdk/integrations/django/__init__.py | 4 +- sentry_sdk/integrations/fastapi.py | 4 +- sentry_sdk/integrations/gcp.py | 4 +- sentry_sdk/integrations/grpc/aio/server.py | 4 +- sentry_sdk/integrations/grpc/server.py | 4 +- sentry_sdk/integrations/huey.py | 4 +- sentry_sdk/integrations/litestar.py | 4 +- sentry_sdk/integrations/ray.py | 6 +-- sentry_sdk/integrations/rq.py | 6 +-- sentry_sdk/integrations/sanic.py | 12 ++--- sentry_sdk/integrations/starlette.py | 9 ++-- sentry_sdk/integrations/starlite.py | 4 +- sentry_sdk/integrations/strawberry.py | 4 +- sentry_sdk/integrations/tornado.py | 9 ++-- sentry_sdk/integrations/wsgi.py | 6 +-- sentry_sdk/tracing.py | 45 +++++++++++-------- tests/integrations/asgi/test_asgi.py | 5 ++- tests/integrations/sanic/test_sanic.py | 8 ++-- tests/test_feature_flags.py | 19 ++++++++ 28 files changed, 124 insertions(+), 97 deletions(-) diff --git a/.github/workflows/test-integrations-dbs.yml b/.github/workflows/test-integrations-dbs.yml index 92778617f4..156e14d03d 100644 --- a/.github/workflows/test-integrations-dbs.yml +++ b/.github/workflows/test-integrations-dbs.yml @@ -55,7 +55,8 @@ jobs: with: python-version: ${{ matrix.python-version }} allow-prereleases: true - - uses: getsentry/action-clickhouse-in-ci@v1.1 + - name: "Setup ClickHouse Server" + uses: getsentry/action-clickhouse-in-ci@v1.5 - name: Setup Test Env run: | pip install "coverage[toml]" tox @@ -140,7 +141,8 @@ jobs: with: python-version: ${{ matrix.python-version }} allow-prereleases: true - - uses: getsentry/action-clickhouse-in-ci@v1.1 + - name: "Setup ClickHouse Server" + uses: getsentry/action-clickhouse-in-ci@v1.5 - name: Setup Test Env run: | pip install "coverage[toml]" tox diff --git a/CHANGELOG.md b/CHANGELOG.md index e6857c34ae..939a612bc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2328,7 +2328,7 @@ By: @mgaligniana (#1773) import sentry_sdk from sentry_sdk.integrations.arq import ArqIntegration - from sentry_sdk.tracing import TRANSACTION_SOURCE_COMPONENT + from sentry_sdk.tracing import TransactionSource sentry_sdk.init( dsn="...", @@ -2348,7 +2348,7 @@ By: @mgaligniana (#1773) await ctx['session'].aclose() async def main(): - with sentry_sdk.start_transaction(name="testing_arq_tasks", source=TRANSACTION_SOURCE_COMPONENT): + with sentry_sdk.start_transaction(name="testing_arq_tasks", source=TransactionSource.COMPONENT): redis = await create_pool(RedisSettings()) for url in ('https://facebook.com', 'https://microsoft.com', 'https://github.com', "asdf" ): @@ -2422,7 +2422,7 @@ By: @mgaligniana (#1773) import sentry_sdk from sentry_sdk.integrations.huey import HueyIntegration - from sentry_sdk.tracing import TRANSACTION_SOURCE_COMPONENT, Transaction + from sentry_sdk.tracing import TransactionSource, Transaction def main(): @@ -2434,7 +2434,7 @@ By: @mgaligniana (#1773) traces_sample_rate=1.0, ) - with sentry_sdk.start_transaction(name="testing_huey_tasks", source=TRANSACTION_SOURCE_COMPONENT): + with sentry_sdk.start_transaction(name="testing_huey_tasks", source=TransactionSource.COMPONENT): r = add_numbers(1, 2) if __name__ == "__main__": diff --git a/scripts/split_tox_gh_actions/templates/test_group.jinja b/scripts/split_tox_gh_actions/templates/test_group.jinja index f94d642e32..adf530b5ad 100644 --- a/scripts/split_tox_gh_actions/templates/test_group.jinja +++ b/scripts/split_tox_gh_actions/templates/test_group.jinja @@ -47,7 +47,8 @@ python-version: {% raw %}${{ matrix.python-version }}{% endraw %} allow-prereleases: true {% if needs_clickhouse %} - - uses: getsentry/action-clickhouse-in-ci@v1.1 + - name: "Setup ClickHouse Server" + uses: getsentry/action-clickhouse-in-ci@v1.5 {% endif %} {% if needs_redis %} diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py index 9ebef2f9c6..6efdd5d883 100644 --- a/sentry_sdk/integrations/aiohttp.py +++ b/sentry_sdk/integrations/aiohttp.py @@ -20,7 +20,7 @@ from sentry_sdk.tracing import ( BAGGAGE_HEADER_NAME, SOURCE_FOR_STYLE, - TRANSACTION_SOURCE_ROUTE, + TransactionSource, ) from sentry_sdk.tracing_utils import should_propagate_trace from sentry_sdk.utils import ( @@ -136,7 +136,7 @@ async def sentry_app_handle(self, request, *args, **kwargs): # If this transaction name makes it to the UI, AIOHTTP's # URL resolver did not find a route or died trying. name="generic AIOHTTP request", - source=TRANSACTION_SOURCE_ROUTE, + source=TransactionSource.ROUTE, origin=AioHttpIntegration.origin, attributes=_prepopulate_attributes(request), ) as span: diff --git a/sentry_sdk/integrations/arq.py b/sentry_sdk/integrations/arq.py index 2f3b063d88..f656b6ece3 100644 --- a/sentry_sdk/integrations/arq.py +++ b/sentry_sdk/integrations/arq.py @@ -5,7 +5,7 @@ from sentry_sdk.integrations import _check_minimum_version, DidNotEnable, Integration from sentry_sdk.integrations.logging import ignore_logger from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import TRANSACTION_SOURCE_TASK +from sentry_sdk.tracing import TransactionSource from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -103,14 +103,14 @@ async def _sentry_run_job(self, job_id, score): scope._name = "arq" scope.set_transaction_name( DEFAULT_TRANSACTION_NAME, - source=TRANSACTION_SOURCE_TASK, + source=TransactionSource.TASK, ) scope.clear_breadcrumbs() with sentry_sdk.start_span( op=OP.QUEUE_TASK_ARQ, name=DEFAULT_TRANSACTION_NAME, - source=TRANSACTION_SOURCE_TASK, + source=TransactionSource.TASK, origin=ArqIntegration.origin, ) as span: return_value = await old_run_job(self, job_id, score) diff --git a/sentry_sdk/integrations/asgi.py b/sentry_sdk/integrations/asgi.py index 2a8bbe5091..a5129debbf 100644 --- a/sentry_sdk/integrations/asgi.py +++ b/sentry_sdk/integrations/asgi.py @@ -25,10 +25,7 @@ from sentry_sdk.sessions import track_session from sentry_sdk.tracing import ( SOURCE_FOR_STYLE, - TRANSACTION_SOURCE_ROUTE, - TRANSACTION_SOURCE_URL, - TRANSACTION_SOURCE_COMPONENT, - TRANSACTION_SOURCE_CUSTOM, + TransactionSource, ) from sentry_sdk.utils import ( ContextVar, @@ -265,9 +262,9 @@ def event_processor(self, event, hint, asgi_scope): and "source" in event["transaction_info"] and event["transaction_info"]["source"] in [ - TRANSACTION_SOURCE_COMPONENT, - TRANSACTION_SOURCE_ROUTE, - TRANSACTION_SOURCE_CUSTOM, + TransactionSource.COMPONENT, + TransactionSource.ROUTE, + TransactionSource.CUSTOM, ] ) if not already_set: @@ -306,7 +303,7 @@ def _get_transaction_name_and_source(self, transaction_style, asgi_scope): name = transaction_from_function(endpoint) or "" else: name = _get_url(asgi_scope, "http" if ty == "http" else "ws", host=None) - source = TRANSACTION_SOURCE_URL + source = TransactionSource.URL elif transaction_style == "url": # FastAPI includes the route object in the scope to let Sentry extract the @@ -318,11 +315,11 @@ def _get_transaction_name_and_source(self, transaction_style, asgi_scope): name = path else: name = _get_url(asgi_scope, "http" if ty == "http" else "ws", host=None) - source = TRANSACTION_SOURCE_URL + source = TransactionSource.URL if name is None: name = _DEFAULT_TRANSACTION_NAME - source = TRANSACTION_SOURCE_ROUTE + source = TransactionSource.ROUTE return name, source return name, source diff --git a/sentry_sdk/integrations/aws_lambda.py b/sentry_sdk/integrations/aws_lambda.py index 82dedb3191..66d14b22a3 100644 --- a/sentry_sdk/integrations/aws_lambda.py +++ b/sentry_sdk/integrations/aws_lambda.py @@ -10,7 +10,7 @@ import sentry_sdk from sentry_sdk.consts import OP from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import TRANSACTION_SOURCE_COMPONENT +from sentry_sdk.tracing import TransactionSource from sentry_sdk.utils import ( AnnotatedValue, capture_internal_exceptions, @@ -125,7 +125,7 @@ def sentry_handler(aws_event, aws_context, *args, **kwargs): with sentry_sdk.isolation_scope() as scope: scope.set_transaction_name( - aws_context.function_name, source=TRANSACTION_SOURCE_COMPONENT + aws_context.function_name, source=TransactionSource.COMPONENT ) timeout_thread = None with capture_internal_exceptions(): @@ -170,7 +170,7 @@ def sentry_handler(aws_event, aws_context, *args, **kwargs): with sentry_sdk.start_span( op=OP.FUNCTION_AWS, name=aws_context.function_name, - source=TRANSACTION_SOURCE_COMPONENT, + source=TransactionSource.COMPONENT, origin=AwsLambdaIntegration.origin, attributes=_prepopulate_attributes(request_data, aws_context), ): diff --git a/sentry_sdk/integrations/celery/__init__.py b/sentry_sdk/integrations/celery/__init__.py index 6b74af1cb7..238704fa68 100644 --- a/sentry_sdk/integrations/celery/__init__.py +++ b/sentry_sdk/integrations/celery/__init__.py @@ -13,7 +13,7 @@ ) from sentry_sdk.integrations.celery.utils import _now_seconds_since_epoch from sentry_sdk.integrations.logging import ignore_logger -from sentry_sdk.tracing import BAGGAGE_HEADER_NAME, TRANSACTION_SOURCE_TASK +from sentry_sdk.tracing import BAGGAGE_HEADER_NAME, TransactionSource from sentry_sdk.tracing_utils import Baggage from sentry_sdk.utils import ( capture_internal_exceptions, @@ -306,7 +306,7 @@ def _inner(*args, **kwargs): with isolation_scope() as scope: scope._name = "celery" scope.clear_breadcrumbs() - scope.set_transaction_name(task.name, source=TRANSACTION_SOURCE_TASK) + scope.set_transaction_name(task.name, source=TransactionSource.TASK) scope.add_event_processor(_make_event_processor(task, *args, **kwargs)) # Celery task objects are not a thing to be trusted. Even @@ -317,7 +317,7 @@ def _inner(*args, **kwargs): with sentry_sdk.start_span( op=OP.QUEUE_TASK_CELERY, name=task.name, - source=TRANSACTION_SOURCE_TASK, + source=TransactionSource.TASK, origin=CeleryIntegration.origin, # for some reason, args[1] is a list if non-empty but a # tuple if empty diff --git a/sentry_sdk/integrations/chalice.py b/sentry_sdk/integrations/chalice.py index 0754d1f13b..947e41ebf7 100644 --- a/sentry_sdk/integrations/chalice.py +++ b/sentry_sdk/integrations/chalice.py @@ -4,7 +4,7 @@ import sentry_sdk from sentry_sdk.integrations import Integration, DidNotEnable from sentry_sdk.integrations.aws_lambda import _make_request_event_processor -from sentry_sdk.tracing import TRANSACTION_SOURCE_COMPONENT +from sentry_sdk.tracing import TransactionSource from sentry_sdk.utils import ( capture_internal_exceptions, event_from_exception, @@ -67,7 +67,7 @@ def wrapped_view_function(**function_args): configured_time = app.lambda_context.get_remaining_time_in_millis() scope.set_transaction_name( app.lambda_context.function_name, - source=TRANSACTION_SOURCE_COMPONENT, + source=TransactionSource.COMPONENT, ) scope.add_event_processor( diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py index c7f5a874cf..e8aa673787 100644 --- a/sentry_sdk/integrations/django/__init__.py +++ b/sentry_sdk/integrations/django/__init__.py @@ -8,7 +8,7 @@ from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.scope import add_global_event_processor, should_send_default_pii from sentry_sdk.serializer import add_global_repr_processor -from sentry_sdk.tracing import SOURCE_FOR_STYLE, TRANSACTION_SOURCE_URL +from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.tracing_utils import add_query_source, record_sql_queries from sentry_sdk.utils import ( AnnotatedValue, @@ -398,7 +398,7 @@ def _set_transaction_name_and_source(scope, transaction_style, request): if transaction_name is None: transaction_name = request.path_info - source = TRANSACTION_SOURCE_URL + source = TransactionSource.URL else: source = SOURCE_FOR_STYLE[transaction_style] diff --git a/sentry_sdk/integrations/fastapi.py b/sentry_sdk/integrations/fastapi.py index 8877925a36..76c6adee0f 100644 --- a/sentry_sdk/integrations/fastapi.py +++ b/sentry_sdk/integrations/fastapi.py @@ -5,7 +5,7 @@ import sentry_sdk from sentry_sdk.integrations import DidNotEnable from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import SOURCE_FOR_STYLE, TRANSACTION_SOURCE_ROUTE +from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.utils import ( transaction_from_function, logger, @@ -61,7 +61,7 @@ def _set_transaction_name_and_source(scope, transaction_style, request): if not name: name = _DEFAULT_TRANSACTION_NAME - source = TRANSACTION_SOURCE_ROUTE + source = TransactionSource.ROUTE else: source = SOURCE_FOR_STYLE[transaction_style] diff --git a/sentry_sdk/integrations/gcp.py b/sentry_sdk/integrations/gcp.py index ec626ed699..97b72ff1ce 100644 --- a/sentry_sdk/integrations/gcp.py +++ b/sentry_sdk/integrations/gcp.py @@ -12,7 +12,7 @@ _request_headers_to_span_attributes, ) from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import TRANSACTION_SOURCE_COMPONENT +from sentry_sdk.tracing import TransactionSource from sentry_sdk.utils import ( AnnotatedValue, capture_internal_exceptions, @@ -90,7 +90,7 @@ def sentry_func(functionhandler, gcp_event, *args, **kwargs): with sentry_sdk.start_span( op=OP.FUNCTION_GCP, name=environ.get("FUNCTION_NAME", ""), - source=TRANSACTION_SOURCE_COMPONENT, + source=TransactionSource.COMPONENT, origin=GcpIntegration.origin, attributes=_prepopulate_attributes(gcp_event), ): diff --git a/sentry_sdk/integrations/grpc/aio/server.py b/sentry_sdk/integrations/grpc/aio/server.py index 4d54b0605c..91c2e9d74f 100644 --- a/sentry_sdk/integrations/grpc/aio/server.py +++ b/sentry_sdk/integrations/grpc/aio/server.py @@ -2,7 +2,7 @@ from sentry_sdk.consts import OP from sentry_sdk.integrations import DidNotEnable from sentry_sdk.integrations.grpc.consts import SPAN_ORIGIN -from sentry_sdk.tracing import TRANSACTION_SOURCE_CUSTOM +from sentry_sdk.tracing import TransactionSource from sentry_sdk.utils import event_from_exception from typing import TYPE_CHECKING @@ -48,7 +48,7 @@ async def wrapped(request, context): with sentry_sdk.start_span( op=OP.GRPC_SERVER, name=name, - source=TRANSACTION_SOURCE_CUSTOM, + source=TransactionSource.CUSTOM, origin=SPAN_ORIGIN, ): try: diff --git a/sentry_sdk/integrations/grpc/server.py b/sentry_sdk/integrations/grpc/server.py index d12b43b92b..582ef6e24a 100644 --- a/sentry_sdk/integrations/grpc/server.py +++ b/sentry_sdk/integrations/grpc/server.py @@ -2,7 +2,7 @@ from sentry_sdk.consts import OP from sentry_sdk.integrations import DidNotEnable from sentry_sdk.integrations.grpc.consts import SPAN_ORIGIN -from sentry_sdk.tracing import TRANSACTION_SOURCE_CUSTOM +from sentry_sdk.tracing import TransactionSource from typing import TYPE_CHECKING @@ -42,7 +42,7 @@ def behavior(request, context): with sentry_sdk.start_span( op=OP.GRPC_SERVER, name=name, - source=TRANSACTION_SOURCE_CUSTOM, + source=TransactionSource.CUSTOM, origin=SPAN_ORIGIN, ): try: diff --git a/sentry_sdk/integrations/huey.py b/sentry_sdk/integrations/huey.py index 4dcff8513f..8e9d45a526 100644 --- a/sentry_sdk/integrations/huey.py +++ b/sentry_sdk/integrations/huey.py @@ -9,7 +9,7 @@ from sentry_sdk.tracing import ( BAGGAGE_HEADER_NAME, SENTRY_TRACE_HEADER_NAME, - TRANSACTION_SOURCE_TASK, + TransactionSource, ) from sentry_sdk.utils import ( capture_internal_exceptions, @@ -165,7 +165,7 @@ def _sentry_execute(self, task, timestamp=None): with sentry_sdk.start_span( name=task.name, op=OP.QUEUE_TASK_HUEY, - source=TRANSACTION_SOURCE_TASK, + source=TransactionSource.TASK, origin=HueyIntegration.origin, ): return old_execute(self, task, timestamp) diff --git a/sentry_sdk/integrations/litestar.py b/sentry_sdk/integrations/litestar.py index 4feb9f775e..484fea46c8 100644 --- a/sentry_sdk/integrations/litestar.py +++ b/sentry_sdk/integrations/litestar.py @@ -9,7 +9,7 @@ from sentry_sdk.integrations.asgi import SentryAsgiMiddleware from sentry_sdk.integrations.logging import ignore_logger from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import SOURCE_FOR_STYLE, TRANSACTION_SOURCE_ROUTE +from sentry_sdk.tracing import TransactionSource, SOURCE_FOR_STYLE from sentry_sdk.utils import ( ensure_integration_enabled, event_from_exception, @@ -252,7 +252,7 @@ def event_processor(event, _): if not tx_name: tx_name = _DEFAULT_TRANSACTION_NAME - tx_info = {"source": TRANSACTION_SOURCE_ROUTE} + tx_info = {"source": TransactionSource.ROUTE} event.update( { diff --git a/sentry_sdk/integrations/ray.py b/sentry_sdk/integrations/ray.py index e033d93335..a0ec9713c1 100644 --- a/sentry_sdk/integrations/ray.py +++ b/sentry_sdk/integrations/ray.py @@ -4,7 +4,7 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANSTATUS from sentry_sdk.integrations import _check_minimum_version, DidNotEnable, Integration -from sentry_sdk.tracing import TRANSACTION_SOURCE_TASK +from sentry_sdk.tracing import TransactionSource from sentry_sdk.utils import ( event_from_exception, logger, @@ -63,14 +63,14 @@ def _f(*f_args, _tracing=None, **f_kwargs): root_span_name = qualname_from_function(f) or DEFAULT_TRANSACTION_NAME sentry_sdk.get_current_scope().set_transaction_name( root_span_name, - source=TRANSACTION_SOURCE_TASK, + source=TransactionSource.TASK, ) with sentry_sdk.continue_trace(_tracing or {}): with sentry_sdk.start_span( op=OP.QUEUE_TASK_RAY, name=root_span_name, origin=RayIntegration.origin, - source=TRANSACTION_SOURCE_TASK, + source=TransactionSource.TASK, ) as root_span: try: result = f(*f_args, **f_kwargs) diff --git a/sentry_sdk/integrations/rq.py b/sentry_sdk/integrations/rq.py index d87a4fbded..33910ed476 100644 --- a/sentry_sdk/integrations/rq.py +++ b/sentry_sdk/integrations/rq.py @@ -4,7 +4,7 @@ from sentry_sdk.consts import OP from sentry_sdk.integrations import _check_minimum_version, DidNotEnable, Integration from sentry_sdk.integrations.logging import ignore_logger -from sentry_sdk.tracing import TRANSACTION_SOURCE_TASK +from sentry_sdk.tracing import TransactionSource from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -66,7 +66,7 @@ def sentry_patched_perform_job(self, job, queue, *args, **kwargs): transaction_name = DEFAULT_TRANSACTION_NAME scope.set_transaction_name( - transaction_name, source=TRANSACTION_SOURCE_TASK + transaction_name, source=TransactionSource.TASK ) scope.clear_breadcrumbs() scope.add_event_processor(_make_event_processor(weakref.ref(job))) @@ -77,7 +77,7 @@ def sentry_patched_perform_job(self, job, queue, *args, **kwargs): with sentry_sdk.start_span( op=OP.QUEUE_TASK_RQ, name=transaction_name, - source=TRANSACTION_SOURCE_TASK, + source=TransactionSource.TASK, origin=RqIntegration.origin, attributes=_prepopulate_attributes(job, queue), ): diff --git a/sentry_sdk/integrations/sanic.py b/sentry_sdk/integrations/sanic.py index 6143313cc4..06e30ffe31 100644 --- a/sentry_sdk/integrations/sanic.py +++ b/sentry_sdk/integrations/sanic.py @@ -8,7 +8,7 @@ from sentry_sdk.integrations import _check_minimum_version, Integration, DidNotEnable from sentry_sdk.integrations._wsgi_common import RequestExtractor, _filter_headers from sentry_sdk.integrations.logging import ignore_logger -from sentry_sdk.tracing import TRANSACTION_SOURCE_COMPONENT, TRANSACTION_SOURCE_URL +from sentry_sdk.tracing import TransactionSource from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -185,7 +185,7 @@ async def _context_enter(request): scope = request.ctx._sentry_scope_manager.__enter__() request.ctx._sentry_scope = scope - scope.set_transaction_name(request.path, TRANSACTION_SOURCE_URL) + scope.set_transaction_name(request.path, TransactionSource.URL) scope.clear_breadcrumbs() scope.add_event_processor(_make_request_processor(weak_request)) @@ -198,7 +198,7 @@ async def _context_enter(request): op=OP.HTTP_SERVER, # Unless the request results in a 404 error, the name and source will get overwritten in _set_transaction name=request.path, - source=TRANSACTION_SOURCE_URL, + source=TransactionSource.URL, origin=SanicIntegration.origin, ).__enter__() @@ -239,7 +239,7 @@ async def _set_transaction(request, route, **_): with capture_internal_exceptions(): scope = sentry_sdk.get_current_scope() route_name = route.name.replace(request.app.name, "").strip(".") - scope.set_transaction_name(route_name, source=TRANSACTION_SOURCE_COMPONENT) + scope.set_transaction_name(route_name, source=TransactionSource.COMPONENT) def _sentry_error_handler_lookup(self, exception, *args, **kwargs): @@ -314,11 +314,11 @@ def _legacy_router_get(self, *args): sanic_route = sanic_route[len(sanic_app_name) + 1 :] scope.set_transaction_name( - sanic_route, source=TRANSACTION_SOURCE_COMPONENT + sanic_route, source=TransactionSource.COMPONENT ) else: scope.set_transaction_name( - rv[0].__name__, source=TRANSACTION_SOURCE_COMPONENT + rv[0].__name__, source=TransactionSource.COMPONENT ) return rv diff --git a/sentry_sdk/integrations/starlette.py b/sentry_sdk/integrations/starlette.py index c8a415a64d..cb2da74a04 100644 --- a/sentry_sdk/integrations/starlette.py +++ b/sentry_sdk/integrations/starlette.py @@ -21,8 +21,7 @@ from sentry_sdk.scope import should_send_default_pii from sentry_sdk.tracing import ( SOURCE_FOR_STYLE, - TRANSACTION_SOURCE_COMPONENT, - TRANSACTION_SOURCE_ROUTE, + TransactionSource, ) from sentry_sdk.utils import ( AnnotatedValue, @@ -717,7 +716,7 @@ def _set_transaction_name_and_source(scope, transaction_style, request): if name is None: name = _DEFAULT_TRANSACTION_NAME - source = TRANSACTION_SOURCE_ROUTE + source = TransactionSource.ROUTE scope.set_transaction_name(name, source=source) logger.debug( @@ -732,9 +731,9 @@ def _get_transaction_from_middleware(app, asgi_scope, integration): if integration.transaction_style == "endpoint": name = transaction_from_function(app.__class__) - source = TRANSACTION_SOURCE_COMPONENT + source = TransactionSource.COMPONENT elif integration.transaction_style == "url": name = _transaction_name_from_router(asgi_scope) - source = TRANSACTION_SOURCE_ROUTE + source = TransactionSource.ROUTE return name, source diff --git a/sentry_sdk/integrations/starlite.py b/sentry_sdk/integrations/starlite.py index 66f5025c26..dae105447b 100644 --- a/sentry_sdk/integrations/starlite.py +++ b/sentry_sdk/integrations/starlite.py @@ -3,7 +3,7 @@ from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.integrations.asgi import SentryAsgiMiddleware from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import SOURCE_FOR_STYLE, TRANSACTION_SOURCE_ROUTE +from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.utils import ( ensure_integration_enabled, event_from_exception, @@ -238,7 +238,7 @@ def event_processor(event, _): if not tx_name: tx_name = _DEFAULT_TRANSACTION_NAME - tx_info = {"source": TRANSACTION_SOURCE_ROUTE} + tx_info = {"source": TransactionSource.ROUTE} event.update( { diff --git a/sentry_sdk/integrations/strawberry.py b/sentry_sdk/integrations/strawberry.py index b2071ed6b5..608dfcbb8c 100644 --- a/sentry_sdk/integrations/strawberry.py +++ b/sentry_sdk/integrations/strawberry.py @@ -7,7 +7,7 @@ from sentry_sdk.integrations import _check_minimum_version, Integration, DidNotEnable from sentry_sdk.integrations.logging import ignore_logger from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import TRANSACTION_SOURCE_COMPONENT +from sentry_sdk.tracing import TransactionSource from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -196,7 +196,7 @@ def on_operation(self): sentry_sdk.get_current_scope().set_transaction_name( self._operation_name, - source=TRANSACTION_SOURCE_COMPONENT, + source=TransactionSource.COMPONENT, ) root_span = graphql_span.root_span diff --git a/sentry_sdk/integrations/tornado.py b/sentry_sdk/integrations/tornado.py index 5ecd71bced..70fb21ee14 100644 --- a/sentry_sdk/integrations/tornado.py +++ b/sentry_sdk/integrations/tornado.py @@ -5,10 +5,7 @@ import sentry_sdk from sentry_sdk.consts import OP from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import ( - TRANSACTION_SOURCE_COMPONENT, - TRANSACTION_SOURCE_ROUTE, -) +from sentry_sdk.tracing import TransactionSource from sentry_sdk.utils import ( HAS_REAL_CONTEXTVARS, CONTEXTVARS_ERROR_MESSAGE, @@ -131,7 +128,7 @@ def _handle_request_impl(self): # sentry_urldispatcher_resolve is responsible for # setting a transaction name later. name="generic Tornado request", - source=TRANSACTION_SOURCE_ROUTE, + source=TransactionSource.ROUTE, origin=TornadoIntegration.origin, attributes=_prepopulate_attributes(self.request), ): @@ -166,7 +163,7 @@ def tornado_processor(event, hint): with capture_internal_exceptions(): method = getattr(handler, handler.request.method.lower()) event["transaction"] = transaction_from_function(method) or "" - event["transaction_info"] = {"source": TRANSACTION_SOURCE_COMPONENT} + event["transaction_info"] = {"source": TransactionSource.COMPONENT} with capture_internal_exceptions(): extractor = TornadoRequestExtractor(request) diff --git a/sentry_sdk/integrations/wsgi.py b/sentry_sdk/integrations/wsgi.py index 74051df0db..85983b18c4 100644 --- a/sentry_sdk/integrations/wsgi.py +++ b/sentry_sdk/integrations/wsgi.py @@ -11,7 +11,7 @@ _request_headers_to_span_attributes, ) from sentry_sdk.sessions import track_session -from sentry_sdk.tracing import Span, TRANSACTION_SOURCE_ROUTE +from sentry_sdk.tracing import Span, TransactionSource from sentry_sdk.utils import ( ContextVar, capture_internal_exceptions, @@ -108,7 +108,7 @@ def __call__(self, environ, start_response): try: with sentry_sdk.isolation_scope() as scope: scope.set_transaction_name( - DEFAULT_TRANSACTION_NAME, source=TRANSACTION_SOURCE_ROUTE + DEFAULT_TRANSACTION_NAME, source=TransactionSource.ROUTE ) with track_session(scope, session_mode="request"): @@ -127,7 +127,7 @@ def __call__(self, environ, start_response): with sentry_sdk.start_span( op=OP.HTTP_SERVER, name=DEFAULT_TRANSACTION_NAME, - source=TRANSACTION_SOURCE_ROUTE, + source=TransactionSource.ROUTE, origin=self.span_origin, attributes=_prepopulate_attributes( environ, self.use_x_forwarded_for diff --git a/sentry_sdk/tracing.py b/sentry_sdk/tracing.py index 0272449198..6bb1eeab76 100644 --- a/sentry_sdk/tracing.py +++ b/sentry_sdk/tracing.py @@ -1,3 +1,4 @@ +from enum import Enum import json from datetime import datetime @@ -23,6 +24,7 @@ from typing import TYPE_CHECKING, cast + if TYPE_CHECKING: from collections.abc import Callable from typing import Any @@ -127,30 +129,37 @@ class TransactionKwargs(SpanKwargs, total=False): BAGGAGE_HEADER_NAME = "baggage" SENTRY_TRACE_HEADER_NAME = "sentry-trace" + # Transaction source # see https://develop.sentry.dev/sdk/event-payloads/transaction/#transaction-annotations -TRANSACTION_SOURCE_CUSTOM = "custom" -TRANSACTION_SOURCE_URL = "url" -TRANSACTION_SOURCE_ROUTE = "route" -TRANSACTION_SOURCE_VIEW = "view" -TRANSACTION_SOURCE_COMPONENT = "component" -TRANSACTION_SOURCE_TASK = "task" +class TransactionSource(str, Enum): + COMPONENT = "component" + CUSTOM = "custom" + ROUTE = "route" + TASK = "task" + URL = "url" + VIEW = "view" + + def __str__(self): + # type: () -> str + return self.value + # These are typically high cardinality and the server hates them LOW_QUALITY_TRANSACTION_SOURCES = [ - TRANSACTION_SOURCE_URL, + TransactionSource.URL, ] SOURCE_FOR_STYLE = { - "endpoint": TRANSACTION_SOURCE_COMPONENT, - "function_name": TRANSACTION_SOURCE_COMPONENT, - "handler_name": TRANSACTION_SOURCE_COMPONENT, - "method_and_path_pattern": TRANSACTION_SOURCE_ROUTE, - "path": TRANSACTION_SOURCE_URL, - "route_name": TRANSACTION_SOURCE_COMPONENT, - "route_pattern": TRANSACTION_SOURCE_ROUTE, - "uri_template": TRANSACTION_SOURCE_ROUTE, - "url": TRANSACTION_SOURCE_ROUTE, + "endpoint": TransactionSource.COMPONENT, + "function_name": TransactionSource.COMPONENT, + "handler_name": TransactionSource.COMPONENT, + "method_and_path_pattern": TransactionSource.ROUTE, + "path": TransactionSource.URL, + "route_name": TransactionSource.COMPONENT, + "route_pattern": TransactionSource.ROUTE, + "uri_template": TransactionSource.ROUTE, + "url": TransactionSource.ROUTE, } DEFAULT_SPAN_ORIGIN = "manual" @@ -303,7 +312,7 @@ def __init__( start_timestamp=None, # type: Optional[Union[datetime, float]] origin=None, # type: Optional[str] name=None, # type: Optional[str] - source=TRANSACTION_SOURCE_CUSTOM, # type: str + source=TransactionSource.CUSTOM, # type: str attributes=None, # type: Optional[dict[str, Any]] only_if_parent=False, # type: bool parent_span=None, # type: Optional[Span] @@ -566,7 +575,7 @@ def source(self): from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute return ( - self.get_attribute(SentrySpanAttribute.SOURCE) or TRANSACTION_SOURCE_CUSTOM + self.get_attribute(SentrySpanAttribute.SOURCE) or TransactionSource.CUSTOM ) @source.setter diff --git a/tests/integrations/asgi/test_asgi.py b/tests/integrations/asgi/test_asgi.py index 96d4e709f1..d0ddef8611 100644 --- a/tests/integrations/asgi/test_asgi.py +++ b/tests/integrations/asgi/test_asgi.py @@ -3,6 +3,7 @@ import pytest import sentry_sdk from sentry_sdk import capture_message +from sentry_sdk.tracing import TransactionSource from sentry_sdk.integrations._asgi_common import _get_ip, _get_headers from sentry_sdk.integrations.asgi import SentryAsgiMiddleware, _looks_like_asgi3 @@ -129,7 +130,9 @@ async def app(scope, receive, send): @pytest.fixture def asgi3_custom_transaction_app(): async def app(scope, receive, send): - sentry_sdk.get_current_scope().set_transaction_name("foobar", source="custom") + sentry_sdk.get_current_scope().set_transaction_name( + "foobar", source=TransactionSource.CUSTOM + ) await send( { "type": "http.response.start", diff --git a/tests/integrations/sanic/test_sanic.py b/tests/integrations/sanic/test_sanic.py index a3fc5a7652..05b23cb215 100644 --- a/tests/integrations/sanic/test_sanic.py +++ b/tests/integrations/sanic/test_sanic.py @@ -10,7 +10,7 @@ import sentry_sdk from sentry_sdk import capture_message from sentry_sdk.integrations.sanic import SanicIntegration -from sentry_sdk.tracing import TRANSACTION_SOURCE_COMPONENT, TRANSACTION_SOURCE_URL +from sentry_sdk.tracing import TransactionSource from sanic import Sanic, request, response, __version__ as SANIC_VERSION_RAW from sanic.response import HTTPResponse @@ -372,7 +372,7 @@ def __init__( url="/message", expected_status=200, expected_transaction_name="hi", - expected_source=TRANSACTION_SOURCE_COMPONENT, + expected_source=TransactionSource.COMPONENT, ), TransactionTestConfig( # Transaction still recorded when we have an internal server error @@ -380,7 +380,7 @@ def __init__( url="/500", expected_status=500, expected_transaction_name="fivehundred", - expected_source=TRANSACTION_SOURCE_COMPONENT, + expected_source=TransactionSource.COMPONENT, ), TransactionTestConfig( # By default, no transaction when we have a 404 error @@ -396,7 +396,7 @@ def __init__( url="/404", expected_status=404, expected_transaction_name="/404", - expected_source=TRANSACTION_SOURCE_URL, + expected_source=TransactionSource.URL, ), TransactionTestConfig( # Transaction can be suppressed for other HTTP statuses, too, by passing config to the integration diff --git a/tests/test_feature_flags.py b/tests/test_feature_flags.py index 4469b5c2ca..0df30bd0ea 100644 --- a/tests/test_feature_flags.py +++ b/tests/test_feature_flags.py @@ -170,6 +170,25 @@ def test_flag_tracking(): {"flag": "f", "result": False}, ] + # Test updates + buffer.set("e", True) + buffer.set("e", False) + buffer.set("e", True) + flags = buffer.get() + assert flags == [ + {"flag": "d", "result": False}, + {"flag": "f", "result": False}, + {"flag": "e", "result": True}, + ] + + buffer.set("d", True) + flags = buffer.get() + assert flags == [ + {"flag": "f", "result": False}, + {"flag": "e", "result": True}, + {"flag": "d", "result": True}, + ] + def test_flag_buffer_concurrent_access(): buffer = FlagBuffer(capacity=100)