From 5c2928c61af4710c7314002f0efff7153e008d5f Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Thu, 30 Jul 2026 12:27:03 +0200 Subject: [PATCH] ref: Remove has_span_streaming_enabled branches --- sentry_sdk/ai/monitoring.py | 191 ++++------ sentry_sdk/client.py | 29 +- sentry_sdk/feature_flags.py | 16 +- sentry_sdk/integrations/aiohttp.py | 260 ++++++------- sentry_sdk/integrations/aiomysql.py | 45 +-- sentry_sdk/integrations/anthropic.py | 100 ++--- sentry_sdk/integrations/arq.py | 73 ++-- sentry_sdk/integrations/asgi.py | 108 ++---- sentry_sdk/integrations/asyncio.py | 21 +- sentry_sdk/integrations/asyncpg.py | 70 ++-- sentry_sdk/integrations/aws_lambda.py | 67 ++-- sentry_sdk/integrations/boto3.py | 63 +--- sentry_sdk/integrations/bottle.py | 8 +- sentry_sdk/integrations/celery/__init__.py | 135 ++----- sentry_sdk/integrations/chalice.py | 110 +++--- sentry_sdk/integrations/clickhouse_driver.py | 38 +- sentry_sdk/integrations/cohere.py | 55 +-- sentry_sdk/integrations/django/__init__.py | 107 ++---- sentry_sdk/integrations/django/asgi.py | 43 +-- sentry_sdk/integrations/django/caching.py | 162 +++----- sentry_sdk/integrations/django/middleware.py | 36 +- .../integrations/django/signals_handlers.py | 35 +- sentry_sdk/integrations/django/tasks.py | 28 +- sentry_sdk/integrations/django/templates.py | 63 +--- sentry_sdk/integrations/django/views.py | 71 ++-- sentry_sdk/integrations/dramatiq.py | 51 +-- sentry_sdk/integrations/falcon.py | 3 +- sentry_sdk/integrations/fastapi.py | 14 +- sentry_sdk/integrations/gcp.py | 49 +-- .../integrations/google_genai/__init__.py | 335 ++++++----------- sentry_sdk/integrations/google_genai/utils.py | 27 +- sentry_sdk/integrations/graphene.py | 59 +-- sentry_sdk/integrations/grpc/aio/client.py | 131 ++----- sentry_sdk/integrations/grpc/aio/server.py | 76 ++-- sentry_sdk/integrations/grpc/client.py | 141 +++---- sentry_sdk/integrations/grpc/server.py | 48 +-- sentry_sdk/integrations/httpx.py | 215 ++++------- sentry_sdk/integrations/httpx2.py | 223 +++++------ sentry_sdk/integrations/huey.py | 94 ++--- sentry_sdk/integrations/huggingface_hub.py | 29 +- sentry_sdk/integrations/langchain.py | 345 ++++++------------ sentry_sdk/integrations/langgraph.py | 228 ++++-------- sentry_sdk/integrations/litellm.py | 34 +- sentry_sdk/integrations/litestar.py | 153 +++----- sentry_sdk/integrations/mcp.py | 81 ++-- sentry_sdk/integrations/openai.py | 249 ++++--------- .../openai_agents/patches/error_tracing.py | 14 +- .../openai_agents/spans/agent_workflow.py | 19 +- .../openai_agents/spans/ai_client.py | 43 +-- .../openai_agents/spans/execute_tool.py | 61 +--- .../openai_agents/spans/handoff.py | 39 +- .../openai_agents/spans/invoke_agent.py | 45 +-- .../pydantic_ai/spans/ai_client.py | 84 ++--- .../pydantic_ai/spans/execute_tool.py | 51 +-- .../pydantic_ai/spans/invoke_agent.py | 39 +- sentry_sdk/integrations/pymongo.py | 121 ++---- sentry_sdk/integrations/pyramid.py | 24 +- sentry_sdk/integrations/pyreqwest.py | 91 ++--- sentry_sdk/integrations/quart.py | 143 ++++---- sentry_sdk/integrations/ray.py | 176 +++------ .../integrations/redis/_async_common.py | 77 ++-- sentry_sdk/integrations/redis/_sync_common.py | 77 ++-- sentry_sdk/integrations/rq.py | 73 ++-- sentry_sdk/integrations/rust_tracing.py | 63 +--- sentry_sdk/integrations/sanic.py | 101 ++--- sentry_sdk/integrations/socket.py | 112 +++--- sentry_sdk/integrations/starlette.py | 49 +-- sentry_sdk/integrations/starlite.py | 39 +- sentry_sdk/integrations/stdlib.py | 183 +++------- sentry_sdk/integrations/strawberry.py | 214 ++++------- sentry_sdk/integrations/tornado.py | 63 +--- sentry_sdk/integrations/wsgi.py | 72 ++-- sentry_sdk/tracing_utils.py | 77 +--- 73 files changed, 2127 insertions(+), 4542 deletions(-) diff --git a/sentry_sdk/ai/monitoring.py b/sentry_sdk/ai/monitoring.py index 423bb50f9d..101b4d8929 100644 --- a/sentry_sdk/ai/monitoring.py +++ b/sentry_sdk/ai/monitoring.py @@ -4,12 +4,10 @@ from typing import TYPE_CHECKING import sentry_sdk.utils -from sentry_sdk import start_span from sentry_sdk.ai.utils import _set_span_data_attribute from sentry_sdk.consts import SPANDATA from sentry_sdk.traces import StreamedSpan from sentry_sdk.tracing import Span -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ContextVar, capture_internal_exceptions, reraise if TYPE_CHECKING: @@ -31,141 +29,76 @@ def get_ai_pipeline_name() -> "Optional[str]": def ai_track(description: str, **span_kwargs: "Any") -> "Callable[[F], F]": def decorator(f: "F") -> "F": def sync_wrapped(*args: "Any", **kwargs: "Any") -> "Any": - client = sentry_sdk.get_client() - curr_pipeline = _ai_pipeline_name.get() op = span_kwargs.pop("op", "ai.run" if curr_pipeline else "ai.pipeline") - if has_span_streaming_enabled(client.options): - with sentry_sdk.traces.start_span( - name=description, attributes={"sentry.op": op} - ) as span: - for k, v in kwargs.pop("sentry_tags", {}).items(): - span.set_attribute(k, v) - for k, v in kwargs.pop("sentry_data", {}).items(): - span.set_attribute(k, v) - - if curr_pipeline: - span.set_attribute(SPANDATA.GEN_AI_PIPELINE_NAME, curr_pipeline) - return f(*args, **kwargs) - else: - _ai_pipeline_name.set(description) - try: - res = f(*args, **kwargs) - except Exception as e: - exc_info = sys.exc_info() - with capture_internal_exceptions(): - event, hint = sentry_sdk.utils.event_from_exception( - e, - client_options=sentry_sdk.get_client().options, - mechanism={ - "type": "ai_monitoring", - "handled": False, - }, - ) - sentry_sdk.capture_event(event, hint=hint) - reraise(*exc_info) - finally: - _ai_pipeline_name.set(None) - return res - - else: - with start_span(name=description, op=op, **span_kwargs) as span: - for k, v in kwargs.pop("sentry_tags", {}).items(): - span.set_tag(k, v) - for k, v in kwargs.pop("sentry_data", {}).items(): - span.set_data(k, v) - if curr_pipeline: - span.set_data(SPANDATA.GEN_AI_PIPELINE_NAME, curr_pipeline) - return f(*args, **kwargs) - else: - _ai_pipeline_name.set(description) - try: - res = f(*args, **kwargs) - except Exception as e: - exc_info = sys.exc_info() - with capture_internal_exceptions(): - event, hint = sentry_sdk.utils.event_from_exception( - e, - client_options=sentry_sdk.get_client().options, - mechanism={ - "type": "ai_monitoring", - "handled": False, - }, - ) - sentry_sdk.capture_event(event, hint=hint) - reraise(*exc_info) - finally: - _ai_pipeline_name.set(None) - return res + with sentry_sdk.traces.start_span( + name=description, attributes={"sentry.op": op} + ) as span: + for k, v in kwargs.pop("sentry_tags", {}).items(): + span.set_attribute(k, v) + for k, v in kwargs.pop("sentry_data", {}).items(): + span.set_attribute(k, v) + + if curr_pipeline: + span.set_attribute(SPANDATA.GEN_AI_PIPELINE_NAME, curr_pipeline) + return f(*args, **kwargs) + else: + _ai_pipeline_name.set(description) + try: + res = f(*args, **kwargs) + except Exception as e: + exc_info = sys.exc_info() + with capture_internal_exceptions(): + event, hint = sentry_sdk.utils.event_from_exception( + e, + client_options=sentry_sdk.get_client().options, + mechanism={ + "type": "ai_monitoring", + "handled": False, + }, + ) + sentry_sdk.capture_event(event, hint=hint) + reraise(*exc_info) + finally: + _ai_pipeline_name.set(None) + return res async def async_wrapped(*args: "Any", **kwargs: "Any") -> "Any": - client = sentry_sdk.get_client() - curr_pipeline = _ai_pipeline_name.get() op = span_kwargs.pop("op", "ai.run" if curr_pipeline else "ai.pipeline") - if has_span_streaming_enabled(client.options): - with sentry_sdk.traces.start_span( - name=description, attributes={"sentry.op": op} - ) as span: - for k, v in kwargs.pop("sentry_tags", {}).items(): - span.set_attribute(k, v) - for k, v in kwargs.pop("sentry_data", {}).items(): - span.set_attribute(k, v) - - if curr_pipeline: - span.set_attribute(SPANDATA.GEN_AI_PIPELINE_NAME, curr_pipeline) - return await f(*args, **kwargs) - else: - _ai_pipeline_name.set(description) - try: - res = await f(*args, **kwargs) - except Exception as e: - exc_info = sys.exc_info() - with capture_internal_exceptions(): - event, hint = sentry_sdk.utils.event_from_exception( - e, - client_options=sentry_sdk.get_client().options, - mechanism={ - "type": "ai_monitoring", - "handled": False, - }, - ) - sentry_sdk.capture_event(event, hint=hint) - reraise(*exc_info) - finally: - _ai_pipeline_name.set(None) - return res - else: - with start_span(name=description, op=op, **span_kwargs) as span: - for k, v in kwargs.pop("sentry_tags", {}).items(): - span.set_tag(k, v) - for k, v in kwargs.pop("sentry_data", {}).items(): - span.set_data(k, v) - if curr_pipeline: - span.set_data(SPANDATA.GEN_AI_PIPELINE_NAME, curr_pipeline) - return await f(*args, **kwargs) - else: - _ai_pipeline_name.set(description) - try: - res = await f(*args, **kwargs) - except Exception as e: - exc_info = sys.exc_info() - with capture_internal_exceptions(): - event, hint = sentry_sdk.utils.event_from_exception( - e, - client_options=sentry_sdk.get_client().options, - mechanism={ - "type": "ai_monitoring", - "handled": False, - }, - ) - sentry_sdk.capture_event(event, hint=hint) - reraise(*exc_info) - finally: - _ai_pipeline_name.set(None) - return res + with sentry_sdk.traces.start_span( + name=description, attributes={"sentry.op": op} + ) as span: + for k, v in kwargs.pop("sentry_tags", {}).items(): + span.set_attribute(k, v) + for k, v in kwargs.pop("sentry_data", {}).items(): + span.set_attribute(k, v) + + if curr_pipeline: + span.set_attribute(SPANDATA.GEN_AI_PIPELINE_NAME, curr_pipeline) + return await f(*args, **kwargs) + else: + _ai_pipeline_name.set(description) + try: + res = await f(*args, **kwargs) + except Exception as e: + exc_info = sys.exc_info() + with capture_internal_exceptions(): + event, hint = sentry_sdk.utils.event_from_exception( + e, + client_options=sentry_sdk.get_client().options, + mechanism={ + "type": "ai_monitoring", + "handled": False, + }, + ) + sentry_sdk.capture_event(event, hint=hint) + reraise(*exc_info) + finally: + _ai_pipeline_name.set(None) + return res if inspect.iscoroutinefunction(f): return wraps(f)(async_wrapped) # type: ignore diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index f865cbac97..fbe5dcb75f 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -36,7 +36,6 @@ from sentry_sdk.sessions import SessionFlusher from sentry_sdk.traces import SpanStatus, StreamedSpan from sentry_sdk.tracing import trace -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.transport import ( AsyncHttpTransport, HttpTransportCore, @@ -366,24 +365,6 @@ def _get_options(*args: "Optional[str]", **kwargs: "Any") -> "Dict[str, Any]": env_to_bool(os.environ.get("SENTRY_KEEP_ALIVE"), strict=True) or False ) - if rv["trace_ignore_status_codes"] and has_span_streaming_enabled(rv): - warnings.warn( - "The `trace_ignore_status_codes` parameter is ignored in span streaming mode.", - stacklevel=2, - ) - - if rv["ignore_spans"] and not has_span_streaming_enabled(rv): - warnings.warn( - "The `ignore_spans` parameter only works when `trace_lifecycle` is set to `stream`.", - stacklevel=2, - ) - - if rv["before_send_span"] and not has_span_streaming_enabled(rv): - warnings.warn( - "The `before_send_span` parameter only works when `trace_lifecycle` is set to `stream`.", - stacklevel=2, - ) - return rv @@ -646,12 +627,10 @@ def _record_lost_event( record_lost_func=_record_lost_event, ) - self.span_batcher = None - if has_span_streaming_enabled(self.options): - self.span_batcher = SpanBatcher( - capture_func=_capture_envelope, - record_lost_func=_record_lost_event, - ) + self.span_batcher = SpanBatcher( + capture_func=_capture_envelope, + record_lost_func=_record_lost_event, + ) max_request_body_size = ("always", "never", "small", "medium") if self.options["max_request_body_size"] not in max_request_body_size: diff --git a/sentry_sdk/feature_flags.py b/sentry_sdk/feature_flags.py index 5eaa5e440b..0703e7004f 100644 --- a/sentry_sdk/feature_flags.py +++ b/sentry_sdk/feature_flags.py @@ -4,8 +4,6 @@ import sentry_sdk from sentry_sdk._lru_cache import LRUCache -from sentry_sdk.tracing import Span -from sentry_sdk.tracing_utils import has_span_streaming_enabled if TYPE_CHECKING: from typing import TypedDict @@ -59,17 +57,9 @@ def add_feature_flag(flag: str, result: bool) -> None: Records a flag and its value to be sent on subsequent error events. We recommend you do this on flag evaluations. Flags are buffered per Sentry scope. """ - client = sentry_sdk.get_client() - flags = sentry_sdk.get_isolation_scope().flags flags.set(flag, result) - if has_span_streaming_enabled(client.options): - span = sentry_sdk.traces.get_current_span() - if span and isinstance(span, sentry_sdk.traces.StreamedSpan): - span.set_attribute(f"flag.evaluation.{flag}", result) - - else: - span = sentry_sdk.get_current_span() - if span and isinstance(span, Span): - span.set_flag(f"flag.evaluation.{flag}", result) + span = sentry_sdk.traces.get_current_span() + if span and isinstance(span, sentry_sdk.traces.StreamedSpan): + span.set_attribute(f"flag.evaluation.{flag}", result) diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py index 858bf273f2..c155a3ea52 100644 --- a/sentry_sdk/integrations/aiohttp.py +++ b/sentry_sdk/integrations/aiohttp.py @@ -3,7 +3,6 @@ from functools import wraps import sentry_sdk -from sentry_sdk.api import continue_trace from sentry_sdk.consts import OP, SPANDATA, SPANSTATUS from sentry_sdk.data_collection import ( _apply_data_collection_filtering_to_query_string, @@ -33,11 +32,9 @@ from sentry_sdk.tracing import ( BAGGAGE_HEADER_NAME, SOURCE_FOR_STYLE, - TransactionSource, ) from sentry_sdk.tracing_utils import ( add_http_request_source, - has_span_streaming_enabled, should_propagate_trace, ) from sentry_sdk.utils import ( @@ -71,14 +68,13 @@ if TYPE_CHECKING: from collections.abc import Set from types import SimpleNamespace - from typing import Any, ContextManager, Optional, Tuple, Union + from typing import Any, Optional, Tuple, Union from aiohttp import TraceRequestEndParams, TraceRequestStartParams from aiohttp.web_request import Request from aiohttp.web_urldispatcher import UrlMappingMatchInfo from sentry_sdk._types import Attributes, Event, EventProcessor - from sentry_sdk.tracing import Span from sentry_sdk.utils import ExcInfo @@ -135,7 +131,6 @@ async def sentry_app_handle( return await old_handle(self, request, *args, **kwargs) weak_request = weakref.ref(request) - is_span_streaming_enabled = has_span_streaming_enabled(client.options) with sentry_sdk.isolation_scope() as scope: with track_session(scope, session_mode="request"): @@ -147,72 +142,47 @@ async def sentry_app_handle( headers = dict(request.headers) - span_ctx: "ContextManager[Union[Span, StreamedSpan]]" - if is_span_streaming_enabled: - sentry_sdk.traces.continue_trace(headers) - Scope.set_custom_sampling_context({"aiohttp_request": request}) - - header_attributes: "dict[str, Any]" = {} - for header, header_value in _filter_headers( - headers, - use_annotated_value=False, - ).items(): - header_attributes[ - f"http.request.header.{header.lower()}" - ] = ( - # header_value will always be a string because we set `use_annotated_value` to false above - header_value - ) + sentry_sdk.traces.continue_trace(headers) + Scope.set_custom_sampling_context({"aiohttp_request": request}) + + header_attributes: "dict[str, Any]" = {} + for header, header_value in _filter_headers( + headers, + use_annotated_value=False, + ).items(): + header_attributes[f"http.request.header.{header.lower()}"] = ( + # header_value will always be a string because we set `use_annotated_value` to false above + header_value + ) - url_attributes = {} - client_address_attributes = {} + url_attributes = {} + client_address_attributes = {} - if has_data_collection_enabled(client.options): - url_attributes["url.full"] = "%s://%s%s" % ( - request.scheme, - request.host, - request.path, - ) - url_attributes["url.path"] = request.path - - if request.query_string: - filtered_query_string = ( - _apply_data_collection_filtering_to_query_string( - query_string=request.query_string, - behaviour=client.options["data_collection"][ - "url_query_params" - ], - ) + if has_data_collection_enabled(client.options): + url_attributes["url.full"] = "%s://%s%s" % ( + request.scheme, + request.host, + request.path, + ) + url_attributes["url.path"] = request.path + + if request.query_string: + filtered_query_string = ( + _apply_data_collection_filtering_to_query_string( + query_string=request.query_string, + behaviour=client.options["data_collection"][ + "url_query_params" + ], ) - if filtered_query_string: - url_attributes["url.query"] = filtered_query_string - url_attributes["url.full"] += ( - "?" + filtered_query_string - ) - - if request.remote: - if client.options["data_collection"]["user_info"]: - client_address_attributes["client.address"] = ( - request.remote - ) - scope.set_attribute( - SPANDATA.USER_IP_ADDRESS, request.remote - ) - - elif should_send_default_pii(): - url_full = "%s://%s%s" % ( - request.scheme, - request.host, - request.path, ) - if request.query_string: - url_full += "?" + request.query_string - url_attributes["url.query"] = request.query_string - - url_attributes["url.full"] = url_full - url_attributes["url.path"] = request.path + if filtered_query_string: + url_attributes["url.query"] = filtered_query_string + url_attributes["url.full"] += ( + "?" + filtered_query_string + ) - if request.remote: + if request.remote: + if client.options["data_collection"]["user_info"]: client_address_attributes["client.address"] = ( request.remote ) @@ -220,37 +190,40 @@ async def sentry_app_handle( SPANDATA.USER_IP_ADDRESS, request.remote ) - span_ctx = sentry_sdk.traces.start_span( - # If this name makes it to the UI, AIOHTTP's URL - # resolver did not find a route or died trying. - name="generic AIOHTTP request", - attributes={ - "sentry.op": OP.HTTP_SERVER, - "sentry.origin": AioHttpIntegration.origin, - "sentry.segment.name.source": SegmentNameSource.ROUTE.value, - "http.request.method": request.method, - **url_attributes, - **client_address_attributes, - **header_attributes, - }, - parent_span=None, - ) - else: - transaction = continue_trace( - headers, - op=OP.HTTP_SERVER, - # 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=TransactionSource.ROUTE, - origin=AioHttpIntegration.origin, - ) - span_ctx = sentry_sdk.start_transaction( - transaction, - custom_sampling_context={"aiohttp_request": request}, + elif should_send_default_pii(): + url_full = "%s://%s%s" % ( + request.scheme, + request.host, + request.path, ) + if request.query_string: + url_full += "?" + request.query_string + url_attributes["url.query"] = request.query_string - with span_ctx as span: + url_attributes["url.full"] = url_full + url_attributes["url.path"] = request.path + + if request.remote: + client_address_attributes["client.address"] = request.remote + scope.set_attribute( + SPANDATA.USER_IP_ADDRESS, request.remote + ) + + with sentry_sdk.traces.start_span( + # If this name makes it to the UI, AIOHTTP's URL + # resolver did not find a route or died trying. + name="generic AIOHTTP request", + attributes={ + "sentry.op": OP.HTTP_SERVER, + "sentry.origin": AioHttpIntegration.origin, + "sentry.segment.name.source": SegmentNameSource.ROUTE.value, + "http.request.method": request.method, + **url_attributes, + **client_address_attributes, + **header_attributes, + }, + parent_span=None, + ) as span: try: response = await old_handle(self, request) except HTTPException as e: @@ -393,67 +366,52 @@ async def on_request_start( parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, ) - span: "Union[Span, StreamedSpan, None]" - if has_span_streaming_enabled(client.options): - if sentry_sdk.traces.get_current_span() is None: - span = None - else: - attributes: "Attributes" = { - "sentry.op": OP.HTTP_CLIENT, - "sentry.origin": AioHttpIntegration.origin, - "http.request.method": method, - } - if parsed_url is not None: - if has_data_collection_enabled(client.options): - url_full = parsed_url.url - attributes["url.path"] = params.url.path - - if parsed_url.query: - filtered_query = ( - _apply_data_collection_filtering_to_query_string( - query_string=parsed_url.query, - behaviour=client.options["data_collection"][ - "url_query_params" - ], - ) + span: "Union[StreamedSpan, None]" + if sentry_sdk.traces.get_current_span() is None: + span = None + else: + attributes: "Attributes" = { + "sentry.op": OP.HTTP_CLIENT, + "sentry.origin": AioHttpIntegration.origin, + "http.request.method": method, + } + if parsed_url is not None: + if has_data_collection_enabled(client.options): + url_full = parsed_url.url + attributes["url.path"] = params.url.path + + if parsed_url.query: + filtered_query = ( + _apply_data_collection_filtering_to_query_string( + query_string=parsed_url.query, + behaviour=client.options["data_collection"][ + "url_query_params" + ], ) - if filtered_query: - attributes["url.query"] = filtered_query - url_full += "?" + filtered_query + ) + if filtered_query: + attributes["url.query"] = filtered_query + url_full += "?" + filtered_query - if parsed_url.fragment: - attributes["url.fragment"] = parsed_url.fragment - url_full += "#" + parsed_url.fragment + if parsed_url.fragment: + attributes["url.fragment"] = parsed_url.fragment + url_full += "#" + parsed_url.fragment - attributes["url.full"] = url_full - elif should_send_default_pii(): - url_full = parsed_url.url - attributes["url.path"] = params.url.path + attributes["url.full"] = url_full + elif should_send_default_pii(): + url_full = parsed_url.url + attributes["url.path"] = params.url.path - if parsed_url.query: - url_full += "?" + parsed_url.query - attributes["url.query"] = parsed_url.query - if parsed_url.fragment: - url_full += "#" + parsed_url.fragment - attributes["url.fragment"] = parsed_url.fragment + if parsed_url.query: + url_full += "?" + parsed_url.query + attributes["url.query"] = parsed_url.query + if parsed_url.fragment: + url_full += "#" + parsed_url.fragment + attributes["url.fragment"] = parsed_url.fragment - attributes["url.full"] = url_full + attributes["url.full"] = url_full - span = sentry_sdk.traces.start_span( - name=span_name, attributes=attributes - ) - else: - legacy_span = sentry_sdk.start_span( - op=OP.HTTP_CLIENT, - name=span_name, - origin=AioHttpIntegration.origin, - ) - legacy_span.set_data(SPANDATA.HTTP_METHOD, method) - if parsed_url is not None: - legacy_span.set_data("url", parsed_url.url) - legacy_span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) - legacy_span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) - span = legacy_span + span = sentry_sdk.traces.start_span(name=span_name, attributes=attributes) if should_propagate_trace(client, str(params.url)): for ( diff --git a/sentry_sdk/integrations/aiomysql.py b/sentry_sdk/integrations/aiomysql.py index 2532b36c31..fdee60c1e2 100644 --- a/sentry_sdk/integrations/aiomysql.py +++ b/sentry_sdk/integrations/aiomysql.py @@ -9,7 +9,6 @@ from sentry_sdk.traces import StreamedSpan from sentry_sdk.tracing_utils import ( add_query_source, - has_span_streaming_enabled, record_sql_queries, ) from sentry_sdk.utils import ( @@ -171,42 +170,22 @@ async def _inner(self: "Connection") -> T: if client.get_integration(AioMySQLIntegration) is None: return await f(self) - if has_span_streaming_enabled(client.options): - breadcrumb_data = _get_connect_data(self, use_streaming_keys=True) + breadcrumb_data = _get_connect_data(self, use_streaming_keys=True) - with capture_internal_exceptions(): - sentry_sdk.add_breadcrumb( - message="connect", category="query", data=breadcrumb_data - ) - - if sentry_sdk.traces.get_current_span() is None: - return await f(self) - - span_attributes: dict[str, Any] = { - "sentry.op": OP.DB, - "sentry.origin": AioMySQLIntegration.origin, - } | breadcrumb_data - - with sentry_sdk.traces.start_span( - name="connect", attributes=span_attributes - ): - return await f(self) + with capture_internal_exceptions(): + sentry_sdk.add_breadcrumb( + message="connect", category="query", data=breadcrumb_data + ) - connect_data = _get_connect_data(self) + if sentry_sdk.traces.get_current_span() is None: + return await f(self) - with sentry_sdk.start_span( - op=OP.DB, - name="connect", - origin=AioMySQLIntegration.origin, - ) as span: - _set_db_data(span, self) + span_attributes: dict[str, Any] = { + "sentry.op": OP.DB, + "sentry.origin": AioMySQLIntegration.origin, + } | breadcrumb_data - with capture_internal_exceptions(): - sentry_sdk.add_breadcrumb( - message="connect", - category="query", - data=connect_data, - ) + with sentry_sdk.traces.start_span(name="connect", attributes=span_attributes): return await f(self) return _inner diff --git a/sentry_sdk/integrations/anthropic.py b/sentry_sdk/integrations/anthropic.py index dfa4aef34c..4a18889715 100644 --- a/sentry_sdk/integrations/anthropic.py +++ b/sentry_sdk/integrations/anthropic.py @@ -8,7 +8,6 @@ from sentry_sdk.ai.monitoring import record_token_usage from sentry_sdk.ai.utils import ( GEN_AI_ALLOWED_MESSAGE_ROLES, - get_start_span_function, normalize_message_roles, set_data_normalized, transform_anthropic_content_part, @@ -20,7 +19,6 @@ from sentry_sdk.traces import StreamedSpan from sentry_sdk.tracing import Span from sentry_sdk.tracing_utils import ( - has_span_streaming_enabled, should_truncate_gen_ai_input, ) from sentry_sdk.utils import ( @@ -638,22 +636,13 @@ def _sentry_patched_create_sync(f: "Any", *args: "Any", **kwargs: "Any") -> "Any model = kwargs.get("model", "") - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - span = sentry_sdk.traces.start_span( - name=f"chat {model}".strip(), - attributes={ - "sentry.op": OP.GEN_AI_CHAT, - "sentry.origin": AnthropicIntegration.origin, - }, - ) - else: - span = get_start_span_function()( - op=OP.GEN_AI_CHAT, - name=f"chat {model}".strip(), - origin=AnthropicIntegration.origin, - ) - span.__enter__() + span = sentry_sdk.traces.start_span( + name=f"chat {model}".strip(), + attributes={ + "sentry.op": OP.GEN_AI_CHAT, + "sentry.origin": AnthropicIntegration.origin, + }, + ) _set_create_input_data(span, kwargs, integration) @@ -736,22 +725,13 @@ async def _sentry_patched_create_async( model = kwargs.get("model", "") - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - span = sentry_sdk.traces.start_span( - name=f"chat {model}".strip(), - attributes={ - "sentry.op": OP.GEN_AI_CHAT, - "sentry.origin": AnthropicIntegration.origin, - }, - ) - else: - span = get_start_span_function()( - op=OP.GEN_AI_CHAT, - name=f"chat {model}".strip(), - origin=AnthropicIntegration.origin, - ) - span.__enter__() + span = sentry_sdk.traces.start_span( + name=f"chat {model}".strip(), + attributes={ + "sentry.op": OP.GEN_AI_CHAT, + "sentry.origin": AnthropicIntegration.origin, + }, + ) _set_create_input_data(span, kwargs, integration) @@ -981,24 +961,14 @@ def _sentry_patched_enter(self: "MessageStreamManager") -> "MessageStream": except TypeError: return f(self) - if has_span_streaming_enabled(client.options): - span = sentry_sdk.traces.start_span( - name="chat" if self._model is None else f"chat {self._model}".strip(), - attributes={ - "sentry.op": OP.GEN_AI_CHAT, - "sentry.origin": AnthropicIntegration.origin, - SPANDATA.GEN_AI_RESPONSE_STREAMING: True, - }, - ) - else: - span = get_start_span_function()( - op=OP.GEN_AI_CHAT, - name="chat" if self._model is None else f"chat {self._model}".strip(), - origin=AnthropicIntegration.origin, - ) - span.__enter__() - - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True) + span = sentry_sdk.traces.start_span( + name="chat" if self._model is None else f"chat {self._model}".strip(), + attributes={ + "sentry.op": OP.GEN_AI_CHAT, + "sentry.origin": AnthropicIntegration.origin, + SPANDATA.GEN_AI_RESPONSE_STREAMING: True, + }, + ) _set_common_input_data( span=span, @@ -1088,24 +1058,14 @@ async def _sentry_patched_aenter( except TypeError: return await f(self) - if has_span_streaming_enabled(client.options): - span = sentry_sdk.traces.start_span( - name="chat" if self._model is None else f"chat {self._model}".strip(), - attributes={ - "sentry.op": OP.GEN_AI_CHAT, - "sentry.origin": AnthropicIntegration.origin, - SPANDATA.GEN_AI_RESPONSE_STREAMING: True, - }, - ) - else: - span = get_start_span_function()( - op=OP.GEN_AI_CHAT, - name="chat" if self._model is None else f"chat {self._model}".strip(), - origin=AnthropicIntegration.origin, - ) - span.__enter__() - - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True) + span = sentry_sdk.traces.start_span( + name="chat" if self._model is None else f"chat {self._model}".strip(), + attributes={ + "sentry.op": OP.GEN_AI_CHAT, + "sentry.origin": AnthropicIntegration.origin, + SPANDATA.GEN_AI_RESPONSE_STREAMING: True, + }, + ) _set_common_input_data( span=span, diff --git a/sentry_sdk/integrations/arq.py b/sentry_sdk/integrations/arq.py index 9d6497f03a..cb830e939b 100644 --- a/sentry_sdk/integrations/arq.py +++ b/sentry_sdk/integrations/arq.py @@ -6,8 +6,6 @@ from sentry_sdk.integrations.logging import ignore_logger from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import SegmentNameSource -from sentry_sdk.tracing import Transaction, TransactionSource -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( SENSITIVE_DATA_SUBSTITUTE, _register_control_flow_exception, @@ -79,21 +77,15 @@ async def _sentry_enqueue_job( if client.get_integration(ArqIntegration) is None: return await old_enqueue_job(self, function, *args, **kwargs) - if has_span_streaming_enabled(client.options): - if sentry_sdk.traces.get_current_span() is None: - return await old_enqueue_job(self, function, *args, **kwargs) - - with sentry_sdk.traces.start_span( - name=function, - attributes={ - "sentry.op": OP.QUEUE_SUBMIT_ARQ, - "sentry.origin": ArqIntegration.origin, - }, - ): - return await old_enqueue_job(self, function, *args, **kwargs) + if sentry_sdk.traces.get_current_span() is None: + return await old_enqueue_job(self, function, *args, **kwargs) - with sentry_sdk.start_span( - op=OP.QUEUE_SUBMIT_ARQ, name=function, origin=ArqIntegration.origin + with sentry_sdk.traces.start_span( + name=function, + attributes={ + "sentry.op": OP.QUEUE_SUBMIT_ARQ, + "sentry.origin": ArqIntegration.origin, + }, ): return await old_enqueue_job(self, function, *args, **kwargs) @@ -113,34 +105,20 @@ async def _sentry_run_job(self: "Worker", job_id: str, score: int) -> None: scope._name = "arq" scope.clear_breadcrumbs() - if has_span_streaming_enabled(client.options): - with sentry_sdk.traces.start_span( - name="unknown arq task", - attributes={ - "sentry.op": OP.QUEUE_TASK_ARQ, - "sentry.origin": ArqIntegration.origin, - "sentry.segment.name.source": SegmentNameSource.TASK, - SPANDATA.MESSAGING_MESSAGE_ID: job_id, - }, - parent_span=None, - ) as span: - if self.queue_name is not None: - span.set_attribute( - SPANDATA.MESSAGING_DESTINATION_NAME, self.queue_name - ) - return await old_run_job(self, job_id, score) - - transaction = Transaction( + with sentry_sdk.traces.start_span( name="unknown arq task", - status="ok", - op=OP.QUEUE_TASK_ARQ, - source=TransactionSource.TASK, - origin=ArqIntegration.origin, - ) - - with sentry_sdk.start_transaction(transaction) as span: + attributes={ + "sentry.op": OP.QUEUE_TASK_ARQ, + "sentry.origin": ArqIntegration.origin, + "sentry.segment.name.source": SegmentNameSource.TASK, + SPANDATA.MESSAGING_MESSAGE_ID: job_id, + }, + parent_span=None, + ) as span: if self.queue_name is not None: - span.set_data(SPANDATA.MESSAGING_DESTINATION_NAME, self.queue_name) + span.set_attribute( + SPANDATA.MESSAGING_DESTINATION_NAME, self.queue_name + ) return await old_run_job(self, job_id, score) Worker.run_job = _sentry_run_job @@ -215,13 +193,12 @@ async def _sentry_coroutine( if integration is None: return await coroutine(ctx, *args, **kwargs) - if has_span_streaming_enabled(client.options): - scope = sentry_sdk.get_current_scope() - span = scope.streamed_span - if span is not None: - span.name = name + scope = sentry_sdk.get_current_scope() + span = scope.streamed_span + if span is not None: + span.name = name - scope.set_transaction_name(name) + scope.set_transaction_name(name) sentry_sdk.get_isolation_scope().add_event_processor( _make_event_processor({**ctx, "job_name": name}, *args, **kwargs) diff --git a/sentry_sdk/integrations/asgi.py b/sentry_sdk/integrations/asgi.py index fa240e35d6..af4eb15500 100644 --- a/sentry_sdk/integrations/asgi.py +++ b/sentry_sdk/integrations/asgi.py @@ -11,7 +11,6 @@ from typing import TYPE_CHECKING import sentry_sdk -from sentry_sdk.api import continue_trace from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations._asgi_common import ( _get_headers, @@ -36,10 +35,8 @@ ) from sentry_sdk.tracing import ( SOURCE_FOR_STYLE, - Transaction, TransactionSource, ) -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( CONTEXTVARS_ERROR_MESSAGE, HAS_REAL_CONTEXTVARS, @@ -59,7 +56,6 @@ from typing import Any, ContextManager, Dict, Optional, Tuple, Union from sentry_sdk._types import Attributes, Event, Hint - from sentry_sdk.tracing import Span _asgi_middleware_applied = ContextVar("sentry_asgi_middleware_applied") @@ -211,9 +207,6 @@ async def _run_app( self._capture_lifespan_exception(exc) reraise(*exc_info) - client = sentry_sdk.get_client() - span_streaming = has_span_streaming_enabled(client.options) - _asgi_middleware_applied.set(True) try: with sentry_sdk.isolation_scope() as sentry_scope: @@ -234,92 +227,55 @@ async def _run_app( method = scope.get("method", "").upper() - span_ctx: "ContextManager[Union[Span, StreamedSpan, None]]" - if span_streaming: - segment: "Optional[StreamedSpan]" = None - attributes: "Attributes" = { - "sentry.segment.name.source": getattr( - transaction_source, "value", transaction_source - ), - "sentry.origin": self.span_origin, - "network.protocol.name": ty, - } - - if scope.get("client"): - client_options = sentry_sdk.get_client().options - if has_data_collection_enabled(client_options): - if client_options["data_collection"]["user_info"]: - sentry_scope.set_attribute( - SPANDATA.USER_IP_ADDRESS, _get_ip(scope) - ) - elif should_send_default_pii(): + span_ctx: "ContextManager[Union[StreamedSpan, None]]" + + segment: "Optional[StreamedSpan]" = None + attributes: "Attributes" = { + "sentry.segment.name.source": getattr( + transaction_source, "value", transaction_source + ), + "sentry.origin": self.span_origin, + "network.protocol.name": ty, + } + + if scope.get("client"): + client_options = sentry_sdk.get_client().options + if has_data_collection_enabled(client_options): + if client_options["data_collection"]["user_info"]: sentry_scope.set_attribute( SPANDATA.USER_IP_ADDRESS, _get_ip(scope) ) + elif should_send_default_pii(): + sentry_scope.set_attribute( + SPANDATA.USER_IP_ADDRESS, _get_ip(scope) + ) - if ty in ("http", "websocket"): - if ( - ty == "websocket" - or method in self.http_methods_to_capture - ): - sentry_sdk.traces.continue_trace(_get_headers(scope)) - - Scope.set_custom_sampling_context({"asgi_scope": scope}) - - attributes["sentry.op"] = f"{ty}.server" - segment = sentry_sdk.traces.start_span( - name=transaction_name, - attributes=attributes, - parent_span=None, - ) - else: - sentry_sdk.traces.new_trace() + if ty in ("http", "websocket"): + if ty == "websocket" or method in self.http_methods_to_capture: + sentry_sdk.traces.continue_trace(_get_headers(scope)) Scope.set_custom_sampling_context({"asgi_scope": scope}) - attributes["sentry.op"] = OP.HTTP_SERVER + attributes["sentry.op"] = f"{ty}.server" segment = sentry_sdk.traces.start_span( name=transaction_name, attributes=attributes, parent_span=None, ) - - span_ctx = segment or nullcontext() - else: - transaction = None - if ty in ("http", "websocket"): - if ( - ty == "websocket" - or method in self.http_methods_to_capture - ): - transaction = continue_trace( - _get_headers(scope), - op="{}.server".format(ty), - name=transaction_name, - source=transaction_source, - origin=self.span_origin, - ) - else: - transaction = Transaction( - op=OP.HTTP_SERVER, - name=transaction_name, - source=transaction_source, - origin=self.span_origin, - ) + sentry_sdk.traces.new_trace() - if transaction: - transaction.set_tag("asgi.type", ty) + Scope.set_custom_sampling_context({"asgi_scope": scope}) - span_ctx = ( - sentry_sdk.start_transaction( - transaction, - custom_sampling_context={"asgi_scope": scope}, - ) - if transaction is not None - else nullcontext() + attributes["sentry.op"] = OP.HTTP_SERVER + segment = sentry_sdk.traces.start_span( + name=transaction_name, + attributes=attributes, + parent_span=None, ) + span_ctx = segment or nullcontext() + with span_ctx as span: if isinstance(span, StreamedSpan): for attribute, value in _get_request_attributes( diff --git a/sentry_sdk/integrations/asyncio.py b/sentry_sdk/integrations/asyncio.py index c7e25a6a76..267063d0d2 100644 --- a/sentry_sdk/integrations/asyncio.py +++ b/sentry_sdk/integrations/asyncio.py @@ -6,7 +6,6 @@ from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.traces import StreamedSpan from sentry_sdk.tracing import Span -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.transport import AsyncHttpTransport from sentry_sdk.utils import ( event_from_exception, @@ -150,24 +149,16 @@ async def _task_with_sentry_span_creation() -> "Any": task_spans = integration.task_spans if integration else False span_ctx: "Optional[Union[StreamedSpan, Span]]" = None - is_span_streaming_enabled = has_span_streaming_enabled(client.options) with sentry_sdk.isolation_scope(): if task_spans: - if is_span_streaming_enabled: - if sentry_sdk.traces.get_current_span() is not None: - span_ctx = sentry_sdk.traces.start_span( - name=get_name(coro), - attributes={ - "sentry.op": OP.FUNCTION, - "sentry.origin": AsyncioIntegration.origin, - }, - ) - else: - span_ctx = sentry_sdk.start_span( - op=OP.FUNCTION, + if sentry_sdk.traces.get_current_span() is not None: + span_ctx = sentry_sdk.traces.start_span( name=get_name(coro), - origin=AsyncioIntegration.origin, + attributes={ + "sentry.op": OP.FUNCTION, + "sentry.origin": AsyncioIntegration.origin, + }, ) with span_ctx if span_ctx else nullcontext(): diff --git a/sentry_sdk/integrations/asyncpg.py b/sentry_sdk/integrations/asyncpg.py index 5354078ca2..ed0de39c3f 100644 --- a/sentry_sdk/integrations/asyncpg.py +++ b/sentry_sdk/integrations/asyncpg.py @@ -11,7 +11,6 @@ from sentry_sdk.tracing import Span from sentry_sdk.tracing_utils import ( add_query_source, - has_span_streaming_enabled, record_sql_queries, ) from sentry_sdk.utils import ( @@ -219,55 +218,30 @@ async def _inner(*args: "Any", **kwargs: "Any") -> "T": database = kwargs["params"].database addr = kwargs.get("addr") - if has_span_streaming_enabled(client.options): - span_attributes = { - "sentry.op": OP.DB, - "sentry.origin": AsyncPGIntegration.origin, - SPANDATA.DB_SYSTEM_NAME: "postgresql", - SPANDATA.DB_USER: user, - SPANDATA.DB_NAMESPACE: database, - SPANDATA.DB_DRIVER_NAME: "asyncpg", - } - if addr: - try: - span_attributes[SPANDATA.SERVER_ADDRESS] = addr[0] - span_attributes[SPANDATA.SERVER_PORT] = addr[1] - except IndexError: - pass + span_attributes = { + "sentry.op": OP.DB, + "sentry.origin": AsyncPGIntegration.origin, + SPANDATA.DB_SYSTEM_NAME: "postgresql", + SPANDATA.DB_USER: user, + SPANDATA.DB_NAMESPACE: database, + SPANDATA.DB_DRIVER_NAME: "asyncpg", + } + if addr: + try: + span_attributes[SPANDATA.SERVER_ADDRESS] = addr[0] + span_attributes[SPANDATA.SERVER_PORT] = addr[1] + except IndexError: + pass - with capture_internal_exceptions(): - sentry_sdk.add_breadcrumb( - message="connect", category="query", data=span_attributes - ) - - if sentry_sdk.traces.get_current_span() is None: - return await f(*args, **kwargs) - - with sentry_sdk.traces.start_span( - name="connect", attributes=span_attributes - ): - return await f(*args, **kwargs) - - with sentry_sdk.start_span( - op=OP.DB, - name="connect", - origin=AsyncPGIntegration.origin, - ) as span: - span.set_data(SPANDATA.DB_SYSTEM, "postgresql") - if addr: - try: - span.set_data(SPANDATA.SERVER_ADDRESS, addr[0]) - span.set_data(SPANDATA.SERVER_PORT, addr[1]) - except IndexError: - pass - span.set_data(SPANDATA.DB_NAME, database) - span.set_data(SPANDATA.DB_USER, user) - span.set_data(SPANDATA.DB_DRIVER_NAME, "asyncpg") + with capture_internal_exceptions(): + sentry_sdk.add_breadcrumb( + message="connect", category="query", data=span_attributes + ) - with capture_internal_exceptions(): - sentry_sdk.add_breadcrumb( - message="connect", category="query", data=span._data - ) + if sentry_sdk.traces.get_current_span() is None: + return await f(*args, **kwargs) + + with sentry_sdk.traces.start_span(name="connect", attributes=span_attributes): return await f(*args, **kwargs) return _inner diff --git a/sentry_sdk/integrations/aws_lambda.py b/sentry_sdk/integrations/aws_lambda.py index 6dad75076c..8c87161962 100644 --- a/sentry_sdk/integrations/aws_lambda.py +++ b/sentry_sdk/integrations/aws_lambda.py @@ -9,7 +9,6 @@ from urllib.parse import urlencode import sentry_sdk -from sentry_sdk.api import continue_trace from sentry_sdk.consts import OP from sentry_sdk.data_collection import _apply_key_value_collection_filtering from sentry_sdk.integrations import Integration @@ -20,8 +19,6 @@ ) from sentry_sdk.scope import Scope, should_send_default_pii from sentry_sdk.traces import SegmentNameSource -from sentry_sdk.tracing import TransactionSource -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( AnnotatedValue, TimeoutThread, @@ -188,45 +185,31 @@ def sentry_handler( function_name = aws_context.function_name - if has_span_streaming_enabled(client.options): - sentry_sdk.traces.continue_trace(headers) - Scope.set_custom_sampling_context(sampling_context) - span_ctx = sentry_sdk.traces.start_span( - name=function_name, - parent_span=None, - attributes={ - "sentry.op": OP.FUNCTION_AWS, - "sentry.origin": AwsLambdaIntegration.origin, - "sentry.segment.name.source": SegmentNameSource.COMPONENT, - "cloud.region": aws_region, - "cloud.resource_id": aws_context.invoked_function_arn, - "cloud.platform": CLOUD_PLATFORM.AWS_LAMBDA, - "cloud.provider": CLOUD_PROVIDER.AWS, - "faas.name": function_name, - "faas.invocation_id": aws_context.aws_request_id, - "faas.version": aws_context.function_version, - "aws.lambda.invoked_arn": aws_context.invoked_function_arn, - "aws.log.group.names": [aws_context.log_group_name], - "aws.log.stream.names": [aws_context.log_stream_name], - "messaging.batch.message_count": batch_size, - **header_attributes, - **additional_attributes, - }, - ) - else: - transaction = continue_trace( - headers, - op=OP.FUNCTION_AWS, - name=function_name, - source=TransactionSource.COMPONENT, - origin=AwsLambdaIntegration.origin, - ) - - span_ctx = sentry_sdk.start_transaction( - transaction, custom_sampling_context=sampling_context - ) - - with span_ctx: + sentry_sdk.traces.continue_trace(headers) + Scope.set_custom_sampling_context(sampling_context) + + with sentry_sdk.traces.start_span( + name=function_name, + parent_span=None, + attributes={ + "sentry.op": OP.FUNCTION_AWS, + "sentry.origin": AwsLambdaIntegration.origin, + "sentry.segment.name.source": SegmentNameSource.COMPONENT, + "cloud.region": aws_region, + "cloud.resource_id": aws_context.invoked_function_arn, + "cloud.platform": CLOUD_PLATFORM.AWS_LAMBDA, + "cloud.provider": CLOUD_PROVIDER.AWS, + "faas.name": function_name, + "faas.invocation_id": aws_context.aws_request_id, + "faas.version": aws_context.function_version, + "aws.lambda.invoked_arn": aws_context.invoked_function_arn, + "aws.log.group.names": [aws_context.log_group_name], + "aws.log.stream.names": [aws_context.log_stream_name], + "messaging.batch.message_count": batch_size, + **header_attributes, + **additional_attributes, + }, + ): try: return handler(aws_event, aws_context, *args, **kwargs) except Exception: diff --git a/sentry_sdk/integrations/boto3.py b/sentry_sdk/integrations/boto3.py index 69deefc7b7..18bd7db38f 100644 --- a/sentry_sdk/integrations/boto3.py +++ b/sentry_sdk/integrations/boto3.py @@ -7,7 +7,6 @@ from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import StreamedSpan from sentry_sdk.tracing import Span -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( capture_internal_exceptions, parse_url, @@ -64,50 +63,26 @@ def _sentry_request_created( if client.get_integration(Boto3Integration) is None: return - is_span_streaming_enabled = has_span_streaming_enabled(client.options) - span: "Union[Span, StreamedSpan]" - if is_span_streaming_enabled: - if sentry_sdk.traces.get_current_span() is None: - return - span = sentry_sdk.traces.start_span( - name=description, - attributes={ - "sentry.op": OP.HTTP_CLIENT, - "sentry.origin": Boto3Integration.origin, - SPANDATA.RPC_METHOD: f"{service_id}/{operation_name}", - }, - ) - if request.url is not None and should_send_default_pii(): - with capture_internal_exceptions(): - parsed_url = parse_url(request.url, sanitize=False) - span.set_attribute(SPANDATA.URL_FULL, parsed_url.url) - span.set_attribute(SPANDATA.URL_QUERY, parsed_url.query) - span.set_attribute(SPANDATA.URL_FRAGMENT, parsed_url.fragment) - - if request.method is not None: - span.set_attribute(SPANDATA.HTTP_REQUEST_METHOD, request.method) - else: - span = sentry_sdk.start_span( - op=OP.HTTP_CLIENT, - name=description, - origin=Boto3Integration.origin, - ) + if sentry_sdk.traces.get_current_span() is None: + return - if request.url is not None: - with capture_internal_exceptions(): - parsed_url = parse_url(request.url, sanitize=False) - span.set_data("aws.request.url", parsed_url.url) - span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) - span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) - - span.set_tag("aws.service_id", service_id.hyphenize()) - span.set_tag("aws.operation_name", operation_name) - if request.method is not None: - span.set_data(SPANDATA.HTTP_METHOD, request.method) - - # We do it in order for subsequent http calls/retries be - # attached to this span. - span.__enter__() + span = sentry_sdk.traces.start_span( + name=description, + attributes={ + "sentry.op": OP.HTTP_CLIENT, + "sentry.origin": Boto3Integration.origin, + SPANDATA.RPC_METHOD: f"{service_id}/{operation_name}", + }, + ) + if request.url is not None and should_send_default_pii(): + with capture_internal_exceptions(): + parsed_url = parse_url(request.url, sanitize=False) + span.set_attribute(SPANDATA.URL_FULL, parsed_url.url) + span.set_attribute(SPANDATA.URL_QUERY, parsed_url.query) + span.set_attribute(SPANDATA.URL_FRAGMENT, parsed_url.fragment) + + if request.method is not None: + span.set_attribute(SPANDATA.HTTP_REQUEST_METHOD, request.method) # request.context is an open-ended data-structure # where we can add anything useful in request life cycle. diff --git a/sentry_sdk/integrations/bottle.py b/sentry_sdk/integrations/bottle.py index 50f6ca2e1d..b0d112d96a 100644 --- a/sentry_sdk/integrations/bottle.py +++ b/sentry_sdk/integrations/bottle.py @@ -12,7 +12,6 @@ from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware from sentry_sdk.traces import SOURCE_FOR_STYLE as SEGMENT_SOURCE_FOR_STYLE from sentry_sdk.tracing import SOURCE_FOR_STYLE as TRANSACTION_SOURCE_FOR_STYLE -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -104,10 +103,9 @@ def _patched_handle(self: "Bottle", environ: "Dict[str, Any]") -> "Any": ) res = old_handle(self, environ) - if has_span_streaming_enabled(sentry_sdk.get_client().options): - _set_segment_name_and_source( - transaction_style=integration.transaction_style - ) + _set_segment_name_and_source( + transaction_style=integration.transaction_style + ) return res diff --git a/sentry_sdk/integrations/celery/__init__.py b/sentry_sdk/integrations/celery/__init__.py index 51eedf976b..91addbb278 100644 --- a/sentry_sdk/integrations/celery/__init__.py +++ b/sentry_sdk/integrations/celery/__init__.py @@ -5,8 +5,7 @@ import sentry_sdk from sentry_sdk import isolation_scope -from sentry_sdk.api import continue_trace -from sentry_sdk.consts import OP, SPANDATA, SPANSTATUS +from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version from sentry_sdk.integrations.celery.beat import ( _patch_beat_apply_entry, @@ -17,8 +16,8 @@ from sentry_sdk.integrations.logging import ignore_logger from sentry_sdk.scope import Scope, should_send_default_pii from sentry_sdk.traces import SegmentNameSource, StreamedSpan, get_current_span -from sentry_sdk.tracing import BAGGAGE_HEADER_NAME, Span, TransactionSource -from sentry_sdk.tracing_utils import Baggage, has_span_streaming_enabled +from sentry_sdk.tracing import BAGGAGE_HEADER_NAME, Span +from sentry_sdk.tracing_utils import Baggage from sentry_sdk.utils import ( SENSITIVE_DATA_SUBSTITUTE, capture_internal_exceptions, @@ -93,16 +92,11 @@ def setup_once() -> None: def _set_status(status: str) -> None: - client = sentry_sdk.get_client() - span_streaming = has_span_streaming_enabled(client.options) - with capture_internal_exceptions(): scope = sentry_sdk.get_current_scope() - if span_streaming and scope.streamed_span is not None: + if scope.streamed_span is not None: scope.streamed_span.status = "ok" if status == "ok" else "error" - elif not span_streaming and scope.span is not None: - scope.span.set_status(status) def _capture_exception(task: "Any", exc_info: "ExcInfo") -> None: @@ -288,28 +282,17 @@ def apply_async(*args: "Any", **kwargs: "Any") -> "Any": else: task_name = "" - span_streaming = has_span_streaming_enabled(client.options) - task_started_from_beat = sentry_sdk.get_isolation_scope()._name == "celery-beat" - span_mgr: "Union[StreamedSpan, Span, NoOpMgr]" = NoOpMgr() - if span_streaming: - if not task_started_from_beat and get_current_span() is not None: - span_mgr = sentry_sdk.traces.start_span( - name=task_name, - attributes={ - "sentry.op": OP.QUEUE_SUBMIT_CELERY, - "sentry.origin": CeleryIntegration.origin, - }, - ) - - else: - if not task_started_from_beat: - span_mgr = sentry_sdk.start_span( - op=OP.QUEUE_SUBMIT_CELERY, - name=task_name, - origin=CeleryIntegration.origin, - ) + span_mgr: "Union[StreamedSpan, NoOpMgr]" = NoOpMgr() + if not task_started_from_beat and get_current_span() is not None: + span_mgr = sentry_sdk.traces.start_span( + name=task_name, + attributes={ + "sentry.op": OP.QUEUE_SUBMIT_CELERY, + "sentry.origin": CeleryIntegration.origin, + }, + ) with span_mgr as span: kwargs["headers"] = _update_celery_task_headers( @@ -333,8 +316,6 @@ def _inner(*args: "Any", **kwargs: "Any") -> "Any": if client.get_integration(CeleryIntegration) is None: return f(*args, **kwargs) - span_streaming = has_span_streaming_enabled(client.options) - with isolation_scope() as scope: scope._name = "celery" scope.clear_breadcrumbs() @@ -361,35 +342,20 @@ def _inner(*args: "Any", **kwargs: "Any") -> "Any": # something such as attribute access can fail. with capture_internal_exceptions(): headers = args[3].get("headers") or {} - if span_streaming: - sentry_sdk.traces.continue_trace(headers) - Scope.set_custom_sampling_context(custom_sampling_context) - span = sentry_sdk.traces.start_span( - name=task_name, - parent_span=None, # make this a segment - attributes={ - "sentry.origin": CeleryIntegration.origin, - "sentry.segment.name.source": SegmentNameSource.TASK.value, - "sentry.op": OP.QUEUE_TASK_CELERY, - }, - ) - - span_ctx = span - else: - span = continue_trace( - headers, - op=OP.QUEUE_TASK_CELERY, - name=task_name, - source=TransactionSource.TASK, - origin=CeleryIntegration.origin, - ) - span.set_status(SPANSTATUS.OK) + sentry_sdk.traces.continue_trace(headers) + Scope.set_custom_sampling_context(custom_sampling_context) + span = sentry_sdk.traces.start_span( + name=task_name, + parent_span=None, # make this a segment + attributes={ + "sentry.origin": CeleryIntegration.origin, + "sentry.segment.name.source": SegmentNameSource.TASK.value, + "sentry.op": OP.QUEUE_TASK_CELERY, + }, + ) - span_ctx = sentry_sdk.start_transaction( - span, - custom_sampling_context=custom_sampling_context, - ) + span_ctx = span with span_ctx: return f(*args, **kwargs) @@ -424,29 +390,17 @@ def _inner(*args: "Any", **kwargs: "Any") -> "Any": if client.get_integration(CeleryIntegration) is None: return f(*args, **kwargs) - span_streaming = has_span_streaming_enabled(client.options) - try: - if span_streaming and get_current_span() is None: + if get_current_span() is None: return f(*args, **kwargs) - span: "Union[Span, StreamedSpan]" - if span_streaming: - span = sentry_sdk.traces.start_span( - name=task.name, - attributes={ - "sentry.op": OP.QUEUE_PROCESS, - "sentry.origin": CeleryIntegration.origin, - }, - ) - else: - span = sentry_sdk.start_span( - op=OP.QUEUE_PROCESS, - name=task.name, - origin=CeleryIntegration.origin, - ) - - with span: + with sentry_sdk.traces.start_span( + name=task.name, + attributes={ + "sentry.op": OP.QUEUE_PROCESS, + "sentry.origin": CeleryIntegration.origin, + }, + ) as span: if isinstance(span, StreamedSpan): set_on_span = span.set_attribute else: @@ -559,8 +513,6 @@ def sentry_publish(self: "Producer", *args: "Any", **kwargs: "Any") -> "Any": if client.get_integration(CeleryIntegration) is None: return original_publish(self, *args, **kwargs) - span_streaming = has_span_streaming_enabled(client.options) - kwargs_headers = kwargs.get("headers", {}) if not isinstance(kwargs_headers, Mapping): # Ensure kwargs_headers is a Mapping, so we can safely call get(). @@ -577,21 +529,14 @@ def sentry_publish(self: "Producer", *args: "Any", **kwargs: "Any") -> "Any": routing_key = kwargs.get("routing_key") exchange = kwargs.get("exchange") - span: "Union[StreamedSpan, Span, None]" = None - if span_streaming: - if get_current_span() is not None: - span = sentry_sdk.traces.start_span( - name=task_name, - attributes={ - "sentry.op": OP.QUEUE_PUBLISH, - "sentry.origin": CeleryIntegration.origin, - }, - ) - else: - span = sentry_sdk.start_span( - op=OP.QUEUE_PUBLISH, + span: "Optional[StreamedSpan]" = None + if get_current_span() is not None: + span = sentry_sdk.traces.start_span( name=task_name, - origin=CeleryIntegration.origin, + attributes={ + "sentry.op": OP.QUEUE_PUBLISH, + "sentry.origin": CeleryIntegration.origin, + }, ) if span is None: diff --git a/sentry_sdk/integrations/chalice.py b/sentry_sdk/integrations/chalice.py index 9baa0e5cdd..c5904a4286 100644 --- a/sentry_sdk/integrations/chalice.py +++ b/sentry_sdk/integrations/chalice.py @@ -10,8 +10,6 @@ StreamedSpan, get_current_span, ) -from sentry_sdk.tracing import TransactionSource -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( capture_internal_exceptions, event_from_exception, @@ -78,73 +76,53 @@ def wrapped_view_function(**function_args: "Any") -> "Any": ) ) - if has_span_streaming_enabled(client.options): - current_span = get_current_span() - segment = None - if type(current_span) is StreamedSpan: - # A segment already exists (created by the AWS Lambda - # integration), so decorate it with Chalice attributes - # The AWS Lambda integration owns the span lifecycle - # (end + flush), but Chalice converts unhandled view exceptions - # into 500 responses, so the error must be captured here. - request_dict = app.current_request.to_dict() - headers = request_dict.get("headers", {}) - - header_attrs: "Dict[str, Any]" = {} - for header, value in _filter_headers( - headers, use_annotated_value=False - ).items(): - header_attrs[f"http.request.header.{header.lower()}"] = value - - additional_attrs: "Dict[str, Any]" = {} - if "method" in request_dict: - additional_attrs["http.request.method"] = request_dict["method"] - - attributes = { - "sentry.origin": ChaliceIntegration.origin, - **header_attrs, - **additional_attrs, - } - - segment = current_span._segment - segment.set_attributes(attributes) - - try: - return view_function(**function_args) - except Exception as exc: - if isinstance(exc, ChaliceViewError): - raise - exc_info = sys.exc_info() - if segment: - segment.status = SpanStatus.ERROR.value - sentry_event, hint = event_from_exception( - exc_info, - client_options=client.options, - mechanism={"type": "chalice", "handled": False}, - ) - sentry_sdk.capture_event(sentry_event, hint=hint) - if segment is None: - client.flush() + current_span = get_current_span() + segment = None + if type(current_span) is StreamedSpan: + # A segment already exists (created by the AWS Lambda + # integration), so decorate it with Chalice attributes + # The AWS Lambda integration owns the span lifecycle + # (end + flush), but Chalice converts unhandled view exceptions + # into 500 responses, so the error must be captured here. + request_dict = app.current_request.to_dict() + headers = request_dict.get("headers", {}) + + header_attrs: "Dict[str, Any]" = {} + for header, value in _filter_headers( + headers, use_annotated_value=False + ).items(): + header_attrs[f"http.request.header.{header.lower()}"] = value + + additional_attrs: "Dict[str, Any]" = {} + if "method" in request_dict: + additional_attrs["http.request.method"] = request_dict["method"] + + attributes = { + "sentry.origin": ChaliceIntegration.origin, + **header_attrs, + **additional_attrs, + } + + segment = current_span._segment + segment.set_attributes(attributes) + + try: + return view_function(**function_args) + except Exception as exc: + if isinstance(exc, ChaliceViewError): raise - else: - scope.set_transaction_name( - app.lambda_context.function_name, - source=TransactionSource.COMPONENT, + exc_info = sys.exc_info() + if segment: + segment.status = SpanStatus.ERROR.value + sentry_event, hint = event_from_exception( + exc_info, + client_options=client.options, + mechanism={"type": "chalice", "handled": False}, ) - try: - return view_function(**function_args) - except Exception as exc: - if isinstance(exc, ChaliceViewError): - raise - exc_info = sys.exc_info() - sentry_event, hint = event_from_exception( - exc_info, - client_options=client.options, - mechanism={"type": "chalice", "handled": False}, - ) - sentry_sdk.capture_event(sentry_event, hint=hint) + sentry_sdk.capture_event(sentry_event, hint=hint) + if segment is None: client.flush() - raise + raise return wrapped_view_function # type: ignore diff --git a/sentry_sdk/integrations/clickhouse_driver.py b/sentry_sdk/integrations/clickhouse_driver.py index 9583b25ca9..68e2684f94 100644 --- a/sentry_sdk/integrations/clickhouse_driver.py +++ b/sentry_sdk/integrations/clickhouse_driver.py @@ -7,7 +7,6 @@ from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import StreamedSpan from sentry_sdk.tracing import Span -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import capture_internal_exceptions # Hack to get new Python features working in older versions @@ -81,34 +80,17 @@ def _inner(*args: "P.args", **kwargs: "P.kwargs") -> "T": connection = args[0] query = args[1] - query_id = args[2] if len(args) > 2 else kwargs.get("query_id") - params = args[3] if len(args) > 3 else kwargs.get("params") - - if has_span_streaming_enabled(client.options): - span = None - if sentry_sdk.traces.get_current_span() is not None: - span = sentry_sdk.traces.start_span( - name=query, # type: ignore - attributes={ - "sentry.op": OP.DB, - "sentry.origin": ClickhouseDriverIntegration.origin, - SPANDATA.DB_QUERY_TEXT: str(query), - }, - ) - else: - span = sentry_sdk.start_span( - op=OP.DB, - name=query, - origin=ClickhouseDriverIntegration.origin, - ) - span.set_data("query", query) - - if query_id: - span.set_data("db.query_id", query_id) - - if params and should_send_default_pii(): - span.set_data("db.params", params) + span = None + if sentry_sdk.traces.get_current_span() is not None: + span = sentry_sdk.traces.start_span( + name=query, # type: ignore + attributes={ + "sentry.op": OP.DB, + "sentry.origin": ClickhouseDriverIntegration.origin, + SPANDATA.DB_QUERY_TEXT: str(query), + }, + ) connection._sentry_span = span # type: ignore[attr-defined] diff --git a/sentry_sdk/integrations/cohere.py b/sentry_sdk/integrations/cohere.py index 7abf3f6808..b7e77f4c0d 100644 --- a/sentry_sdk/integrations/cohere.py +++ b/sentry_sdk/integrations/cohere.py @@ -4,10 +4,9 @@ from sentry_sdk import consts from sentry_sdk.ai.monitoring import record_token_usage -from sentry_sdk.ai.utils import get_start_span_function, set_data_normalized +from sentry_sdk.ai.utils import set_data_normalized from sentry_sdk.consts import SPANDATA from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing_utils import has_span_streaming_enabled if TYPE_CHECKING: from typing import Any, Callable, Iterator, Union @@ -140,9 +139,6 @@ def collect_chat_response_fields( @wraps(f) def new_chat(*args: "Any", **kwargs: "Any") -> "Any": integration = sentry_sdk.get_client().get_integration(CohereIntegration) - is_span_streaming_enabled = has_span_streaming_enabled( - sentry_sdk.get_client().options - ) if ( integration is None @@ -153,21 +149,13 @@ def new_chat(*args: "Any", **kwargs: "Any") -> "Any": message = kwargs.get("message") - if is_span_streaming_enabled: - span = sentry_sdk.traces.start_span( - name="cohere.client.Chat", - attributes={ - "sentry.op": consts.OP.COHERE_CHAT_COMPLETIONS_CREATE, - "sentry.origin": CohereIntegration.origin, - }, - ) - else: - span = get_start_span_function()( - op=consts.OP.COHERE_CHAT_COMPLETIONS_CREATE, - name="cohere.client.Chat", - origin=CohereIntegration.origin, - ) - span.__enter__() + span = sentry_sdk.traces.start_span( + name="cohere.client.Chat", + attributes={ + "sentry.op": consts.OP.COHERE_CHAT_COMPLETIONS_CREATE, + "sentry.origin": CohereIntegration.origin, + }, + ) try: res = f(*args, **kwargs) except Exception as e: @@ -245,26 +233,13 @@ def new_embed(*args: "Any", **kwargs: "Any") -> "Any": if integration is None: return f(*args, **kwargs) - is_span_streaming_enabled = has_span_streaming_enabled( - sentry_sdk.get_client().options - ) - - if is_span_streaming_enabled: - span_ctx = sentry_sdk.traces.start_span( - name="Cohere Embedding Creation", - attributes={ - "sentry.op": consts.OP.COHERE_EMBEDDINGS_CREATE, - "sentry.origin": CohereIntegration.origin, - }, - ) - else: - span_ctx = get_start_span_function()( - op=consts.OP.COHERE_EMBEDDINGS_CREATE, - name="Cohere Embedding Creation", - origin=CohereIntegration.origin, - ) - - with span_ctx as span: + with sentry_sdk.traces.start_span( + name="Cohere Embedding Creation", + attributes={ + "sentry.op": consts.OP.COHERE_EMBEDDINGS_CREATE, + "sentry.origin": CohereIntegration.origin, + }, + ) as span: if "texts" in kwargs and ( should_send_default_pii() and integration.include_prompts ): diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py index 0f8dfcd24a..4286c9af68 100644 --- a/sentry_sdk/integrations/django/__init__.py +++ b/sentry_sdk/integrations/django/__init__.py @@ -19,7 +19,6 @@ from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.tracing_utils import ( add_query_source, - has_span_streaming_enabled, record_sql_queries, ) from sentry_sdk.utils import ( @@ -501,13 +500,11 @@ def _after_get_response(request: "WSGIRequest") -> None: scope = sentry_sdk.get_current_scope() _attempt_resolve_again(request, scope, integration.transaction_style) - span_streaming = has_span_streaming_enabled(client.options) - if span_streaming: - if has_data_collection_enabled(client.options): - if client.options["data_collection"]["user_info"]: - _get_user_from_request_and_set_on_scope(request) - elif should_send_default_pii(): + if has_data_collection_enabled(client.options): + if client.options["data_collection"]["user_info"]: _get_user_from_request_and_set_on_scope(request) + elif should_send_default_pii(): + _get_user_from_request_and_set_on_scope(request) def _patch_get_response() -> None: @@ -736,27 +733,17 @@ def connect(self: "BaseDatabaseWrapper") -> None: with capture_internal_exceptions(): sentry_sdk.add_breadcrumb(message="connect", category="query") - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return real_connect(self) - with sentry_sdk.traces.start_span( - name="connect", - attributes={ - "sentry.op": OP.DB, - "sentry.origin": DjangoIntegration.origin_db, - }, - ) as span: - _set_db_data(span, self) - return real_connect(self) - else: - with sentry_sdk.start_span( - op=OP.DB, - name="connect", - origin=DjangoIntegration.origin_db, - ) as span: - _set_db_data(span, self) - return real_connect(self) + if sentry_sdk.traces.get_current_span() is None: + return real_connect(self) + with sentry_sdk.traces.start_span( + name="connect", + attributes={ + "sentry.op": OP.DB, + "sentry.origin": DjangoIntegration.origin_db, + }, + ) as span: + _set_db_data(span, self) + return real_connect(self) def _commit(self: "BaseDatabaseWrapper") -> None: integration = sentry_sdk.get_client().get_integration(DjangoIntegration) @@ -764,27 +751,17 @@ def _commit(self: "BaseDatabaseWrapper") -> None: if integration is None or not integration.db_transaction_spans: return real_commit(self) - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return real_commit(self) - with sentry_sdk.traces.start_span( - name=SPANNAME.DB_COMMIT, - attributes={ - "sentry.op": OP.DB, - "sentry.origin": DjangoIntegration.origin_db, - }, - ) as span: - _set_db_data(span, self, SPANNAME.DB_COMMIT) - return real_commit(self) - else: - with sentry_sdk.start_span( - op=OP.DB, - name=SPANNAME.DB_COMMIT, - origin=DjangoIntegration.origin_db, - ) as span: - _set_db_data(span, self, SPANNAME.DB_COMMIT) - return real_commit(self) + if sentry_sdk.traces.get_current_span() is None: + return real_commit(self) + with sentry_sdk.traces.start_span( + name=SPANNAME.DB_COMMIT, + attributes={ + "sentry.op": OP.DB, + "sentry.origin": DjangoIntegration.origin_db, + }, + ) as span: + _set_db_data(span, self, SPANNAME.DB_COMMIT) + return real_commit(self) def _rollback(self: "BaseDatabaseWrapper") -> None: integration = sentry_sdk.get_client().get_integration(DjangoIntegration) @@ -792,27 +769,17 @@ def _rollback(self: "BaseDatabaseWrapper") -> None: if integration is None or not integration.db_transaction_spans: return real_rollback(self) - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return real_rollback(self) - with sentry_sdk.traces.start_span( - name=SPANNAME.DB_ROLLBACK, - attributes={ - "sentry.op": OP.DB, - "sentry.origin": DjangoIntegration.origin_db, - }, - ) as span: - _set_db_data(span, self, SPANNAME.DB_ROLLBACK) - return real_rollback(self) - else: - with sentry_sdk.start_span( - op=OP.DB, - name=SPANNAME.DB_ROLLBACK, - origin=DjangoIntegration.origin_db, - ) as span: - _set_db_data(span, self, SPANNAME.DB_ROLLBACK) - return real_rollback(self) + if sentry_sdk.traces.get_current_span() is None: + return real_rollback(self) + with sentry_sdk.traces.start_span( + name=SPANNAME.DB_ROLLBACK, + attributes={ + "sentry.op": OP.DB, + "sentry.origin": DjangoIntegration.origin_db, + }, + ) as span: + _set_db_data(span, self, SPANNAME.DB_ROLLBACK) + return real_rollback(self) CursorWrapper.execute = execute CursorWrapper.executemany = executemany diff --git a/sentry_sdk/integrations/django/asgi.py b/sentry_sdk/integrations/django/asgi.py index f3b1fd0898..db1744aa7e 100644 --- a/sentry_sdk/integrations/django/asgi.py +++ b/sentry_sdk/integrations/django/asgi.py @@ -18,7 +18,6 @@ from sentry_sdk.integrations.asgi import SentryAsgiMiddleware from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -177,39 +176,27 @@ async def sentry_wrapped_callback( request: "Any", *args: "Any", **kwargs: "Any" ) -> "Any": client = sentry_sdk.get_client() - span_streaming = has_span_streaming_enabled(client.options) current_scope = sentry_sdk.get_current_scope() - if span_streaming: - current_span = current_scope.streamed_span - if type(current_span) is StreamedSpan: - segment = current_span._segment - segment._update_active_thread() - else: - if current_scope.transaction is not None: - current_scope.transaction.update_active_thread() + + current_span = current_scope.streamed_span + if type(current_span) is StreamedSpan: + segment = current_span._segment + segment._update_active_thread() integration = client.get_integration(DjangoIntegration) if not integration or not integration.middleware_spans: return await callback(request, *args, **kwargs) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return await callback(request, *args, **kwargs) - with sentry_sdk.traces.start_span( - name=request.resolver_match.view_name, - attributes={ - "sentry.op": OP.VIEW_RENDER, - "sentry.origin": DjangoIntegration.origin, - }, - ): - return await callback(request, *args, **kwargs) - else: - with sentry_sdk.start_span( - op=OP.VIEW_RENDER, - name=request.resolver_match.view_name, - origin=DjangoIntegration.origin, - ): - return await callback(request, *args, **kwargs) + if sentry_sdk.traces.get_current_span() is None: + return await callback(request, *args, **kwargs) + with sentry_sdk.traces.start_span( + name=request.resolver_match.view_name, + attributes={ + "sentry.op": OP.VIEW_RENDER, + "sentry.origin": DjangoIntegration.origin, + }, + ): + return await callback(request, *args, **kwargs) return sentry_wrapped_callback diff --git a/sentry_sdk/integrations/django/caching.py b/sentry_sdk/integrations/django/caching.py index 2cfc0cd2e1..b969f4366e 100644 --- a/sentry_sdk/integrations/django/caching.py +++ b/sentry_sdk/integrations/django/caching.py @@ -8,7 +8,6 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations.redis.utils import _get_safe_key, _key_as_string -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -59,113 +58,60 @@ def _instrument_call( op = OP.CACHE_PUT if is_set_operation else OP.CACHE_GET description = _get_span_description(method_name, args, kwargs) - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return original_method(*args, **kwargs) - with sentry_sdk.traces.start_span( - name=description, - attributes={ - "sentry.op": op, - "sentry.origin": DjangoIntegration.origin, - }, - ) as span: - value = original_method(*args, **kwargs) - - with capture_internal_exceptions(): - if address is not None: - span.set_attribute(SPANDATA.NETWORK_PEER_ADDRESS, address) - - if port is not None: - span.set_attribute(SPANDATA.NETWORK_PEER_PORT, port) - - key = _get_safe_key(method_name, args, kwargs) - if key is not None: - span.set_attribute(SPANDATA.CACHE_KEY, key) - - item_size = None - if is_get_many_method: - if value != {}: - item_size = len(str(value)) - span.set_attribute(SPANDATA.CACHE_HIT, True) - else: - span.set_attribute(SPANDATA.CACHE_HIT, False) - elif is_get_method: - default_value = None - if len(args) >= 2: - default_value = args[1] - elif "default" in kwargs: - default_value = kwargs["default"] - - if value != default_value: - item_size = len(str(value)) - span.set_attribute(SPANDATA.CACHE_HIT, True) - else: - span.set_attribute(SPANDATA.CACHE_HIT, False) - else: # TODO: We don't handle `get_or_set` which we should - arg_count = len(args) - if arg_count >= 2: - # 'set' command - item_size = len(str(args[1])) - elif arg_count == 1: - # 'set_many' command - item_size = len(str(args[0])) - - if item_size is not None: - span.set_attribute(SPANDATA.CACHE_ITEM_SIZE, item_size) - - return value - else: - with sentry_sdk.start_span( - op=op, - name=description, - origin=DjangoIntegration.origin, - ) as span: - value = original_method(*args, **kwargs) - - with capture_internal_exceptions(): - if address is not None: - span.set_data(SPANDATA.NETWORK_PEER_ADDRESS, address) - - if port is not None: - span.set_data(SPANDATA.NETWORK_PEER_PORT, port) - - key = _get_safe_key(method_name, args, kwargs) - if key is not None: - span.set_data(SPANDATA.CACHE_KEY, key) - - item_size = None - if is_get_many_method: - if value != {}: - item_size = len(str(value)) - span.set_data(SPANDATA.CACHE_HIT, True) - else: - span.set_data(SPANDATA.CACHE_HIT, False) - elif is_get_method: - default_value = None - if len(args) >= 2: - default_value = args[1] - elif "default" in kwargs: - default_value = kwargs["default"] - - if value != default_value: - item_size = len(str(value)) - span.set_data(SPANDATA.CACHE_HIT, True) - else: - span.set_data(SPANDATA.CACHE_HIT, False) - else: # TODO: We don't handle `get_or_set` which we should - arg_count = len(args) - if arg_count >= 2: - # 'set' command - item_size = len(str(args[1])) - elif arg_count == 1: - # 'set_many' command - item_size = len(str(args[0])) - - if item_size is not None: - span.set_data(SPANDATA.CACHE_ITEM_SIZE, item_size) - - return value + if sentry_sdk.traces.get_current_span() is None: + return original_method(*args, **kwargs) + with sentry_sdk.traces.start_span( + name=description, + attributes={ + "sentry.op": op, + "sentry.origin": DjangoIntegration.origin, + }, + ) as span: + value = original_method(*args, **kwargs) + + with capture_internal_exceptions(): + if address is not None: + span.set_attribute(SPANDATA.NETWORK_PEER_ADDRESS, address) + + if port is not None: + span.set_attribute(SPANDATA.NETWORK_PEER_PORT, port) + + key = _get_safe_key(method_name, args, kwargs) + if key is not None: + span.set_attribute(SPANDATA.CACHE_KEY, key) + + item_size = None + if is_get_many_method: + if value != {}: + item_size = len(str(value)) + span.set_attribute(SPANDATA.CACHE_HIT, True) + else: + span.set_attribute(SPANDATA.CACHE_HIT, False) + elif is_get_method: + default_value = None + if len(args) >= 2: + default_value = args[1] + elif "default" in kwargs: + default_value = kwargs["default"] + + if value != default_value: + item_size = len(str(value)) + span.set_attribute(SPANDATA.CACHE_HIT, True) + else: + span.set_attribute(SPANDATA.CACHE_HIT, False) + else: # TODO: We don't handle `get_or_set` which we should + arg_count = len(args) + if arg_count >= 2: + # 'set' command + item_size = len(str(args[1])) + elif arg_count == 1: + # 'set_many' command + item_size = len(str(args[0])) + + if item_size is not None: + span.set_attribute(SPANDATA.CACHE_ITEM_SIZE, item_size) + + return value @functools.wraps(original_method) def sentry_method(*args: "Any", **kwargs: "Any") -> "Any": diff --git a/sentry_sdk/integrations/django/middleware.py b/sentry_sdk/integrations/django/middleware.py index 01ed8962e0..d7020e1e8d 100644 --- a/sentry_sdk/integrations/django/middleware.py +++ b/sentry_sdk/integrations/django/middleware.py @@ -9,11 +9,9 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( ContextVar, capture_internal_exceptions, - transaction_from_function, ) if TYPE_CHECKING: @@ -74,34 +72,22 @@ def _check_middleware_span( if integration is None or not integration.middleware_spans: return None - function_name = transaction_from_function(old_method) - description = middleware_name function_basename = getattr(old_method, "__name__", None) if function_basename: description = "{}.{}".format(description, function_basename) - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - middleware_span: "Union[Span, StreamedSpan]" - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return None - middleware_span = sentry_sdk.traces.start_span( - name=description, - attributes={ - "sentry.op": OP.MIDDLEWARE_DJANGO, - "sentry.origin": DjangoIntegration.origin, - SPANDATA.MIDDLEWARE_NAME: middleware_name, - }, - ) - else: - middleware_span = sentry_sdk.start_span( - op=OP.MIDDLEWARE_DJANGO, - name=description, - origin=DjangoIntegration.origin, - ) - middleware_span.set_tag("django.function_name", function_name) - middleware_span.set_tag("django.middleware_name", middleware_name) + if sentry_sdk.traces.get_current_span() is None: + return None + + middleware_span = sentry_sdk.traces.start_span( + name=description, + attributes={ + "sentry.op": OP.MIDDLEWARE_DJANGO, + "sentry.origin": DjangoIntegration.origin, + SPANDATA.MIDDLEWARE_NAME: middleware_name, + }, + ) return middleware_span diff --git a/sentry_sdk/integrations/django/signals_handlers.py b/sentry_sdk/integrations/django/signals_handlers.py index 711e74b441..73fcad046b 100644 --- a/sentry_sdk/integrations/django/signals_handlers.py +++ b/sentry_sdk/integrations/django/signals_handlers.py @@ -6,7 +6,6 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations.django import DJANGO_VERSION -from sentry_sdk.tracing_utils import has_span_streaming_enabled if TYPE_CHECKING: from collections.abc import Callable @@ -64,29 +63,17 @@ def sentry_sync_receiver_wrapper( def wrapper(*args: "Any", **kwargs: "Any") -> "Any": signal_name = _get_receiver_name(receiver) - span_streaming = has_span_streaming_enabled( - sentry_sdk.get_client().options - ) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return receiver(*args, **kwargs) - with sentry_sdk.traces.start_span( - name=signal_name, - attributes={ - "sentry.op": OP.EVENT_DJANGO, - "sentry.origin": DjangoIntegration.origin, - SPANDATA.CODE_FUNCTION_NAME: signal_name, - }, - ): - return receiver(*args, **kwargs) - else: - with sentry_sdk.start_span( - op=OP.EVENT_DJANGO, - name=signal_name, - origin=DjangoIntegration.origin, - ) as span: - span.set_data("signal", signal_name) - return receiver(*args, **kwargs) + if sentry_sdk.traces.get_current_span() is None: + return receiver(*args, **kwargs) + with sentry_sdk.traces.start_span( + name=signal_name, + attributes={ + "sentry.op": OP.EVENT_DJANGO, + "sentry.origin": DjangoIntegration.origin, + SPANDATA.CODE_FUNCTION_NAME: signal_name, + }, + ): + return receiver(*args, **kwargs) return wrapper diff --git a/sentry_sdk/integrations/django/tasks.py b/sentry_sdk/integrations/django/tasks.py index 303040d042..f3ea649c74 100644 --- a/sentry_sdk/integrations/django/tasks.py +++ b/sentry_sdk/integrations/django/tasks.py @@ -2,7 +2,6 @@ import sentry_sdk from sentry_sdk.consts import OP -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import qualname_from_function try: @@ -33,22 +32,15 @@ def _sentry_enqueue(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": name = qualname_from_function(self.func) or "" - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return old_task_enqueue(self, *args, **kwargs) - with sentry_sdk.traces.start_span( - name=name, - attributes={ - "sentry.op": OP.QUEUE_SUBMIT_DJANGO, - "sentry.origin": DjangoIntegration.origin, - }, - ): - return old_task_enqueue(self, *args, **kwargs) - else: - with sentry_sdk.start_span( - op=OP.QUEUE_SUBMIT_DJANGO, name=name, origin=DjangoIntegration.origin - ): - return old_task_enqueue(self, *args, **kwargs) + if sentry_sdk.traces.get_current_span() is None: + return old_task_enqueue(self, *args, **kwargs) + with sentry_sdk.traces.start_span( + name=name, + attributes={ + "sentry.op": OP.QUEUE_SUBMIT_DJANGO, + "sentry.origin": DjangoIntegration.origin, + }, + ): + return old_task_enqueue(self, *args, **kwargs) Task.enqueue = _sentry_enqueue diff --git a/sentry_sdk/integrations/django/templates.py b/sentry_sdk/integrations/django/templates.py index 1c0986dd9e..c8c284d706 100644 --- a/sentry_sdk/integrations/django/templates.py +++ b/sentry_sdk/integrations/django/templates.py @@ -7,7 +7,6 @@ import sentry_sdk from sentry_sdk.consts import OP -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ensure_integration_enabled if TYPE_CHECKING: @@ -62,26 +61,16 @@ def patch_templates() -> None: @property # type: ignore @ensure_integration_enabled(DjangoIntegration, real_rendered_content.fget) def rendered_content(self: "SimpleTemplateResponse") -> str: - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return real_rendered_content.fget(self) - with sentry_sdk.traces.start_span( - name=_get_template_name_description(self.template_name), - attributes={ - "sentry.op": OP.TEMPLATE_RENDER, - "sentry.origin": DjangoIntegration.origin, - }, - ): - return real_rendered_content.fget(self) - else: - with sentry_sdk.start_span( - op=OP.TEMPLATE_RENDER, - name=_get_template_name_description(self.template_name), - origin=DjangoIntegration.origin, - ) as span: - span.set_data("context", self.context_data) - return real_rendered_content.fget(self) + if sentry_sdk.traces.get_current_span() is None: + return real_rendered_content.fget(self) + with sentry_sdk.traces.start_span( + name=_get_template_name_description(self.template_name), + attributes={ + "sentry.op": OP.TEMPLATE_RENDER, + "sentry.origin": DjangoIntegration.origin, + }, + ): + return real_rendered_content.fget(self) SimpleTemplateResponse.rendered_content = rendered_content @@ -107,28 +96,16 @@ def render( sentry_sdk.get_current_scope().trace_propagation_meta() ) - client = sentry_sdk.get_client() - span_streaming = has_span_streaming_enabled(client.options) - - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return real_render(request, template_name, context, *args, **kwargs) - with sentry_sdk.traces.start_span( - name=_get_template_name_description(template_name), - attributes={ - "sentry.op": OP.TEMPLATE_RENDER, - "sentry.origin": DjangoIntegration.origin, - }, - ): - return real_render(request, template_name, context, *args, **kwargs) - else: - with sentry_sdk.start_span( - op=OP.TEMPLATE_RENDER, - name=_get_template_name_description(template_name), - origin=DjangoIntegration.origin, - ) as span: - span.set_data("context", context) - return real_render(request, template_name, context, *args, **kwargs) + if sentry_sdk.traces.get_current_span() is None: + return real_render(request, template_name, context, *args, **kwargs) + with sentry_sdk.traces.start_span( + name=_get_template_name_description(template_name), + attributes={ + "sentry.op": OP.TEMPLATE_RENDER, + "sentry.origin": DjangoIntegration.origin, + }, + ): + return real_render(request, template_name, context, *args, **kwargs) django.shortcuts.render = render diff --git a/sentry_sdk/integrations/django/views.py b/sentry_sdk/integrations/django/views.py index eacd3b74fe..1819065289 100644 --- a/sentry_sdk/integrations/django/views.py +++ b/sentry_sdk/integrations/django/views.py @@ -4,7 +4,6 @@ import sentry_sdk from sentry_sdk.consts import OP from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing_utils import has_span_streaming_enabled if TYPE_CHECKING: from typing import Any @@ -32,25 +31,16 @@ def patch_views() -> None: old_render = SimpleTemplateResponse.render def sentry_patched_render(self: "SimpleTemplateResponse") -> "Any": - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return old_render(self) - with sentry_sdk.traces.start_span( - name="serialize response", - attributes={ - "sentry.op": OP.VIEW_RESPONSE_RENDER, - "sentry.origin": DjangoIntegration.origin, - }, - ): - return old_render(self) - else: - with sentry_sdk.start_span( - op=OP.VIEW_RESPONSE_RENDER, - name="serialize response", - origin=DjangoIntegration.origin, - ): - return old_render(self) + if sentry_sdk.traces.get_current_span() is None: + return old_render(self) + with sentry_sdk.traces.start_span( + name="serialize response", + attributes={ + "sentry.op": OP.VIEW_RESPONSE_RENDER, + "sentry.origin": DjangoIntegration.origin, + }, + ): + return old_render(self) @functools.wraps(old_make_view_atomic) def sentry_patched_make_view_atomic( @@ -88,38 +78,25 @@ def _wrap_sync_view(callback: "Any") -> "Any": @functools.wraps(callback) def sentry_wrapped_callback(request: "Any", *args: "Any", **kwargs: "Any") -> "Any": client = sentry_sdk.get_client() - span_streaming = has_span_streaming_enabled(client.options) current_scope = sentry_sdk.get_current_scope() - if span_streaming: - current_span = current_scope.streamed_span - if type(current_span) is StreamedSpan: - segment = current_span._segment - segment._update_active_thread() - else: - if current_scope.transaction is not None: - current_scope.transaction.update_active_thread() + current_span = current_scope.streamed_span + if type(current_span) is StreamedSpan: + segment = current_span._segment + segment._update_active_thread() integration = client.get_integration(DjangoIntegration) if not integration or not integration.middleware_spans: return callback(request, *args, **kwargs) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return callback(request, *args, **kwargs) - with sentry_sdk.traces.start_span( - name=request.resolver_match.view_name, - attributes={ - "sentry.op": OP.VIEW_RENDER, - "sentry.origin": DjangoIntegration.origin, - }, - ): - return callback(request, *args, **kwargs) - else: - with sentry_sdk.start_span( - op=OP.VIEW_RENDER, - name=request.resolver_match.view_name, - origin=DjangoIntegration.origin, - ): - return callback(request, *args, **kwargs) + if sentry_sdk.traces.get_current_span() is None: + return callback(request, *args, **kwargs) + with sentry_sdk.traces.start_span( + name=request.resolver_match.view_name, + attributes={ + "sentry.op": OP.VIEW_RENDER, + "sentry.origin": DjangoIntegration.origin, + }, + ): + return callback(request, *args, **kwargs) return sentry_wrapped_callback diff --git a/sentry_sdk/integrations/dramatiq.py b/sentry_sdk/integrations/dramatiq.py index 2840c24fe5..8c6bef5a7c 100644 --- a/sentry_sdk/integrations/dramatiq.py +++ b/sentry_sdk/integrations/dramatiq.py @@ -2,17 +2,15 @@ from typing import TypeVar import sentry_sdk -from sentry_sdk.api import continue_trace, get_baggage, get_traceparent -from sentry_sdk.consts import OP, SPANDATA, SPANSTATUS +from sentry_sdk.api import get_baggage, get_traceparent +from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.integrations._wsgi_common import request_body_within_bounds from sentry_sdk.traces import SegmentNameSource from sentry_sdk.tracing import ( BAGGAGE_HEADER_NAME, SENTRY_TRACE_HEADER_NAME, - TransactionSource, ) -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( AnnotatedValue, capture_internal_exceptions, @@ -132,39 +130,18 @@ def before_process_message(self, broker: "Broker", message: "Message[R]") -> Non # start new trace in case of retrying sentry_headers = {} - if has_span_streaming_enabled(client.options): - sentry_sdk.traces.continue_trace(sentry_headers) - span = sentry_sdk.traces.start_span( - name=message.actor_name, - attributes={ - "sentry.op": OP.QUEUE_TASK_DRAMATIQ, - "sentry.origin": DramatiqIntegration.origin, - "sentry.segment.name.source": SegmentNameSource.TASK.value, - SPANDATA.MESSAGING_DESTINATION_NAME: message.queue_name, - }, - parent_span=None, - ) - message._sentry_span_ctx = span - else: - transaction = continue_trace( - sentry_headers, - name=message.actor_name, - op=OP.QUEUE_TASK_DRAMATIQ, - source=TransactionSource.TASK, - origin=DramatiqIntegration.origin, - ) - transaction.set_status(SPANSTATUS.OK) - sentry_sdk.start_transaction( - transaction, - name=message.actor_name, - op=OP.QUEUE_TASK_DRAMATIQ, - source=TransactionSource.TASK, - ) - transaction.__enter__() - transaction.set_data( - SPANDATA.MESSAGING_DESTINATION_NAME, message.queue_name - ) - message._sentry_span_ctx = transaction + sentry_sdk.traces.continue_trace(sentry_headers) + span = sentry_sdk.traces.start_span( + name=message.actor_name, + attributes={ + "sentry.op": OP.QUEUE_TASK_DRAMATIQ, + "sentry.origin": DramatiqIntegration.origin, + "sentry.segment.name.source": SegmentNameSource.TASK.value, + SPANDATA.MESSAGING_DESTINATION_NAME: message.queue_name, + }, + parent_span=None, + ) + message._sentry_span_ctx = span def after_process_message( self, diff --git a/sentry_sdk/integrations/falcon.py b/sentry_sdk/integrations/falcon.py index 7a595bcf2a..bbfc0e83aa 100644 --- a/sentry_sdk/integrations/falcon.py +++ b/sentry_sdk/integrations/falcon.py @@ -5,7 +5,6 @@ from sentry_sdk.integrations._wsgi_common import RequestExtractor from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware from sentry_sdk.tracing import SOURCE_FOR_STYLE -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -113,7 +112,7 @@ def process_resource( """ client = sentry_sdk.get_client() integration = client.get_integration(FalconIntegration) - if integration is None or not has_span_streaming_enabled(client.options): + if integration is None: return name_for_style = { diff --git a/sentry_sdk/integrations/fastapi.py b/sentry_sdk/integrations/fastapi.py index 14ee66eecf..593826020b 100644 --- a/sentry_sdk/integrations/fastapi.py +++ b/sentry_sdk/integrations/fastapi.py @@ -8,7 +8,6 @@ from sentry_sdk.integrations import DidNotEnable from sentry_sdk.traces import StreamedSpan, get_current_span from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import transaction_from_function if TYPE_CHECKING: @@ -170,16 +169,11 @@ def _sentry_get_request_handler(*args: "Any", **kwargs: "Any") -> "Any": def _sentry_call(*args: "Any", **kwargs: "Any") -> "Any": current_scope = sentry_sdk.get_current_scope() - client = sentry_sdk.get_client() - if has_span_streaming_enabled(client.options): - current_span = current_scope.streamed_span + current_span = current_scope.streamed_span - if type(current_span) is StreamedSpan: - segment = current_span._segment - segment._update_active_thread() - - elif current_scope.transaction is not None: - current_scope.transaction.update_active_thread() + if type(current_span) is StreamedSpan: + segment = current_span._segment + segment._update_active_thread() return old_call(*args, **kwargs) diff --git a/sentry_sdk/integrations/gcp.py b/sentry_sdk/integrations/gcp.py index cfd3344ab8..f3a241ac08 100644 --- a/sentry_sdk/integrations/gcp.py +++ b/sentry_sdk/integrations/gcp.py @@ -6,7 +6,6 @@ from typing import TYPE_CHECKING import sentry_sdk -from sentry_sdk.api import continue_trace from sentry_sdk.consts import OP from sentry_sdk.data_collection import _apply_data_collection_filtering_to_query_string from sentry_sdk.integrations import Integration @@ -14,8 +13,6 @@ from sentry_sdk.integrations.cloud_resource_context import CLOUD_PROVIDER from sentry_sdk.scope import Scope, should_send_default_pii from sentry_sdk.traces import SegmentNameSource -from sentry_sdk.tracing import TransactionSource -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( AnnotatedValue, TimeoutThread, @@ -141,36 +138,22 @@ def sentry_func( if environ.get("ENTRY_POINT"): additional_attributes["faas.entry_point"] = environ.get("ENTRY_POINT") - if has_span_streaming_enabled(client.options): - sentry_sdk.traces.continue_trace(headers) - Scope.set_custom_sampling_context(sampling_context) - span_ctx = sentry_sdk.traces.start_span( - name=function_name, - parent_span=None, - attributes={ - "sentry.op": OP.FUNCTION_GCP, - "sentry.origin": GcpIntegration.origin, - "sentry.segment.name.source": SegmentNameSource.COMPONENT, - "cloud.provider": CLOUD_PROVIDER.GCP, - "faas.name": function_name, - **header_attributes, - **additional_attributes, - }, - ) - else: - transaction = continue_trace( - headers, - op=OP.FUNCTION_GCP, - name=environ.get("FUNCTION_NAME", ""), - source=TransactionSource.COMPONENT, - origin=GcpIntegration.origin, - ) - - span_ctx = sentry_sdk.start_transaction( - transaction, custom_sampling_context=sampling_context - ) - - with span_ctx: + sentry_sdk.traces.continue_trace(headers) + Scope.set_custom_sampling_context(sampling_context) + + with sentry_sdk.traces.start_span( + name=function_name, + parent_span=None, + attributes={ + "sentry.op": OP.FUNCTION_GCP, + "sentry.origin": GcpIntegration.origin, + "sentry.segment.name.source": SegmentNameSource.COMPONENT, + "cloud.provider": CLOUD_PROVIDER.GCP, + "faas.name": function_name, + **header_attributes, + **additional_attributes, + }, + ): try: return func(functionhandler, gcp_event, *args, **kwargs) except Exception: diff --git a/sentry_sdk/integrations/google_genai/__init__.py b/sentry_sdk/integrations/google_genai/__init__.py index 45652c3f71..a021cdabfd 100644 --- a/sentry_sdk/integrations/google_genai/__init__.py +++ b/sentry_sdk/integrations/google_genai/__init__.py @@ -8,12 +8,10 @@ ) import sentry_sdk -from sentry_sdk.ai.utils import get_start_span_function from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.traces import SpanStatus, StreamedSpan from sentry_sdk.tracing import SPANSTATUS -from sentry_sdk.tracing_utils import has_span_streaming_enabled try: from google.genai.models import AsyncModels, Models @@ -75,30 +73,17 @@ def new_generate_content_stream( _model, contents, model_name = prepare_generate_content_args(args, kwargs) - if has_span_streaming_enabled(client.options): - chat_span = sentry_sdk.traces.start_span( - name=f"chat {model_name}", - attributes={ - "sentry.op": OP.GEN_AI_CHAT, - "sentry.origin": ORIGIN, - SPANDATA.GEN_AI_OPERATION_NAME: "chat", - SPANDATA.GEN_AI_SYSTEM: GEN_AI_SYSTEM, - SPANDATA.GEN_AI_REQUEST_MODEL: model_name, - SPANDATA.GEN_AI_RESPONSE_STREAMING: True, - }, - ) - else: - chat_span = get_start_span_function()( - op=OP.GEN_AI_CHAT, - name=f"chat {model_name}", - origin=ORIGIN, - ) - chat_span.__enter__() - - chat_span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "chat") - chat_span.set_data(SPANDATA.GEN_AI_SYSTEM, GEN_AI_SYSTEM) - chat_span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model_name) - chat_span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True) + chat_span = sentry_sdk.traces.start_span( + name=f"chat {model_name}", + attributes={ + "sentry.op": OP.GEN_AI_CHAT, + "sentry.origin": ORIGIN, + SPANDATA.GEN_AI_OPERATION_NAME: "chat", + SPANDATA.GEN_AI_SYSTEM: GEN_AI_SYSTEM, + SPANDATA.GEN_AI_REQUEST_MODEL: model_name, + SPANDATA.GEN_AI_RESPONSE_STREAMING: True, + }, + ) set_span_data_for_request(chat_span, integration, model_name, contents, kwargs) @@ -152,30 +137,17 @@ async def new_async_generate_content_stream( _model, contents, model_name = prepare_generate_content_args(args, kwargs) - if has_span_streaming_enabled(client.options): - chat_span = sentry_sdk.traces.start_span( - name=f"chat {model_name}", - attributes={ - "sentry.op": OP.GEN_AI_CHAT, - "sentry.origin": ORIGIN, - SPANDATA.GEN_AI_OPERATION_NAME: "chat", - SPANDATA.GEN_AI_SYSTEM: GEN_AI_SYSTEM, - SPANDATA.GEN_AI_REQUEST_MODEL: model_name, - SPANDATA.GEN_AI_RESPONSE_STREAMING: True, - }, - ) - else: - chat_span = get_start_span_function()( - op=OP.GEN_AI_CHAT, - name=f"chat {model_name}", - origin=ORIGIN, - ) - chat_span.__enter__() - - chat_span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "chat") - chat_span.set_data(SPANDATA.GEN_AI_SYSTEM, GEN_AI_SYSTEM) - chat_span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model_name) - chat_span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True) + chat_span = sentry_sdk.traces.start_span( + name=f"chat {model_name}", + attributes={ + "sentry.op": OP.GEN_AI_CHAT, + "sentry.origin": ORIGIN, + SPANDATA.GEN_AI_OPERATION_NAME: "chat", + SPANDATA.GEN_AI_SYSTEM: GEN_AI_SYSTEM, + SPANDATA.GEN_AI_REQUEST_MODEL: model_name, + SPANDATA.GEN_AI_RESPONSE_STREAMING: True, + }, + ) set_span_data_for_request(chat_span, integration, model_name, contents, kwargs) @@ -225,54 +197,30 @@ def new_generate_content(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": model, contents, model_name = prepare_generate_content_args(args, kwargs) - if has_span_streaming_enabled(client.options): - with sentry_sdk.traces.start_span( - name=f"chat {model_name}", - attributes={ - "sentry.op": OP.GEN_AI_CHAT, - "sentry.origin": ORIGIN, - SPANDATA.GEN_AI_OPERATION_NAME: "chat", - SPANDATA.GEN_AI_SYSTEM: GEN_AI_SYSTEM, - SPANDATA.GEN_AI_REQUEST_MODEL: model_name, - }, - ) as chat_span: - set_span_data_for_request( - chat_span, integration, model_name, contents, kwargs - ) + with sentry_sdk.traces.start_span( + name=f"chat {model_name}", + attributes={ + "sentry.op": OP.GEN_AI_CHAT, + "sentry.origin": ORIGIN, + SPANDATA.GEN_AI_OPERATION_NAME: "chat", + SPANDATA.GEN_AI_SYSTEM: GEN_AI_SYSTEM, + SPANDATA.GEN_AI_REQUEST_MODEL: model_name, + }, + ) as chat_span: + set_span_data_for_request( + chat_span, integration, model_name, contents, kwargs + ) - try: - response = f(self, *args, **kwargs) - except Exception as exc: - _capture_exception(exc) - chat_span.status = SpanStatus.ERROR - raise + try: + response = f(self, *args, **kwargs) + except Exception as exc: + _capture_exception(exc) + chat_span.status = SpanStatus.ERROR + raise - set_span_data_for_response(chat_span, integration, response) - - return response - else: - with get_start_span_function()( - op=OP.GEN_AI_CHAT, - name=f"chat {model_name}", - origin=ORIGIN, - ) as chat_span: - chat_span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "chat") - chat_span.set_data(SPANDATA.GEN_AI_SYSTEM, GEN_AI_SYSTEM) - chat_span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model_name) - set_span_data_for_request( - chat_span, integration, model_name, contents, kwargs - ) + set_span_data_for_response(chat_span, integration, response) - try: - response = f(self, *args, **kwargs) - except Exception as exc: - _capture_exception(exc) - chat_span.set_status(SPANSTATUS.INTERNAL_ERROR) - raise - - set_span_data_for_response(chat_span, integration, response) - - return response + return response return new_generate_content @@ -289,52 +237,29 @@ async def new_async_generate_content( model, contents, model_name = prepare_generate_content_args(args, kwargs) - if has_span_streaming_enabled(client.options): - with sentry_sdk.traces.start_span( - name=f"chat {model_name}", - attributes={ - "sentry.op": OP.GEN_AI_CHAT, - "sentry.origin": ORIGIN, - SPANDATA.GEN_AI_OPERATION_NAME: "chat", - SPANDATA.GEN_AI_SYSTEM: GEN_AI_SYSTEM, - SPANDATA.GEN_AI_REQUEST_MODEL: model_name, - }, - ) as chat_span: - set_span_data_for_request( - chat_span, integration, model_name, contents, kwargs - ) - try: - response = await f(self, *args, **kwargs) - except Exception as exc: - _capture_exception(exc) - chat_span.status = SpanStatus.ERROR - raise - - set_span_data_for_response(chat_span, integration, response) - - return response - else: - with get_start_span_function()( - op=OP.GEN_AI_CHAT, - name=f"chat {model_name}", - origin=ORIGIN, - ) as chat_span: - chat_span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "chat") - chat_span.set_data(SPANDATA.GEN_AI_SYSTEM, GEN_AI_SYSTEM) - chat_span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model_name) - set_span_data_for_request( - chat_span, integration, model_name, contents, kwargs - ) - try: - response = await f(self, *args, **kwargs) - except Exception as exc: - _capture_exception(exc) - chat_span.set_status(SPANSTATUS.INTERNAL_ERROR) - raise + with sentry_sdk.traces.start_span( + name=f"chat {model_name}", + attributes={ + "sentry.op": OP.GEN_AI_CHAT, + "sentry.origin": ORIGIN, + SPANDATA.GEN_AI_OPERATION_NAME: "chat", + SPANDATA.GEN_AI_SYSTEM: GEN_AI_SYSTEM, + SPANDATA.GEN_AI_REQUEST_MODEL: model_name, + }, + ) as chat_span: + set_span_data_for_request( + chat_span, integration, model_name, contents, kwargs + ) + try: + response = await f(self, *args, **kwargs) + except Exception as exc: + _capture_exception(exc) + chat_span.status = SpanStatus.ERROR + raise - set_span_data_for_response(chat_span, integration, response) + set_span_data_for_response(chat_span, integration, response) - return response + return response return new_async_generate_content @@ -349,50 +274,28 @@ def new_embed_content(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": model_name, contents = prepare_embed_content_args(args, kwargs) - if has_span_streaming_enabled(client.options): - with sentry_sdk.traces.start_span( - name=f"embeddings {model_name}", - attributes={ - "sentry.op": OP.GEN_AI_EMBEDDINGS, - "sentry.origin": ORIGIN, - SPANDATA.GEN_AI_OPERATION_NAME: "embeddings", - SPANDATA.GEN_AI_SYSTEM: GEN_AI_SYSTEM, - SPANDATA.GEN_AI_REQUEST_MODEL: model_name, - }, - ) as span: - set_span_data_for_embed_request(span, integration, contents, kwargs) - - try: - response = f(self, *args, **kwargs) - except Exception as exc: - _capture_exception(exc) - span.status = SpanStatus.ERROR - raise - - set_span_data_for_embed_response(span, integration, response) - - return response - else: - with get_start_span_function()( - op=OP.GEN_AI_EMBEDDINGS, - name=f"embeddings {model_name}", - origin=ORIGIN, - ) as span: - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "embeddings") - span.set_data(SPANDATA.GEN_AI_SYSTEM, GEN_AI_SYSTEM) - span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model_name) - set_span_data_for_embed_request(span, integration, contents, kwargs) - - try: - response = f(self, *args, **kwargs) - except Exception as exc: - _capture_exception(exc) - span.set_status(SPANSTATUS.INTERNAL_ERROR) - raise - - set_span_data_for_embed_response(span, integration, response) - - return response + with sentry_sdk.traces.start_span( + name=f"embeddings {model_name}", + attributes={ + "sentry.op": OP.GEN_AI_EMBEDDINGS, + "sentry.origin": ORIGIN, + SPANDATA.GEN_AI_OPERATION_NAME: "embeddings", + SPANDATA.GEN_AI_SYSTEM: GEN_AI_SYSTEM, + SPANDATA.GEN_AI_REQUEST_MODEL: model_name, + }, + ) as span: + set_span_data_for_embed_request(span, integration, contents, kwargs) + + try: + response = f(self, *args, **kwargs) + except Exception as exc: + _capture_exception(exc) + span.status = SpanStatus.ERROR + raise + + set_span_data_for_embed_response(span, integration, response) + + return response return new_embed_content @@ -409,49 +312,27 @@ async def new_async_embed_content( model_name, contents = prepare_embed_content_args(args, kwargs) - if has_span_streaming_enabled(client.options): - with sentry_sdk.traces.start_span( - name=f"embeddings {model_name}", - attributes={ - "sentry.op": OP.GEN_AI_EMBEDDINGS, - "sentry.origin": ORIGIN, - SPANDATA.GEN_AI_OPERATION_NAME: "embeddings", - SPANDATA.GEN_AI_SYSTEM: GEN_AI_SYSTEM, - SPANDATA.GEN_AI_REQUEST_MODEL: model_name, - }, - ) as span: - set_span_data_for_embed_request(span, integration, contents, kwargs) - - try: - response = await f(self, *args, **kwargs) - except Exception as exc: - _capture_exception(exc) - span.status = SpanStatus.ERROR - raise - - set_span_data_for_embed_response(span, integration, response) - - return response - else: - with get_start_span_function()( - op=OP.GEN_AI_EMBEDDINGS, - name=f"embeddings {model_name}", - origin=ORIGIN, - ) as span: - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "embeddings") - span.set_data(SPANDATA.GEN_AI_SYSTEM, GEN_AI_SYSTEM) - span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model_name) - set_span_data_for_embed_request(span, integration, contents, kwargs) - - try: - response = await f(self, *args, **kwargs) - except Exception as exc: - _capture_exception(exc) - span.set_status(SPANSTATUS.INTERNAL_ERROR) - raise - - set_span_data_for_embed_response(span, integration, response) - - return response + with sentry_sdk.traces.start_span( + name=f"embeddings {model_name}", + attributes={ + "sentry.op": OP.GEN_AI_EMBEDDINGS, + "sentry.origin": ORIGIN, + SPANDATA.GEN_AI_OPERATION_NAME: "embeddings", + SPANDATA.GEN_AI_SYSTEM: GEN_AI_SYSTEM, + SPANDATA.GEN_AI_REQUEST_MODEL: model_name, + }, + ) as span: + set_span_data_for_embed_request(span, integration, contents, kwargs) + + try: + response = await f(self, *args, **kwargs) + except Exception as exc: + _capture_exception(exc) + span.status = SpanStatus.ERROR + raise + + set_span_data_for_embed_response(span, integration, response) + + return response return new_async_embed_content diff --git a/sentry_sdk/integrations/google_genai/utils.py b/sentry_sdk/integrations/google_genai/utils.py index 464a812680..980b47263a 100644 --- a/sentry_sdk/integrations/google_genai/utils.py +++ b/sentry_sdk/integrations/google_genai/utils.py @@ -30,7 +30,6 @@ from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import StreamedSpan from sentry_sdk.tracing_utils import ( - has_span_streaming_enabled, should_truncate_gen_ai_input, ) from sentry_sdk.utils import ( @@ -673,28 +672,16 @@ def _create_tool_span( tool_name: str, tool_doc: "Optional[str]" ) -> "Union[Span, StreamedSpan]": """Create a span for tool execution.""" - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - span = sentry_sdk.traces.start_span( - name=f"execute_tool {tool_name}", - attributes={ - "sentry.op": OP.GEN_AI_EXECUTE_TOOL, - "sentry.origin": ORIGIN, - SPANDATA.GEN_AI_TOOL_NAME: tool_name, - }, - ) - if tool_doc: - span.set_attribute(SPANDATA.GEN_AI_TOOL_DESCRIPTION, tool_doc) - return span - - span = sentry_sdk.start_span( - op=OP.GEN_AI_EXECUTE_TOOL, + span = sentry_sdk.traces.start_span( name=f"execute_tool {tool_name}", - origin=ORIGIN, + attributes={ + "sentry.op": OP.GEN_AI_EXECUTE_TOOL, + "sentry.origin": ORIGIN, + SPANDATA.GEN_AI_TOOL_NAME: tool_name, + }, ) - span.set_data(SPANDATA.GEN_AI_TOOL_NAME, tool_name) if tool_doc: - span.set_data(SPANDATA.GEN_AI_TOOL_DESCRIPTION, tool_doc) + span.set_attribute(SPANDATA.GEN_AI_TOOL_DESCRIPTION, tool_doc) return span diff --git a/sentry_sdk/integrations/graphene.py b/sentry_sdk/integrations/graphene.py index 7f567a5407..bce59be054 100644 --- a/sentry_sdk/integrations/graphene.py +++ b/sentry_sdk/integrations/graphene.py @@ -4,7 +4,6 @@ from sentry_sdk.consts import OP from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -153,47 +152,29 @@ def graphql_span( ) client_options = sentry_sdk.get_client().options - is_span_streaming_enabled = has_span_streaming_enabled(client_options) - - if is_span_streaming_enabled: - if sentry_sdk.traces.get_current_span() is None: - yield - return - - additional_attributes = {} - if has_data_collection_enabled(client_options): - if client_options["data_collection"]["graphql"]["document"]: - additional_attributes["graphql.document"] = source - elif should_send_default_pii(): - additional_attributes["graphql.document"] = source - - _graphql_span = sentry_sdk.traces.start_span( - name=operation_name, - attributes={ - "sentry.op": op, - "graphql.operation.name": operation_name, - "graphql.operation.type": operation_type, - **additional_attributes, - }, - ) - else: - _graphql_span = sentry_sdk.start_span(op=op, name=operation_name) - if has_data_collection_enabled(client_options): - if client_options["data_collection"]["graphql"]["document"]: - _graphql_span.set_data("graphql.document", source) - elif should_send_default_pii(): - _graphql_span.set_data("graphql.document", source) - - _graphql_span.set_data("graphql.operation.name", operation_name) - _graphql_span.set_data("graphql.operation.type", operation_type) + if sentry_sdk.traces.get_current_span() is None: + yield + return - _graphql_span.__enter__() + additional_attributes = {} + if has_data_collection_enabled(client_options): + if client_options["data_collection"]["graphql"]["document"]: + additional_attributes["graphql.document"] = source + elif should_send_default_pii(): + additional_attributes["graphql.document"] = source + + _graphql_span = sentry_sdk.traces.start_span( + name=operation_name, + attributes={ + "sentry.op": op, + "graphql.operation.name": operation_name, + "graphql.operation.type": operation_type, + **additional_attributes, + }, + ) try: yield finally: - if is_span_streaming_enabled: - _graphql_span.end() # type: ignore - else: - _graphql_span.__exit__(None, None, None) + _graphql_span.end() # type: ignore diff --git a/sentry_sdk/integrations/grpc/aio/client.py b/sentry_sdk/integrations/grpc/aio/client.py index 97e9d828c0..dd8e2826ff 100644 --- a/sentry_sdk/integrations/grpc/aio/client.py +++ b/sentry_sdk/integrations/grpc/aio/client.py @@ -4,7 +4,6 @@ from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable from sentry_sdk.integrations.grpc.consts import SPAN_ORIGIN -from sentry_sdk.tracing_utils import has_span_streaming_enabled try: from google.protobuf.message import Message @@ -50,54 +49,28 @@ async def intercept_unary_unary( ) -> "Union[UnaryUnaryCall, Message]": method = client_call_details.method - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - client_call_details = ( - self._update_client_call_details_metadata_from_scope( - client_call_details - ) - ) - return await continuation(client_call_details, request) - with sentry_sdk.traces.start_span( - name="unary unary call to %s" % method.decode(), - attributes={ - "sentry.op": OP.GRPC_CLIENT, - "sentry.origin": SPAN_ORIGIN, - SPANDATA.RPC_METHOD: method.decode(), - }, - ) as span: - client_call_details = ( - self._update_client_call_details_metadata_from_scope( - client_call_details - ) - ) - - response = await continuation(client_call_details, request) - status_code = await response.code() - span.set_attribute(SPANDATA.RPC_RESPONSE_STATUS_CODE, status_code.name) - - return response - else: - with sentry_sdk.start_span( - op=OP.GRPC_CLIENT, - name="unary unary call to %s" % method.decode(), - origin=SPAN_ORIGIN, - ) as span: - span.set_data("type", "unary unary") - span.set_data("method", method) - - client_call_details = ( - self._update_client_call_details_metadata_from_scope( - client_call_details - ) - ) + if sentry_sdk.traces.get_current_span() is None: + client_call_details = self._update_client_call_details_metadata_from_scope( + client_call_details + ) + return await continuation(client_call_details, request) + with sentry_sdk.traces.start_span( + name="unary unary call to %s" % method.decode(), + attributes={ + "sentry.op": OP.GRPC_CLIENT, + "sentry.origin": SPAN_ORIGIN, + SPANDATA.RPC_METHOD: method.decode(), + }, + ) as span: + client_call_details = self._update_client_call_details_metadata_from_scope( + client_call_details + ) - response = await continuation(client_call_details, request) - status_code = await response.code() - span.set_data("code", status_code.name) + response = await continuation(client_call_details, request) + status_code = await response.code() + span.set_attribute(SPANDATA.RPC_RESPONSE_STATUS_CODE, status_code.name) - return response + return response class SentryUnaryStreamClientInterceptor( @@ -112,49 +85,23 @@ async def intercept_unary_stream( ) -> "Union[AsyncIterable[Any], UnaryStreamCall]": method = client_call_details.method - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - client_call_details = ( - self._update_client_call_details_metadata_from_scope( - client_call_details - ) - ) - return await continuation(client_call_details, request) - with sentry_sdk.traces.start_span( - name="unary stream call to %s" % method.decode(), - attributes={ - "sentry.op": OP.GRPC_CLIENT, - "sentry.origin": SPAN_ORIGIN, - SPANDATA.RPC_METHOD: method.decode(), - }, - ) as span: - client_call_details = ( - self._update_client_call_details_metadata_from_scope( - client_call_details - ) - ) - - response = await continuation(client_call_details, request) - - return response - else: - with sentry_sdk.start_span( - op=OP.GRPC_CLIENT, - name="unary stream call to %s" % method.decode(), - origin=SPAN_ORIGIN, - ) as span: - span.set_data("type", "unary stream") - span.set_data("method", method) - - client_call_details = ( - self._update_client_call_details_metadata_from_scope( - client_call_details - ) - ) - - response = await continuation(client_call_details, request) - # status_code = await response.code() - # span.set_data("code", status_code) + if sentry_sdk.traces.get_current_span() is None: + client_call_details = self._update_client_call_details_metadata_from_scope( + client_call_details + ) + return await continuation(client_call_details, request) + + with sentry_sdk.traces.start_span( + name="unary stream call to %s" % method.decode(), + attributes={ + "sentry.op": OP.GRPC_CLIENT, + "sentry.origin": SPAN_ORIGIN, + SPANDATA.RPC_METHOD: method.decode(), + }, + ): + client_call_details = self._update_client_call_details_metadata_from_scope( + client_call_details + ) - return response + response = await continuation(client_call_details, request) + return response diff --git a/sentry_sdk/integrations/grpc/aio/server.py b/sentry_sdk/integrations/grpc/aio/server.py index 15dcacab59..89a8d7b889 100644 --- a/sentry_sdk/integrations/grpc/aio/server.py +++ b/sentry_sdk/integrations/grpc/aio/server.py @@ -5,8 +5,6 @@ from sentry_sdk.integrations import DidNotEnable from sentry_sdk.integrations.grpc.consts import SPAN_ORIGIN from sentry_sdk.traces import SegmentNameSource -from sentry_sdk.tracing import TransactionSource -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import event_from_exception if TYPE_CHECKING: @@ -54,57 +52,31 @@ async def wrapped(request: "Any", context: "ServicerContext") -> "Any": if not name: return await handler(request, context) - span_streaming = has_span_streaming_enabled( - sentry_sdk.get_client().options + # What if the headers are empty? + sentry_sdk.traces.continue_trace( + dict(context.invocation_metadata()) ) - if span_streaming: - # What if the headers are empty? - sentry_sdk.traces.continue_trace( - dict(context.invocation_metadata()) - ) - - with sentry_sdk.traces.start_span( - name=name, - attributes={ - "sentry.op": OP.GRPC_SERVER, - "sentry.segment.name.source": SegmentNameSource.CUSTOM.value, - "sentry.origin": SPAN_ORIGIN, - }, - parent_span=None, - ): - try: - return await handler.unary_unary(request, context) - except AbortError: - raise - except Exception as exc: - event, hint = event_from_exception( - exc, - mechanism={"type": "grpc", "handled": False}, - ) - sentry_sdk.capture_event(event, hint=hint) - raise - else: - # What if the headers are empty? - transaction = sentry_sdk.continue_trace( - dict(context.invocation_metadata()), - op=OP.GRPC_SERVER, - name=name, - source=TransactionSource.CUSTOM, - origin=SPAN_ORIGIN, - ) - - with sentry_sdk.start_transaction(transaction=transaction): - try: - return await handler.unary_unary(request, context) - except AbortError: - raise - except Exception as exc: - event, hint = event_from_exception( - exc, - mechanism={"type": "grpc", "handled": False}, - ) - sentry_sdk.capture_event(event, hint=hint) - raise + + with sentry_sdk.traces.start_span( + name=name, + attributes={ + "sentry.op": OP.GRPC_SERVER, + "sentry.segment.name.source": SegmentNameSource.CUSTOM.value, + "sentry.origin": SPAN_ORIGIN, + }, + parent_span=None, + ): + try: + return await handler.unary_unary(request, context) + except AbortError: + raise + except Exception as exc: + event, hint = event_from_exception( + exc, + mechanism={"type": "grpc", "handled": False}, + ) + sentry_sdk.capture_event(event, hint=hint) + raise elif not handler.request_streaming and handler.response_streaming: handler_factory = grpc.unary_stream_rpc_method_handler diff --git a/sentry_sdk/integrations/grpc/client.py b/sentry_sdk/integrations/grpc/client.py index fe9954445e..75415e6747 100644 --- a/sentry_sdk/integrations/grpc/client.py +++ b/sentry_sdk/integrations/grpc/client.py @@ -4,7 +4,6 @@ from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable from sentry_sdk.integrations.grpc.consts import SPAN_ORIGIN -from sentry_sdk.tracing_utils import has_span_streaming_enabled if TYPE_CHECKING: from typing import Any, Callable, Iterable, Iterator, Union @@ -31,54 +30,28 @@ def intercept_unary_unary( ) -> "_UnaryOutcome": method = client_call_details.method - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - client_call_details = ( - self._update_client_call_details_metadata_from_scope( - client_call_details - ) - ) - return continuation(client_call_details, request) - with sentry_sdk.traces.start_span( - name="unary unary call to %s" % method, - attributes={ - "sentry.op": OP.GRPC_CLIENT, - "sentry.origin": SPAN_ORIGIN, - SPANDATA.RPC_METHOD: method, - }, - ) as span: - client_call_details = ( - self._update_client_call_details_metadata_from_scope( - client_call_details - ) - ) - - response = continuation(client_call_details, request) - span.set_attribute( - SPANDATA.RPC_RESPONSE_STATUS_CODE, response.code().name - ) - - return response - else: - with sentry_sdk.start_span( - op=OP.GRPC_CLIENT, - name="unary unary call to %s" % method, - origin=SPAN_ORIGIN, - ) as span: - span.set_data("type", "unary unary") - span.set_data("method", method) - - client_call_details = ( - self._update_client_call_details_metadata_from_scope( - client_call_details - ) - ) - - response = continuation(client_call_details, request) - span.set_data("code", response.code().name) - - return response + if sentry_sdk.traces.get_current_span() is None: + client_call_details = self._update_client_call_details_metadata_from_scope( + client_call_details + ) + return continuation(client_call_details, request) + + with sentry_sdk.traces.start_span( + name="unary unary call to %s" % method, + attributes={ + "sentry.op": OP.GRPC_CLIENT, + "sentry.origin": SPAN_ORIGIN, + SPANDATA.RPC_METHOD: method, + }, + ) as span: + client_call_details = self._update_client_call_details_metadata_from_scope( + client_call_details + ) + + response = continuation(client_call_details, request) + span.set_attribute(SPANDATA.RPC_RESPONSE_STATUS_CODE, response.code().name) + + return response def intercept_unary_stream( self: "ClientInterceptor", @@ -88,55 +61,29 @@ def intercept_unary_stream( ) -> "Union[Iterator[Message], Call]": method = client_call_details.method - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) response: "UnaryStreamCall" - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - client_call_details = ( - self._update_client_call_details_metadata_from_scope( - client_call_details - ) - ) - return continuation(client_call_details, request) - with sentry_sdk.traces.start_span( - name="unary stream call to %s" % method, - attributes={ - "sentry.op": OP.GRPC_CLIENT, - "sentry.origin": SPAN_ORIGIN, - SPANDATA.RPC_METHOD: method, - }, - ) as span: - client_call_details = ( - self._update_client_call_details_metadata_from_scope( - client_call_details - ) - ) - - response = continuation(client_call_details, request) - # Setting code on unary-stream leads to execution getting stuck - # span.set_data("code", response.code().name) - - return response - else: - with sentry_sdk.start_span( - op=OP.GRPC_CLIENT, - name="unary stream call to %s" % method, - origin=SPAN_ORIGIN, - ) as span: - span.set_data("type", "unary stream") - span.set_data("method", method) - - client_call_details = ( - self._update_client_call_details_metadata_from_scope( - client_call_details - ) - ) - - response = continuation(client_call_details, request) - # Setting code on unary-stream leads to execution getting stuck - # span.set_data("code", response.code().name) - - return response + if sentry_sdk.traces.get_current_span() is None: + client_call_details = self._update_client_call_details_metadata_from_scope( + client_call_details + ) + return continuation(client_call_details, request) + with sentry_sdk.traces.start_span( + name="unary stream call to %s" % method, + attributes={ + "sentry.op": OP.GRPC_CLIENT, + "sentry.origin": SPAN_ORIGIN, + SPANDATA.RPC_METHOD: method, + }, + ): + client_call_details = self._update_client_call_details_metadata_from_scope( + client_call_details + ) + + response = continuation(client_call_details, request) + # Setting code on unary-stream leads to execution getting stuck + # span.set_data("code", response.code().name) + + return response @staticmethod def _update_client_call_details_metadata_from_scope( diff --git a/sentry_sdk/integrations/grpc/server.py b/sentry_sdk/integrations/grpc/server.py index 9b091c258d..2dc831fcb3 100644 --- a/sentry_sdk/integrations/grpc/server.py +++ b/sentry_sdk/integrations/grpc/server.py @@ -5,8 +5,6 @@ from sentry_sdk.integrations import DidNotEnable from sentry_sdk.integrations.grpc.consts import SPAN_ORIGIN from sentry_sdk.traces import SegmentNameSource -from sentry_sdk.tracing import TransactionSource -from sentry_sdk.tracing_utils import has_span_streaming_enabled if TYPE_CHECKING: from typing import Callable, Optional @@ -48,39 +46,21 @@ def behavior(request: "Message", context: "ServicerContext") -> "Message": if name: metadata = dict(context.invocation_metadata()) - span_streaming = has_span_streaming_enabled( - sentry_sdk.get_client().options - ) - if span_streaming: - sentry_sdk.traces.continue_trace(metadata) + sentry_sdk.traces.continue_trace(metadata) - with sentry_sdk.traces.start_span( - name=name, - attributes={ - "sentry.op": OP.GRPC_SERVER, - "sentry.segment.name.source": SegmentNameSource.CUSTOM.value, - "sentry.origin": SPAN_ORIGIN, - }, - parent_span=None, - ): - try: - return handler.unary_unary(request, context) - except BaseException as e: - raise e - else: - transaction = sentry_sdk.continue_trace( - metadata, - op=OP.GRPC_SERVER, - name=name, - source=TransactionSource.CUSTOM, - origin=SPAN_ORIGIN, - ) - - with sentry_sdk.start_transaction(transaction=transaction): - try: - return handler.unary_unary(request, context) - except BaseException as e: - raise e + with sentry_sdk.traces.start_span( + name=name, + attributes={ + "sentry.op": OP.GRPC_SERVER, + "sentry.segment.name.source": SegmentNameSource.CUSTOM.value, + "sentry.origin": SPAN_ORIGIN, + }, + parent_span=None, + ): + try: + return handler.unary_unary(request, context) + except BaseException as e: + raise e else: return handler.unary_unary(request, context) diff --git a/sentry_sdk/integrations/httpx.py b/sentry_sdk/integrations/httpx.py index 333754e209..0f808a2e4b 100644 --- a/sentry_sdk/integrations/httpx.py +++ b/sentry_sdk/integrations/httpx.py @@ -1,12 +1,11 @@ from typing import TYPE_CHECKING import sentry_sdk -from sentry_sdk.consts import OP, SPANDATA +from sentry_sdk.consts import OP from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.scope import should_send_default_pii from sentry_sdk.tracing_utils import ( add_http_request_source, - has_span_streaming_enabled, propagate_trace_headers, ) from sentry_sdk.utils import ( @@ -50,83 +49,54 @@ def _install_httpx_client() -> None: @ensure_integration_enabled(HttpxIntegration, real_send) def send(self: "Client", request: "Request", **kwargs: "Any") -> "Response": client = sentry_sdk.get_client() - is_span_streaming_enabled = has_span_streaming_enabled(client.options) parsed_url = None with capture_internal_exceptions(): parsed_url = parse_url(str(request.url), sanitize=False) - if is_span_streaming_enabled: - if sentry_sdk.traces.get_current_span() is None: - propagate_trace_headers(client, request) - return real_send(self, request, **kwargs) - - with sentry_sdk.traces.start_span( - name="%s %s" - % ( - request.method, - parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, - ), - attributes={ - "sentry.op": OP.HTTP_CLIENT, - "sentry.origin": HttpxIntegration.origin, - "http.request.method": request.method, - }, - ) as streamed_span: - attributes: "Attributes" = {} - - if parsed_url is not None and should_send_default_pii(): - url_full = parsed_url.url - if parsed_url.query: - url_full += "?" + parsed_url.query - if parsed_url.fragment: - url_full += "#" + parsed_url.fragment - - attributes["url.full"] = url_full - if parsed_url.query: - attributes["url.query"] = parsed_url.query - if parsed_url.fragment: - attributes["url.fragment"] = parsed_url.fragment - - propagate_trace_headers(client, request) - - try: - rv = real_send(self, request, **kwargs) - - streamed_span.status = "error" if rv.status_code >= 400 else "ok" - attributes["http.response.status_code"] = rv.status_code - finally: - streamed_span.set_attributes(attributes) - - # Needs to happen within the context manager as we want to attach the - # final data before the span finishes and is sent for ingesting. - with capture_internal_exceptions(): - add_http_request_source(streamed_span) - else: - with sentry_sdk.start_span( - op=OP.HTTP_CLIENT, - name="%s %s" - % ( - request.method, - parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, - ), - origin=HttpxIntegration.origin, - ) as span: - span.set_data(SPANDATA.HTTP_METHOD, request.method) - if parsed_url is not None: - span.set_data("url", parsed_url.url) - span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) - span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) - - propagate_trace_headers(client, request) - + if sentry_sdk.traces.get_current_span() is None: + propagate_trace_headers(client, request) + return real_send(self, request, **kwargs) + + with sentry_sdk.traces.start_span( + name="%s %s" + % ( + request.method, + parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, + ), + attributes={ + "sentry.op": OP.HTTP_CLIENT, + "sentry.origin": HttpxIntegration.origin, + "http.request.method": request.method, + }, + ) as streamed_span: + attributes: "Attributes" = {} + + if parsed_url is not None and should_send_default_pii(): + url_full = parsed_url.url + if parsed_url.query: + url_full += "?" + parsed_url.query + if parsed_url.fragment: + url_full += "#" + parsed_url.fragment + + attributes["url.full"] = url_full + if parsed_url.query: + attributes["url.query"] = parsed_url.query + if parsed_url.fragment: + attributes["url.fragment"] = parsed_url.fragment + + propagate_trace_headers(client, request) + + try: rv = real_send(self, request, **kwargs) - span.set_http_status(rv.status_code) - span.set_data("reason", rv.reason_phrase) + streamed_span.status = "error" if rv.status_code >= 400 else "ok" + attributes["http.response.status_code"] = rv.status_code + finally: + streamed_span.set_attributes(attributes) with capture_internal_exceptions(): - add_http_request_source(span) + add_http_request_source(streamed_span) return rv @@ -143,82 +113,53 @@ async def send( if client.get_integration(HttpxIntegration) is None: return await real_send(self, request, **kwargs) - is_span_streaming_enabled = has_span_streaming_enabled(client.options) parsed_url = None with capture_internal_exceptions(): parsed_url = parse_url(str(request.url), sanitize=False) - if is_span_streaming_enabled: - if sentry_sdk.traces.get_current_span() is None: - propagate_trace_headers(client, request) - return await real_send(self, request, **kwargs) - - with sentry_sdk.traces.start_span( - name="%s %s" - % ( - request.method, - parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, - ), - attributes={ - "sentry.op": OP.HTTP_CLIENT, - "sentry.origin": HttpxIntegration.origin, - "http.request.method": request.method, - }, - ) as streamed_span: - attributes: "Attributes" = {} - - if parsed_url is not None and should_send_default_pii(): - url_full = parsed_url.url - if parsed_url.query: - url_full += "?" + parsed_url.query - if parsed_url.fragment: - url_full += "#" + parsed_url.fragment - - attributes["url.full"] = url_full - if parsed_url.query: - attributes["url.query"] = parsed_url.query - if parsed_url.fragment: - attributes["url.fragment"] = parsed_url.fragment - - propagate_trace_headers(client, request) - - try: - rv = await real_send(self, request, **kwargs) - - streamed_span.status = "error" if rv.status_code >= 400 else "ok" - attributes["http.response.status_code"] = rv.status_code - finally: - streamed_span.set_attributes(attributes) - - # Needs to happen within the context manager as we want to attach the - # final data before the span finishes and is sent for ingesting. - with capture_internal_exceptions(): - add_http_request_source(streamed_span) - else: - with sentry_sdk.start_span( - op=OP.HTTP_CLIENT, - name="%s %s" - % ( - request.method, - parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, - ), - origin=HttpxIntegration.origin, - ) as span: - span.set_data(SPANDATA.HTTP_METHOD, request.method) - if parsed_url is not None: - span.set_data("url", parsed_url.url) - span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) - span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) - - propagate_trace_headers(client, request) + if sentry_sdk.traces.get_current_span() is None: + propagate_trace_headers(client, request) + return await real_send(self, request, **kwargs) + with sentry_sdk.traces.start_span( + name="%s %s" + % ( + request.method, + parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, + ), + attributes={ + "sentry.op": OP.HTTP_CLIENT, + "sentry.origin": HttpxIntegration.origin, + "http.request.method": request.method, + }, + ) as streamed_span: + attributes: "Attributes" = {} + + if parsed_url is not None and should_send_default_pii(): + url_full = parsed_url.url + if parsed_url.query: + url_full += "?" + parsed_url.query + if parsed_url.fragment: + url_full += "#" + parsed_url.fragment + + attributes["url.full"] = url_full + if parsed_url.query: + attributes["url.query"] = parsed_url.query + if parsed_url.fragment: + attributes["url.fragment"] = parsed_url.fragment + + propagate_trace_headers(client, request) + + try: rv = await real_send(self, request, **kwargs) - span.set_http_status(rv.status_code) - span.set_data("reason", rv.reason_phrase) + streamed_span.status = "error" if rv.status_code >= 400 else "ok" + attributes["http.response.status_code"] = rv.status_code + finally: + streamed_span.set_attributes(attributes) with capture_internal_exceptions(): - add_http_request_source(span) + add_http_request_source(streamed_span) return rv diff --git a/sentry_sdk/integrations/httpx2.py b/sentry_sdk/integrations/httpx2.py index b658ce8ba4..249021d4ad 100644 --- a/sentry_sdk/integrations/httpx2.py +++ b/sentry_sdk/integrations/httpx2.py @@ -1,12 +1,11 @@ from typing import TYPE_CHECKING import sentry_sdk -from sentry_sdk.consts import OP, SPANDATA +from sentry_sdk.consts import OP from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.scope import should_send_default_pii from sentry_sdk.tracing_utils import ( add_http_request_source, - has_span_streaming_enabled, propagate_trace_headers, ) from sentry_sdk.utils import ( @@ -50,84 +49,57 @@ def _install_httpx2_client() -> None: @ensure_integration_enabled(Httpx2Integration, real_send) def send(self: "Client", request: "Request", **kwargs: "Any") -> "Response": client = sentry_sdk.get_client() - is_span_streaming_enabled = has_span_streaming_enabled(client.options) parsed_url = None with capture_internal_exceptions(): parsed_url = parse_url(str(request.url), sanitize=False) - if is_span_streaming_enabled: - if sentry_sdk.traces.get_current_span() is None: - propagate_trace_headers(client, request) - - return real_send(self, request, **kwargs) - - with sentry_sdk.traces.start_span( - name="%s %s" - % ( - request.method, - parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, - ), - attributes={ - "sentry.op": OP.HTTP_CLIENT, - "sentry.origin": Httpx2Integration.origin, - "http.request.method": request.method, - }, - ) as streamed_span: - attributes: "Attributes" = {} - - if parsed_url is not None and should_send_default_pii(): - url_full = parsed_url.url - if parsed_url.query: - url_full += "?" + parsed_url.query - if parsed_url.fragment: - url_full += "#" + parsed_url.fragment - - attributes["url.full"] = url_full - if parsed_url.query: - attributes["url.query"] = parsed_url.query - if parsed_url.fragment: - attributes["url.fragment"] = parsed_url.fragment - - propagate_trace_headers(client, request) - - try: - rv = real_send(self, request, **kwargs) - - streamed_span.status = "error" if rv.status_code >= 400 else "ok" - attributes["http.response.status_code"] = rv.status_code - finally: - streamed_span.set_attributes(attributes) - - # Needs to happen within the context manager as we want to attach the - # final data before the span finishes and is sent for ingesting. - with capture_internal_exceptions(): - add_http_request_source(streamed_span) - else: - with sentry_sdk.start_span( - op=OP.HTTP_CLIENT, - name="%s %s" - % ( - request.method, - parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, - ), - origin=Httpx2Integration.origin, - ) as span: - span.set_data(SPANDATA.HTTP_METHOD, request.method) - if parsed_url is not None: - span.set_data("url", parsed_url.url) - span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) - span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) - - propagate_trace_headers(client, request) - + if sentry_sdk.traces.get_current_span() is None: + propagate_trace_headers(client, request) + + return real_send(self, request, **kwargs) + + with sentry_sdk.traces.start_span( + name="%s %s" + % ( + request.method, + parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, + ), + attributes={ + "sentry.op": OP.HTTP_CLIENT, + "sentry.origin": Httpx2Integration.origin, + "http.request.method": request.method, + }, + ) as streamed_span: + attributes: "Attributes" = {} + + if parsed_url is not None and should_send_default_pii(): + url_full = parsed_url.url + if parsed_url.query: + url_full += "?" + parsed_url.query + if parsed_url.fragment: + url_full += "#" + parsed_url.fragment + + attributes["url.full"] = url_full + if parsed_url.query: + attributes["url.query"] = parsed_url.query + if parsed_url.fragment: + attributes["url.fragment"] = parsed_url.fragment + + propagate_trace_headers(client, request) + + try: rv = real_send(self, request, **kwargs) - span.set_http_status(rv.status_code) - span.set_data("reason", rv.reason_phrase) + streamed_span.status = "error" if rv.status_code >= 400 else "ok" + attributes["http.response.status_code"] = rv.status_code + finally: + streamed_span.set_attributes(attributes) + # Needs to happen within the context manager as we want to attach the + # final data before the span finishes and is sent for ingesting. with capture_internal_exceptions(): - add_http_request_source(span) + add_http_request_source(streamed_span) return rv @@ -144,83 +116,56 @@ async def send( if client.get_integration(Httpx2Integration) is None: return await real_send(self, request, **kwargs) - is_span_streaming_enabled = has_span_streaming_enabled(client.options) parsed_url = None with capture_internal_exceptions(): parsed_url = parse_url(str(request.url), sanitize=False) - if is_span_streaming_enabled: - if sentry_sdk.traces.get_current_span() is None: - propagate_trace_headers(client, request) - - return await real_send(self, request, **kwargs) - - with sentry_sdk.traces.start_span( - name="%s %s" - % ( - request.method, - parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, - ), - attributes={ - "sentry.op": OP.HTTP_CLIENT, - "sentry.origin": Httpx2Integration.origin, - "http.request.method": request.method, - }, - ) as streamed_span: - attributes: "Attributes" = {} - - if parsed_url is not None and should_send_default_pii(): - url_full = parsed_url.url - if parsed_url.query: - url_full += "?" + parsed_url.query - if parsed_url.fragment: - url_full += "#" + parsed_url.fragment - - attributes["url.full"] = url_full - if parsed_url.query: - attributes["url.query"] = parsed_url.query - if parsed_url.fragment: - attributes["url.fragment"] = parsed_url.fragment - - propagate_trace_headers(client, request) - - try: - rv = await real_send(self, request, **kwargs) - - streamed_span.status = "error" if rv.status_code >= 400 else "ok" - attributes["http.response.status_code"] = rv.status_code - finally: - streamed_span.set_attributes(attributes) - - # Needs to happen within the context manager as we want to attach the - # final data before the span finishes and is sent for ingesting. - with capture_internal_exceptions(): - add_http_request_source(streamed_span) - else: - with sentry_sdk.start_span( - op=OP.HTTP_CLIENT, - name="%s %s" - % ( - request.method, - parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, - ), - origin=Httpx2Integration.origin, - ) as span: - span.set_data(SPANDATA.HTTP_METHOD, request.method) - if parsed_url is not None: - span.set_data("url", parsed_url.url) - span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) - span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) - - propagate_trace_headers(client, request) + if sentry_sdk.traces.get_current_span() is None: + propagate_trace_headers(client, request) + + return await real_send(self, request, **kwargs) + with sentry_sdk.traces.start_span( + name="%s %s" + % ( + request.method, + parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, + ), + attributes={ + "sentry.op": OP.HTTP_CLIENT, + "sentry.origin": Httpx2Integration.origin, + "http.request.method": request.method, + }, + ) as streamed_span: + attributes: "Attributes" = {} + + if parsed_url is not None and should_send_default_pii(): + url_full = parsed_url.url + if parsed_url.query: + url_full += "?" + parsed_url.query + if parsed_url.fragment: + url_full += "#" + parsed_url.fragment + + attributes["url.full"] = url_full + if parsed_url.query: + attributes["url.query"] = parsed_url.query + if parsed_url.fragment: + attributes["url.fragment"] = parsed_url.fragment + + propagate_trace_headers(client, request) + + try: rv = await real_send(self, request, **kwargs) - span.set_http_status(rv.status_code) - span.set_data("reason", rv.reason_phrase) + streamed_span.status = "error" if rv.status_code >= 400 else "ok" + attributes["http.response.status_code"] = rv.status_code + finally: + streamed_span.set_attributes(attributes) + # Needs to happen within the context manager as we want to attach the + # final data before the span finishes and is sent for ingesting. with capture_internal_exceptions(): - add_http_request_source(span) + add_http_request_source(streamed_span) return rv diff --git a/sentry_sdk/integrations/huey.py b/sentry_sdk/integrations/huey.py index e1d34f05d7..bcb44b5054 100644 --- a/sentry_sdk/integrations/huey.py +++ b/sentry_sdk/integrations/huey.py @@ -3,17 +3,15 @@ from typing import TYPE_CHECKING import sentry_sdk -from sentry_sdk.api import continue_trace, get_baggage, get_traceparent -from sentry_sdk.consts import OP, SPANDATA, SPANSTATUS +from sentry_sdk.api import get_baggage, get_traceparent +from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import SegmentNameSource, SpanStatus, StreamedSpan from sentry_sdk.tracing import ( BAGGAGE_HEADER_NAME, SENTRY_TRACE_HEADER_NAME, - TransactionSource, ) -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( SENSITIVE_DATA_SUBSTITUTE, _register_control_flow_exception, @@ -76,15 +74,11 @@ def _sentry_enqueue( else: span_name = item.name - is_span_streaming_enabled = has_span_streaming_enabled( - sentry_sdk.get_client().options - ) - no_headers_types = (PeriodicTask,) + tuple( t for t in [HueyGroup, HueyChord] if t is not None ) - if is_span_streaming_enabled and sentry_sdk.traces.get_current_span() is None: + if sentry_sdk.traces.get_current_span() is None: if not isinstance(item, no_headers_types): item.kwargs["sentry_headers"] = { BAGGAGE_HEADER_NAME: get_baggage(), @@ -92,22 +86,14 @@ def _sentry_enqueue( } return old_enqueue(self, item) - if is_span_streaming_enabled: - span_ctx = sentry_sdk.traces.start_span( - name=span_name, - attributes={ - "sentry.op": OP.QUEUE_SUBMIT_HUEY, - "sentry.origin": HueyIntegration.origin, - SPANDATA.MESSAGING_DESTINATION_NAME: self.name, - }, - ) - else: - span_ctx = sentry_sdk.start_span( - op=OP.QUEUE_SUBMIT_HUEY, - name=span_name, - origin=HueyIntegration.origin, - ) - span_ctx.set_data(SPANDATA.MESSAGING_DESTINATION_NAME, self.name) + span_ctx = sentry_sdk.traces.start_span( + name=span_name, + attributes={ + "sentry.op": OP.QUEUE_SUBMIT_HUEY, + "sentry.origin": HueyIntegration.origin, + SPANDATA.MESSAGING_DESTINATION_NAME: self.name, + }, + ) with span_ctx: if not isinstance(item, no_headers_types): @@ -161,20 +147,13 @@ def event_processor(event: "Event", hint: "Hint") -> "Optional[Event]": def _capture_exception(exc_info: "ExcInfo") -> None: scope = sentry_sdk.get_current_scope() - is_span_streaming_enabled = has_span_streaming_enabled( - sentry_sdk.get_client().options - ) if exc_info[0] in HUEY_CONTROL_FLOW_EXCEPTIONS: - if not is_span_streaming_enabled: - scope.transaction.set_status(SPANSTATUS.ABORTED) - elif type(scope._span) is StreamedSpan: + if type(scope._span) is StreamedSpan: scope._span._segment.status = SpanStatus.OK return - if not is_span_streaming_enabled: - scope.transaction.set_status(SPANSTATUS.INTERNAL_ERROR) - elif type(scope._span) is StreamedSpan: + if type(scope._span) is StreamedSpan: scope._span._segment.status = SpanStatus.ERROR event, hint = event_from_exception( @@ -214,38 +193,23 @@ def _sentry_execute( scope.add_event_processor(_make_event_processor(task)) sentry_headers = task.kwargs.pop("sentry_headers", None) - is_span_streaming_enabled = has_span_streaming_enabled( - sentry_sdk.get_client().options - ) - if is_span_streaming_enabled: - headers = sentry_headers or {} - sentry_sdk.traces.continue_trace(headers) - span_ctx = sentry_sdk.traces.start_span( - name=task.name, - attributes={ - "sentry.op": OP.QUEUE_TASK_HUEY, - "sentry.origin": HueyIntegration.origin, - "sentry.segment.name.source": SegmentNameSource.TASK, - SPANDATA.MESSAGING_DESTINATION_NAME: self.name, - "messaging.message.id": task.id, - "messaging.message.system": "huey", - "messaging.message.retry.count": (task.default_retries or 0) - - task.retries, - }, - parent_span=None, - ) - else: - transaction = continue_trace( - sentry_headers or {}, - name=task.name, - op=OP.QUEUE_TASK_HUEY, - source=TransactionSource.TASK, - origin=HueyIntegration.origin, - ) - transaction.set_status(SPANSTATUS.OK) - span_ctx = sentry_sdk.start_transaction(transaction) - span_ctx.set_data(SPANDATA.MESSAGING_DESTINATION_NAME, self.name) + headers = sentry_headers or {} + sentry_sdk.traces.continue_trace(headers) + span_ctx = sentry_sdk.traces.start_span( + name=task.name, + attributes={ + "sentry.op": OP.QUEUE_TASK_HUEY, + "sentry.origin": HueyIntegration.origin, + "sentry.segment.name.source": SegmentNameSource.TASK, + SPANDATA.MESSAGING_DESTINATION_NAME: self.name, + "messaging.message.id": task.id, + "messaging.message.system": "huey", + "messaging.message.retry.count": (task.default_retries or 0) + - task.retries, + }, + parent_span=None, + ) if not getattr(task, "_sentry_is_patched", False): task.execute = _wrap_task_execute(task.execute) diff --git a/sentry_sdk/integrations/huggingface_hub.py b/sentry_sdk/integrations/huggingface_hub.py index 835acc7279..9cdbe571a5 100644 --- a/sentry_sdk/integrations/huggingface_hub.py +++ b/sentry_sdk/integrations/huggingface_hub.py @@ -7,14 +7,11 @@ from sentry_sdk.ai.monitoring import record_token_usage from sentry_sdk.ai.utils import ( _set_span_data_attribute, - get_start_span_function, set_data_normalized, ) from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( capture_internal_exceptions, event_from_exception, @@ -22,9 +19,7 @@ ) if TYPE_CHECKING: - from typing import Any, Callable, Iterable, Union - - from sentry_sdk.tracing import Span + from typing import Any, Callable, Iterable try: import huggingface_hub.inference._client @@ -91,21 +86,13 @@ def new_huggingface_task(*args: "Any", **kwargs: "Any") -> "Any": model = client.model or kwargs.get("model") or "" operation_name = op.split(".")[-1] - span: "Union[Span, StreamedSpan]" - if has_span_streaming_enabled(sentry_sdk.get_client().options): - span = sentry_sdk.traces.start_span( - name=f"{operation_name} {model}", - attributes={ - "sentry.op": op, - "sentry.origin": HuggingfaceHubIntegration.origin, - }, - ) - else: - span = get_start_span_function()( - op=op, - name=f"{operation_name} {model}", - origin=HuggingfaceHubIntegration.origin, - ) + span = sentry_sdk.traces.start_span( + name=f"{operation_name} {model}", + attributes={ + "sentry.op": op, + "sentry.origin": HuggingfaceHubIntegration.origin, + }, + ) span.__enter__() _set_span_data_attribute(span, SPANDATA.GEN_AI_OPERATION_NAME, operation_name) diff --git a/sentry_sdk/integrations/langchain.py b/sentry_sdk/integrations/langchain.py index 9dcbb189ce..2a0d67e348 100644 --- a/sentry_sdk/integrations/langchain.py +++ b/sentry_sdk/integrations/langchain.py @@ -9,7 +9,6 @@ import sentry_sdk from sentry_sdk.ai.utils import ( GEN_AI_ALLOWED_MESSAGE_ROLES, - get_start_span_function, normalize_message_roles, set_data_normalized, transform_content_part, @@ -21,7 +20,6 @@ from sentry_sdk.traces import StreamedSpan from sentry_sdk.tracing_utils import ( _get_value, - has_span_streaming_enabled, should_truncate_gen_ai_input, ) from sentry_sdk.utils import capture_internal_exceptions, logger @@ -317,17 +315,12 @@ def _create_span( ) if span is None: - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - span = ( - sentry_sdk.traces.start_span( - name=name, - attributes={ - "sentry.op": op, - "sentry.origin": origin, - }, - ) - if span_streaming - else sentry_sdk.start_span(op=op, name=name, origin=origin) + span = sentry_sdk.traces.start_span( + name=name, + attributes={ + "sentry.op": op, + "sentry.origin": origin, + }, ) span.__enter__() @@ -1019,107 +1012,55 @@ def new_invoke(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": run_name, tools = _get_request_data(self, args, kwargs) - if has_span_streaming_enabled(client.options): - with sentry_sdk.traces.start_span( - name=f"invoke_agent {run_name}" if run_name else "invoke_agent", - attributes={ - "sentry.op": OP.GEN_AI_INVOKE_AGENT, - "sentry.origin": LangchainIntegration.origin, - SPANDATA.GEN_AI_OPERATION_NAME: "invoke_agent", - SPANDATA.GEN_AI_RESPONSE_STREAMING: False, - }, - ) as span: - if run_name: - span.set_attribute(SPANDATA.GEN_AI_FUNCTION_ID, run_name) - - _set_tools_on_span(span, tools) - - # Run the agent - result = f(self, *args, **kwargs) - - input = result.get("input") - if ( - input is not None - and should_send_default_pii() - and integration.include_prompts - ): - normalized_messages = normalize_message_roles([input]) - - client = sentry_sdk.get_client() - scope = sentry_sdk.get_current_scope() - messages_data = ( - truncate_and_annotate_messages(normalized_messages, span, scope) - if should_truncate_gen_ai_input(client.options) - else normalized_messages - ) - if messages_data is not None: - set_data_normalized( - span, - SPANDATA.GEN_AI_REQUEST_MESSAGES, - messages_data, - unpack=False, - ) - - output = result.get("output") - if ( - output is not None - and should_send_default_pii() - and integration.include_prompts - ): - set_data_normalized(span, SPANDATA.GEN_AI_RESPONSE_TEXT, output) - - return result - else: - start_span_function = get_start_span_function() - - with start_span_function( - op=OP.GEN_AI_INVOKE_AGENT, - name=f"invoke_agent {run_name}" if run_name else "invoke_agent", - origin=LangchainIntegration.origin, - ) as span: - if run_name: - span.set_data(SPANDATA.GEN_AI_FUNCTION_ID, run_name) + with sentry_sdk.traces.start_span( + name=f"invoke_agent {run_name}" if run_name else "invoke_agent", + attributes={ + "sentry.op": OP.GEN_AI_INVOKE_AGENT, + "sentry.origin": LangchainIntegration.origin, + SPANDATA.GEN_AI_OPERATION_NAME: "invoke_agent", + SPANDATA.GEN_AI_RESPONSE_STREAMING: False, + }, + ) as span: + if run_name: + span.set_attribute(SPANDATA.GEN_AI_FUNCTION_ID, run_name) - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "invoke_agent") - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, False) + _set_tools_on_span(span, tools) - _set_tools_on_span(span, tools) + # Run the agent + result = f(self, *args, **kwargs) - # Run the agent - result = f(self, *args, **kwargs) + input = result.get("input") + if ( + input is not None + and should_send_default_pii() + and integration.include_prompts + ): + normalized_messages = normalize_message_roles([input]) - input = result.get("input") - if ( - input is not None - and should_send_default_pii() - and integration.include_prompts - ): - normalized_messages = normalize_message_roles([input]) - - client = sentry_sdk.get_client() - scope = sentry_sdk.get_current_scope() - messages_data = ( - truncate_and_annotate_messages(normalized_messages, span, scope) - if should_truncate_gen_ai_input(client.options) - else normalized_messages + client = sentry_sdk.get_client() + scope = sentry_sdk.get_current_scope() + messages_data = ( + truncate_and_annotate_messages(normalized_messages, span, scope) + if should_truncate_gen_ai_input(client.options) + else normalized_messages + ) + if messages_data is not None: + set_data_normalized( + span, + SPANDATA.GEN_AI_REQUEST_MESSAGES, + messages_data, + unpack=False, ) - if messages_data is not None: - set_data_normalized( - span, - SPANDATA.GEN_AI_REQUEST_MESSAGES, - messages_data, - unpack=False, - ) - output = result.get("output") - if ( - output is not None - and should_send_default_pii() - and integration.include_prompts - ): - set_data_normalized(span, SPANDATA.GEN_AI_RESPONSE_TEXT, output) + output = result.get("output") + if ( + output is not None + and should_send_default_pii() + and integration.include_prompts + ): + set_data_normalized(span, SPANDATA.GEN_AI_RESPONSE_TEXT, output) - return result + return result return new_invoke @@ -1134,34 +1075,18 @@ def new_stream(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": run_name, tools = _get_request_data(self, args, kwargs) - if has_span_streaming_enabled(client.options): - span = sentry_sdk.traces.start_span( - name=f"invoke_agent {run_name}" if run_name else "invoke_agent", - attributes={ - "sentry.op": OP.GEN_AI_INVOKE_AGENT, - "sentry.origin": LangchainIntegration.origin, - SPANDATA.GEN_AI_OPERATION_NAME: "invoke_agent", - SPANDATA.GEN_AI_RESPONSE_STREAMING: True, - }, - ) - - if run_name: - span.set_attribute(SPANDATA.GEN_AI_FUNCTION_ID, run_name) - else: - start_span_function = get_start_span_function() - - span = start_span_function( - op=OP.GEN_AI_INVOKE_AGENT, - name=f"invoke_agent {run_name}" if run_name else "invoke_agent", - origin=LangchainIntegration.origin, - ) - span.__enter__() - - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "invoke_agent") - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, True) + span = sentry_sdk.traces.start_span( + name=f"invoke_agent {run_name}" if run_name else "invoke_agent", + attributes={ + "sentry.op": OP.GEN_AI_INVOKE_AGENT, + "sentry.origin": LangchainIntegration.origin, + SPANDATA.GEN_AI_OPERATION_NAME: "invoke_agent", + SPANDATA.GEN_AI_RESPONSE_STREAMING: True, + }, + ) - if run_name: - span.set_data(SPANDATA.GEN_AI_FUNCTION_ID, run_name) + if run_name: + span.set_attribute(SPANDATA.GEN_AI_FUNCTION_ID, run_name) _set_tools_on_span(span, tools) @@ -1286,58 +1211,32 @@ def new_embedding_method(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": model_name = getattr(self, "model", None) or getattr(self, "model_name", None) - if has_span_streaming_enabled(client.options): - with sentry_sdk.traces.start_span( - name=f"embeddings {model_name}" if model_name else "embeddings", - attributes={ - "sentry.op": OP.GEN_AI_EMBEDDINGS, - "sentry.origin": LangchainIntegration.origin, - SPANDATA.GEN_AI_OPERATION_NAME: "embeddings", - }, - ) as span: - if model_name: - span.set_attribute(SPANDATA.GEN_AI_REQUEST_MODEL, model_name) - - # Capture input if PII is allowed - if ( - should_send_default_pii() - and integration.include_prompts - and len(args) > 0 - ): - input_data = args[0] - # Normalize to list format - texts = input_data if isinstance(input_data, list) else [input_data] - set_data_normalized( - span, SPANDATA.GEN_AI_EMBEDDINGS_INPUT, texts, unpack=False - ) - - result = f(self, *args, **kwargs) - return result - else: - with sentry_sdk.start_span( - op=OP.GEN_AI_EMBEDDINGS, - name=f"embeddings {model_name}" if model_name else "embeddings", - origin=LangchainIntegration.origin, - ) as span: - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "embeddings") - if model_name: - span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model_name) - - # Capture input if PII is allowed - if ( - should_send_default_pii() - and integration.include_prompts - and len(args) > 0 - ): - input_data = args[0] - # Normalize to list format - texts = input_data if isinstance(input_data, list) else [input_data] - set_data_normalized( - span, SPANDATA.GEN_AI_EMBEDDINGS_INPUT, texts, unpack=False - ) + with sentry_sdk.traces.start_span( + name=f"embeddings {model_name}" if model_name else "embeddings", + attributes={ + "sentry.op": OP.GEN_AI_EMBEDDINGS, + "sentry.origin": LangchainIntegration.origin, + SPANDATA.GEN_AI_OPERATION_NAME: "embeddings", + }, + ) as span: + if model_name: + span.set_attribute(SPANDATA.GEN_AI_REQUEST_MODEL, model_name) + + # Capture input if PII is allowed + if ( + should_send_default_pii() + and integration.include_prompts + and len(args) > 0 + ): + input_data = args[0] + # Normalize to list format + texts = input_data if isinstance(input_data, list) else [input_data] + set_data_normalized( + span, SPANDATA.GEN_AI_EMBEDDINGS_INPUT, texts, unpack=False + ) - result = f(self, *args, **kwargs) - return result + result = f(self, *args, **kwargs) + return result return new_embedding_method @@ -1356,57 +1255,31 @@ async def new_async_embedding_method( model_name = getattr(self, "model", None) or getattr(self, "model_name", None) - if has_span_streaming_enabled(client.options): - with sentry_sdk.traces.start_span( - name=f"embeddings {model_name}" if model_name else "embeddings", - attributes={ - "sentry.op": OP.GEN_AI_EMBEDDINGS, - "sentry.origin": LangchainIntegration.origin, - SPANDATA.GEN_AI_OPERATION_NAME: "embeddings", - }, - ) as span: - if model_name: - span.set_attribute(SPANDATA.GEN_AI_REQUEST_MODEL, model_name) - - # Capture input if PII is allowed - if ( - should_send_default_pii() - and integration.include_prompts - and len(args) > 0 - ): - input_data = args[0] - # Normalize to list format - texts = input_data if isinstance(input_data, list) else [input_data] - set_data_normalized( - span, SPANDATA.GEN_AI_EMBEDDINGS_INPUT, texts, unpack=False - ) - - result = await f(self, *args, **kwargs) - return result - else: - with sentry_sdk.start_span( - op=OP.GEN_AI_EMBEDDINGS, - name=f"embeddings {model_name}" if model_name else "embeddings", - origin=LangchainIntegration.origin, - ) as span: - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "embeddings") - if model_name: - span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model_name) - - # Capture input if PII is allowed - if ( - should_send_default_pii() - and integration.include_prompts - and len(args) > 0 - ): - input_data = args[0] - # Normalize to list format - texts = input_data if isinstance(input_data, list) else [input_data] - set_data_normalized( - span, SPANDATA.GEN_AI_EMBEDDINGS_INPUT, texts, unpack=False - ) + with sentry_sdk.traces.start_span( + name=f"embeddings {model_name}" if model_name else "embeddings", + attributes={ + "sentry.op": OP.GEN_AI_EMBEDDINGS, + "sentry.origin": LangchainIntegration.origin, + SPANDATA.GEN_AI_OPERATION_NAME: "embeddings", + }, + ) as span: + if model_name: + span.set_attribute(SPANDATA.GEN_AI_REQUEST_MODEL, model_name) + + # Capture input if PII is allowed + if ( + should_send_default_pii() + and integration.include_prompts + and len(args) > 0 + ): + input_data = args[0] + # Normalize to list format + texts = input_data if isinstance(input_data, list) else [input_data] + set_data_normalized( + span, SPANDATA.GEN_AI_EMBEDDINGS_INPUT, texts, unpack=False + ) - result = await f(self, *args, **kwargs) - return result + result = await f(self, *args, **kwargs) + return result return new_async_embedding_method diff --git a/sentry_sdk/integrations/langgraph.py b/sentry_sdk/integrations/langgraph.py index 3d3856a913..67c0561680 100644 --- a/sentry_sdk/integrations/langgraph.py +++ b/sentry_sdk/integrations/langgraph.py @@ -3,7 +3,6 @@ import sentry_sdk from sentry_sdk.ai.utils import ( - get_start_span_function, normalize_message_roles, set_data_normalized, truncate_and_annotate_messages, @@ -14,9 +13,7 @@ # This is fine because langgraph depends on langchain-base, and LangchainIntegration only imports from langchain-base. from sentry_sdk.integrations.langchain import LangchainIntegration from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import StreamedSpan from sentry_sdk.tracing_utils import ( - has_span_streaming_enabled, should_truncate_gen_ai_input, ) from sentry_sdk.utils import safe_serialize @@ -119,26 +116,24 @@ def _wrap_state_graph_compile(f: "Callable[..., Any]") -> "Callable[..., Any]": def new_compile(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": client = sentry_sdk.get_client() integration = client.get_integration(LanggraphIntegration) - if integration is None or has_span_streaming_enabled(client.options): + if integration is None: return f(self, *args, **kwargs) - with sentry_sdk.start_span( - op=OP.GEN_AI_CREATE_AGENT, - origin=LanggraphIntegration.origin, + with sentry_sdk.traces.start_span( + name="create_agent", + attributes={ + "sentry.op": OP.GEN_AI_CREATE_AGENT, + "sentry.origin": LanggraphIntegration.origin, + SPANDATA.GEN_AI_OPERATION_NAME: "create_agent", + }, ) as span: compiled_graph = f(self, *args, **kwargs) compiled_graph_name = getattr(compiled_graph, "name", None) - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "create_agent") - span.set_data(SPANDATA.GEN_AI_AGENT_NAME, compiled_graph_name) - - if compiled_graph_name: - span.description = f"create_agent {compiled_graph_name}" - else: - span.description = "create_agent" + span.set_attribute(SPANDATA.GEN_AI_AGENT_NAME, compiled_graph_name) if kwargs.get("model", None) is not None: - span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, kwargs.get("model")) + span.set_attribute(SPANDATA.GEN_AI_REQUEST_MODEL, kwargs.get("model")) tools = None get_graph = getattr(compiled_graph, "get_graph", None) @@ -153,7 +148,7 @@ def new_compile(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": tools = list(data.tools_by_name.keys()) if tools is not None: - span.set_data(SPANDATA.GEN_AI_REQUEST_AVAILABLE_TOOLS, tools) + span.set_attribute(SPANDATA.GEN_AI_REQUEST_AVAILABLE_TOOLS, tools) return compiled_graph @@ -173,101 +168,51 @@ def new_invoke(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": f"invoke_agent {graph_name}".strip() if graph_name else "invoke_agent" ) - if has_span_streaming_enabled(client.options): - with sentry_sdk.traces.start_span( - name=span_name, - attributes={ - "sentry.op": OP.GEN_AI_INVOKE_AGENT, - "sentry.origin": LanggraphIntegration.origin, - SPANDATA.GEN_AI_OPERATION_NAME: "invoke_agent", - }, - ) as span: - if graph_name: - span.set_attribute(SPANDATA.GEN_AI_PIPELINE_NAME, graph_name) - span.set_attribute(SPANDATA.GEN_AI_AGENT_NAME, graph_name) - - # Store input messages to later compare with output - input_messages = None - if ( - len(args) > 0 - and should_send_default_pii() - and integration.include_prompts - ): - input_messages = _parse_langgraph_messages(args[0]) - if input_messages: - normalized_input_messages = normalize_message_roles( - input_messages - ) + with sentry_sdk.traces.start_span( + name=span_name, + attributes={ + "sentry.op": OP.GEN_AI_INVOKE_AGENT, + "sentry.origin": LanggraphIntegration.origin, + SPANDATA.GEN_AI_OPERATION_NAME: "invoke_agent", + }, + ) as span: + if graph_name: + span.set_attribute(SPANDATA.GEN_AI_PIPELINE_NAME, graph_name) + span.set_attribute(SPANDATA.GEN_AI_AGENT_NAME, graph_name) - client = sentry_sdk.get_client() - scope = sentry_sdk.get_current_scope() - messages_data = ( - truncate_and_annotate_messages( - normalized_input_messages, span, scope - ) - if should_truncate_gen_ai_input(client.options) - else normalized_input_messages - ) - if messages_data is not None: - set_data_normalized( - span, - SPANDATA.GEN_AI_REQUEST_MESSAGES, - messages_data, - unpack=False, - ) - - result = f(self, *args, **kwargs) - - _set_response_attributes(span, input_messages, result, integration) - - return result - else: - with get_start_span_function()( - op=OP.GEN_AI_INVOKE_AGENT, - name=span_name, - origin=LanggraphIntegration.origin, - ) as span: - if graph_name: - span.set_data(SPANDATA.GEN_AI_PIPELINE_NAME, graph_name) - span.set_data(SPANDATA.GEN_AI_AGENT_NAME, graph_name) - - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "invoke_agent") - - # Store input messages to later compare with output - input_messages = None - if ( - len(args) > 0 - and should_send_default_pii() - and integration.include_prompts - ): - input_messages = _parse_langgraph_messages(args[0]) - if input_messages: - normalized_input_messages = normalize_message_roles( - input_messages - ) + # Store input messages to later compare with output + input_messages = None + if ( + len(args) > 0 + and should_send_default_pii() + and integration.include_prompts + ): + input_messages = _parse_langgraph_messages(args[0]) + if input_messages: + normalized_input_messages = normalize_message_roles(input_messages) - client = sentry_sdk.get_client() - scope = sentry_sdk.get_current_scope() - messages_data = ( - truncate_and_annotate_messages( - normalized_input_messages, span, scope - ) - if should_truncate_gen_ai_input(client.options) - else normalized_input_messages + client = sentry_sdk.get_client() + scope = sentry_sdk.get_current_scope() + messages_data = ( + truncate_and_annotate_messages( + normalized_input_messages, span, scope + ) + if should_truncate_gen_ai_input(client.options) + else normalized_input_messages + ) + if messages_data is not None: + set_data_normalized( + span, + SPANDATA.GEN_AI_REQUEST_MESSAGES, + messages_data, + unpack=False, ) - if messages_data is not None: - set_data_normalized( - span, - SPANDATA.GEN_AI_REQUEST_MESSAGES, - messages_data, - unpack=False, - ) - result = f(self, *args, **kwargs) + result = f(self, *args, **kwargs) - _set_response_attributes(span, input_messages, result, integration) + _set_response_attributes(span, input_messages, result, integration) - return result + return result return new_invoke @@ -285,64 +230,17 @@ async def new_ainvoke(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": f"invoke_agent {graph_name}".strip() if graph_name else "invoke_agent" ) - if has_span_streaming_enabled(client.options): - with sentry_sdk.traces.start_span( - name=span_name, - attributes={ - "sentry.op": OP.GEN_AI_INVOKE_AGENT, - "sentry.origin": LanggraphIntegration.origin, - SPANDATA.GEN_AI_OPERATION_NAME: "invoke_agent", - }, - ) as span: - if graph_name: - span.set_attribute(SPANDATA.GEN_AI_PIPELINE_NAME, graph_name) - span.set_attribute(SPANDATA.GEN_AI_AGENT_NAME, graph_name) - - input_messages = None - if ( - len(args) > 0 - and should_send_default_pii() - and integration.include_prompts - ): - input_messages = _parse_langgraph_messages(args[0]) - if input_messages: - normalized_input_messages = normalize_message_roles( - input_messages - ) - - client = sentry_sdk.get_client() - scope = sentry_sdk.get_current_scope() - messages_data = ( - truncate_and_annotate_messages( - normalized_input_messages, span, scope - ) - if should_truncate_gen_ai_input(client.options) - else normalized_input_messages - ) - if messages_data is not None: - set_data_normalized( - span, - SPANDATA.GEN_AI_REQUEST_MESSAGES, - messages_data, - unpack=False, - ) - - result = await f(self, *args, **kwargs) - - _set_response_attributes(span, input_messages, result, integration) - - return result - - with get_start_span_function()( - op=OP.GEN_AI_INVOKE_AGENT, + with sentry_sdk.traces.start_span( name=span_name, - origin=LanggraphIntegration.origin, + attributes={ + "sentry.op": OP.GEN_AI_INVOKE_AGENT, + "sentry.origin": LanggraphIntegration.origin, + SPANDATA.GEN_AI_OPERATION_NAME: "invoke_agent", + }, ) as span: if graph_name: - span.set_data(SPANDATA.GEN_AI_PIPELINE_NAME, graph_name) - span.set_data(SPANDATA.GEN_AI_AGENT_NAME, graph_name) - - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "invoke_agent") + span.set_attribute(SPANDATA.GEN_AI_PIPELINE_NAME, graph_name) + span.set_attribute(SPANDATA.GEN_AI_AGENT_NAME, graph_name) input_messages = None if ( @@ -446,18 +344,14 @@ def _set_usage_data(span: "sentry_sdk.tracing.Span", messages: "Any") -> None: output_tokens += int(token_usage.get("completion_tokens", 0)) total_tokens += int(token_usage.get("total_tokens", 0)) - set_on_span = ( - span.set_attribute if isinstance(span, StreamedSpan) else span.set_data - ) - if input_tokens > 0: - set_on_span(SPANDATA.GEN_AI_USAGE_INPUT_TOKENS, input_tokens) + span.set_attribute(SPANDATA.GEN_AI_USAGE_INPUT_TOKENS, input_tokens) if output_tokens > 0: - set_on_span(SPANDATA.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens) + span.set_attribute(SPANDATA.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens) if total_tokens > 0: - set_on_span( + span.set_attribute( SPANDATA.GEN_AI_USAGE_TOTAL_TOKENS, total_tokens, ) diff --git a/sentry_sdk/integrations/litellm.py b/sentry_sdk/integrations/litellm.py index 49ead6b068..24c9f2e238 100644 --- a/sentry_sdk/integrations/litellm.py +++ b/sentry_sdk/integrations/litellm.py @@ -5,7 +5,6 @@ from sentry_sdk import consts from sentry_sdk.ai.monitoring import record_token_usage from sentry_sdk.ai.utils import ( - get_start_span_function, set_data_normalized, transform_openai_content_part, truncate_and_annotate_embedding_inputs, @@ -14,10 +13,7 @@ from sentry_sdk.consts import SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing_utils import ( - has_span_streaming_enabled, - should_truncate_gen_ai_input, -) +from sentry_sdk.tracing_utils import should_truncate_gen_ai_input from sentry_sdk.utils import event_from_exception if TYPE_CHECKING: @@ -97,30 +93,18 @@ def _input_callback(kwargs: "Dict[str, Any]") -> None: else: operation = "chat" - # Start a new span/transaction - if has_span_streaming_enabled(client.options): - span = sentry_sdk.traces.start_span( - name=f"{operation} {model}", - attributes={ - "sentry.op": ( - consts.OP.GEN_AI_CHAT - if operation == "chat" - else consts.OP.GEN_AI_EMBEDDINGS - ), - "sentry.origin": LiteLLMIntegration.origin, - }, - ) - else: - span = get_start_span_function()( - op=( + # Start a new span + span = sentry_sdk.traces.start_span( + name=f"{operation} {model}", + attributes={ + "sentry.op": ( consts.OP.GEN_AI_CHAT if operation == "chat" else consts.OP.GEN_AI_EMBEDDINGS ), - name=f"{operation} {model}", - origin=LiteLLMIntegration.origin, - ) - span.__enter__() + "sentry.origin": LiteLLMIntegration.origin, + }, + ) _store_span(kwargs, span) diff --git a/sentry_sdk/integrations/litestar.py b/sentry_sdk/integrations/litestar.py index 8a3f09ffa0..f3885b5d35 100644 --- a/sentry_sdk/integrations/litestar.py +++ b/sentry_sdk/integrations/litestar.py @@ -13,7 +13,6 @@ 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, TransactionSource -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( ensure_integration_enabled, event_from_exception, @@ -165,104 +164,60 @@ async def _create_span_call( return await old_call(self, scope, receive, send) middleware_name = self.__class__.__name__ - if has_span_streaming_enabled(client.options): - if sentry_sdk.traces.get_current_span() is None: - return await old_call(self, scope, receive, send) - with sentry_sdk.traces.start_span( - name=middleware_name, - attributes={ - "sentry.op": OP.MIDDLEWARE_LITESTAR, - "sentry.origin": LitestarIntegration.origin, - }, - ) as middleware_span: - middleware_span.set_attribute(SPANDATA.MIDDLEWARE_NAME, middleware_name) - - # Creating spans for the "receive" callback - async def _sentry_receive( - *args: "Any", **kwargs: "Any" - ) -> "Union[HTTPReceiveMessage, WebSocketReceiveMessage]": - if client.get_integration(LitestarIntegration) is None: - return await receive(*args, **kwargs) - if sentry_sdk.traces.get_current_span() is None: - return await receive(*args, **kwargs) - with sentry_sdk.traces.start_span( - name=getattr(receive, "__qualname__", str(receive)), - attributes={ - "sentry.op": OP.MIDDLEWARE_LITESTAR_RECEIVE, - "sentry.origin": LitestarIntegration.origin, - }, - ) as span: - span.set_attribute(SPANDATA.MIDDLEWARE_NAME, middleware_name) - return await receive(*args, **kwargs) - - receive_name = getattr(receive, "__name__", str(receive)) - receive_patched = receive_name == "_sentry_receive" - new_receive = _sentry_receive if not receive_patched else receive - - # Creating spans for the "send" callback - async def _sentry_send(message: "Message") -> None: - if client.get_integration(LitestarIntegration) is None: - return await send(message) - if sentry_sdk.traces.get_current_span() is None: - return await send(message) - with sentry_sdk.traces.start_span( - name=getattr(send, "__qualname__", str(send)), - attributes={ - "sentry.op": OP.MIDDLEWARE_LITESTAR_SEND, - "sentry.origin": LitestarIntegration.origin, - }, - ) as span: - span.set_attribute(SPANDATA.MIDDLEWARE_NAME, middleware_name) - return await send(message) - - send_name = getattr(send, "__name__", str(send)) - send_patched = send_name == "_sentry_send" - new_send = _sentry_send if not send_patched else send - - return await old_call(self, scope, new_receive, new_send) - else: - with sentry_sdk.start_span( - op=OP.MIDDLEWARE_LITESTAR, - name=middleware_name, - origin=LitestarIntegration.origin, - ) as middleware_span: - middleware_span.set_tag("litestar.middleware_name", middleware_name) - - # Creating spans for the "receive" callback - async def _sentry_receive( - *args: "Any", **kwargs: "Any" - ) -> "Union[HTTPReceiveMessage, WebSocketReceiveMessage]": - if client.get_integration(LitestarIntegration) is None: - return await receive(*args, **kwargs) - with sentry_sdk.start_span( - op=OP.MIDDLEWARE_LITESTAR_RECEIVE, - name=getattr(receive, "__qualname__", str(receive)), - origin=LitestarIntegration.origin, - ) as span: - span.set_tag("litestar.middleware_name", middleware_name) - return await receive(*args, **kwargs) - - receive_name = getattr(receive, "__name__", str(receive)) - receive_patched = receive_name == "_sentry_receive" - new_receive = _sentry_receive if not receive_patched else receive - - # Creating spans for the "send" callback - async def _sentry_send(message: "Message") -> None: - if client.get_integration(LitestarIntegration) is None: - return await send(message) - with sentry_sdk.start_span( - op=OP.MIDDLEWARE_LITESTAR_SEND, - name=getattr(send, "__qualname__", str(send)), - origin=LitestarIntegration.origin, - ) as span: - span.set_tag("litestar.middleware_name", middleware_name) - return await send(message) - - send_name = getattr(send, "__name__", str(send)) - send_patched = send_name == "_sentry_send" - new_send = _sentry_send if not send_patched else send - - return await old_call(self, scope, new_receive, new_send) + if sentry_sdk.traces.get_current_span() is None: + return await old_call(self, scope, receive, send) + with sentry_sdk.traces.start_span( + name=middleware_name, + attributes={ + "sentry.op": OP.MIDDLEWARE_LITESTAR, + "sentry.origin": LitestarIntegration.origin, + }, + ) as middleware_span: + middleware_span.set_attribute(SPANDATA.MIDDLEWARE_NAME, middleware_name) + + # Creating spans for the "receive" callback + async def _sentry_receive( + *args: "Any", **kwargs: "Any" + ) -> "Union[HTTPReceiveMessage, WebSocketReceiveMessage]": + if client.get_integration(LitestarIntegration) is None: + return await receive(*args, **kwargs) + if sentry_sdk.traces.get_current_span() is None: + return await receive(*args, **kwargs) + with sentry_sdk.traces.start_span( + name=getattr(receive, "__qualname__", str(receive)), + attributes={ + "sentry.op": OP.MIDDLEWARE_LITESTAR_RECEIVE, + "sentry.origin": LitestarIntegration.origin, + }, + ) as span: + span.set_attribute(SPANDATA.MIDDLEWARE_NAME, middleware_name) + return await receive(*args, **kwargs) + + receive_name = getattr(receive, "__name__", str(receive)) + receive_patched = receive_name == "_sentry_receive" + new_receive = _sentry_receive if not receive_patched else receive + + # Creating spans for the "send" callback + async def _sentry_send(message: "Message") -> None: + if client.get_integration(LitestarIntegration) is None: + return await send(message) + if sentry_sdk.traces.get_current_span() is None: + return await send(message) + with sentry_sdk.traces.start_span( + name=getattr(send, "__qualname__", str(send)), + attributes={ + "sentry.op": OP.MIDDLEWARE_LITESTAR_SEND, + "sentry.origin": LitestarIntegration.origin, + }, + ) as span: + span.set_attribute(SPANDATA.MIDDLEWARE_NAME, middleware_name) + return await send(message) + + send_name = getattr(send, "__name__", str(send)) + send_patched = send_name == "_sentry_send" + new_send = _sentry_send if not send_patched else send + + return await old_call(self, scope, new_receive, new_send) not_yet_patched = old_call.__name__ not in ["_create_span_call"] diff --git a/sentry_sdk/integrations/mcp.py b/sentry_sdk/integrations/mcp.py index b45ec84716..f64882a47f 100644 --- a/sentry_sdk/integrations/mcp.py +++ b/sentry_sdk/integrations/mcp.py @@ -14,12 +14,11 @@ from typing import TYPE_CHECKING import sentry_sdk -from sentry_sdk.ai.utils import _set_span_data_attribute, get_start_span_function +from sentry_sdk.ai.utils import _set_span_data_attribute from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import nullcontext, package_version, safe_serialize MCP_PACKAGE_VERSION = package_version("mcp") @@ -387,27 +386,15 @@ async def _tool_handler_wrapper( # Get request ID, session ID, and transport from context request_id, session_id, mcp_transport = _get_request_context_data(ctx=ctx) - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - # Start span and execute with _active_http_scopes(ctx=ctx): - span_mgr: "Union[Span, StreamedSpan]" - if span_streaming: - span_mgr = sentry_sdk.traces.start_span( - name=f"tools/call {handler_name}", - attributes={ - "sentry.op": OP.MCP_SERVER, - "sentry.origin": MCPIntegration.origin, - }, - ) - else: - span_mgr = get_start_span_function()( - op=OP.MCP_SERVER, - name=f"tools/call {handler_name}", - origin=MCPIntegration.origin, - ) - - with span_mgr as span: + with sentry_sdk.traces.start_span( + name=f"tools/call {handler_name}", + attributes={ + "sentry.op": OP.MCP_SERVER, + "sentry.origin": MCPIntegration.origin, + }, + ) as span: # Set input span data _set_span_input_data( span, @@ -503,27 +490,15 @@ async def _prompt_handler_wrapper( # Get request ID, session ID, and transport from context request_id, session_id, mcp_transport = _get_request_context_data(ctx=ctx) - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - # Start span and execute with _active_http_scopes(ctx=ctx): - span_mgr: "Union[Span, StreamedSpan]" - if span_streaming: - span_mgr = sentry_sdk.traces.start_span( - name=f"prompts/get {handler_name}", - attributes={ - "sentry.op": OP.MCP_SERVER, - "sentry.origin": MCPIntegration.origin, - }, - ) - else: - span_mgr = get_start_span_function()( - op=OP.MCP_SERVER, - name=f"prompts/get {handler_name}", - origin=MCPIntegration.origin, - ) - - with span_mgr as span: + with sentry_sdk.traces.start_span( + name=f"prompts/get {handler_name}", + attributes={ + "sentry.op": OP.MCP_SERVER, + "sentry.origin": MCPIntegration.origin, + }, + ) as span: # Set input span data _set_span_input_data( span, @@ -673,27 +648,15 @@ async def _resource_handler_wrapper( # Get request ID, session ID, and transport from context request_id, session_id, mcp_transport = _get_request_context_data(ctx=ctx) - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - # Start span and execute with _active_http_scopes(ctx=ctx): - span_mgr: "Union[Span, StreamedSpan]" - if span_streaming: - span_mgr = sentry_sdk.traces.start_span( - name=f"resources/read {handler_name}", - attributes={ - "sentry.op": OP.MCP_SERVER, - "sentry.origin": MCPIntegration.origin, - }, - ) - else: - span_mgr = get_start_span_function()( - op=OP.MCP_SERVER, - name=f"resources/read {handler_name}", - origin=MCPIntegration.origin, - ) - - with span_mgr as span: + with sentry_sdk.traces.start_span( + name=f"resources/read {handler_name}", + attributes={ + "sentry.op": OP.MCP_SERVER, + "sentry.origin": MCPIntegration.origin, + }, + ) as span: # Set input span data _set_span_input_data( span, diff --git a/sentry_sdk/integrations/openai.py b/sentry_sdk/integrations/openai.py index 8a77668329..25a47ae19a 100644 --- a/sentry_sdk/integrations/openai.py +++ b/sentry_sdk/integrations/openai.py @@ -25,7 +25,6 @@ ) from sentry_sdk.ai.monitoring import record_token_usage from sentry_sdk.ai.utils import ( - get_start_span_function, normalize_message_roles, set_data_normalized, truncate_and_annotate_embedding_inputs, @@ -36,7 +35,6 @@ from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import StreamedSpan from sentry_sdk.tracing_utils import ( - has_span_streaming_enabled, should_truncate_gen_ai_input, ) from sentry_sdk.utils import ( @@ -739,27 +737,15 @@ def _new_sync_chat_completion(f: "Any", *args: "Any", **kwargs: "Any") -> "Any": # Same bool handling as in https://github.com/openai/openai-python/blob/acd0c54d8a68efeedde0e5b4e6c310eef1ce7867/src/openai/resources/completions.py#L585 is_streaming_response = kwargs.get("stream", False) or False - if has_span_streaming_enabled(client.options): - span = sentry_sdk.traces.start_span( - name=f"chat {model}", - attributes={ - "sentry.op": consts.OP.GEN_AI_CHAT, - "sentry.origin": OpenAIIntegration.origin, - SPANDATA.GEN_AI_SYSTEM: "openai", - SPANDATA.GEN_AI_RESPONSE_STREAMING: is_streaming_response, - }, - ) - - else: - span = get_start_span_function()( - op=consts.OP.GEN_AI_CHAT, - name=f"chat {model}", - origin=OpenAIIntegration.origin, - ) - span.__enter__() - - span.set_data(SPANDATA.GEN_AI_SYSTEM, "openai") - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, is_streaming_response) + span = sentry_sdk.traces.start_span( + name=f"chat {model}", + attributes={ + "sentry.op": consts.OP.GEN_AI_CHAT, + "sentry.origin": OpenAIIntegration.origin, + SPANDATA.GEN_AI_SYSTEM: "openai", + SPANDATA.GEN_AI_RESPONSE_STREAMING: is_streaming_response, + }, + ) _set_completions_api_input_data(span, kwargs, integration) @@ -820,26 +806,15 @@ async def _new_async_chat_completion(f: "Any", *args: "Any", **kwargs: "Any") -> # Same bool handling as in https://github.com/openai/openai-python/blob/acd0c54d8a68efeedde0e5b4e6c310eef1ce7867/src/openai/resources/completions.py#L585 is_streaming_response = kwargs.get("stream", False) or False - if has_span_streaming_enabled(client.options): - span = sentry_sdk.traces.start_span( - name=f"chat {model}", - attributes={ - "sentry.op": consts.OP.GEN_AI_CHAT, - "sentry.origin": OpenAIIntegration.origin, - SPANDATA.GEN_AI_SYSTEM: "openai", - SPANDATA.GEN_AI_RESPONSE_STREAMING: is_streaming_response, - }, - ) - else: - span = get_start_span_function()( - op=consts.OP.GEN_AI_CHAT, - name=f"chat {model}", - origin=OpenAIIntegration.origin, - ) - span.__enter__() - - span.set_data(SPANDATA.GEN_AI_SYSTEM, "openai") - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, is_streaming_response) + span = sentry_sdk.traces.start_span( + name=f"chat {model}", + attributes={ + "sentry.op": consts.OP.GEN_AI_CHAT, + "sentry.origin": OpenAIIntegration.origin, + SPANDATA.GEN_AI_SYSTEM: "openai", + SPANDATA.GEN_AI_RESPONSE_STREAMING: is_streaming_response, + }, + ) _set_completions_api_input_data(span, kwargs, integration) @@ -1237,52 +1212,29 @@ def _new_sync_embeddings_create(f: "Any", *args: "Any", **kwargs: "Any") -> "Any model = kwargs.get("model") - if has_span_streaming_enabled(client.options): - with sentry_sdk.traces.start_span( - name=f"embeddings {model}", - attributes={ - "sentry.op": consts.OP.GEN_AI_EMBEDDINGS, - "sentry.origin": OpenAIIntegration.origin, - SPANDATA.GEN_AI_SYSTEM: "openai", - }, - ) as span: - _set_embeddings_input_data(span, kwargs, integration) - - try: - response = f(*args, **kwargs) - except Exception as exc: - exc_info = sys.exc_info() - with capture_internal_exceptions(): - _capture_exception(exc) - reraise(*exc_info) - - _set_embeddings_output_data( - span, response, kwargs, integration, finish_span=False - ) + with sentry_sdk.traces.start_span( + name=f"embeddings {model}", + attributes={ + "sentry.op": consts.OP.GEN_AI_EMBEDDINGS, + "sentry.origin": OpenAIIntegration.origin, + SPANDATA.GEN_AI_SYSTEM: "openai", + }, + ) as span: + _set_embeddings_input_data(span, kwargs, integration) - return response - else: - with get_start_span_function()( - op=consts.OP.GEN_AI_EMBEDDINGS, - name=f"embeddings {model}", - origin=OpenAIIntegration.origin, - ) as span: - span.set_data(SPANDATA.GEN_AI_SYSTEM, "openai") - _set_embeddings_input_data(span, kwargs, integration) - - try: - response = f(*args, **kwargs) - except Exception as exc: - exc_info = sys.exc_info() - with capture_internal_exceptions(): - _capture_exception(exc) - reraise(*exc_info) - - _set_embeddings_output_data( - span, response, kwargs, integration, finish_span=False - ) + try: + response = f(*args, **kwargs) + except Exception as exc: + exc_info = sys.exc_info() + with capture_internal_exceptions(): + _capture_exception(exc) + reraise(*exc_info) + + _set_embeddings_output_data( + span, response, kwargs, integration, finish_span=False + ) - return response + return response async def _new_async_embeddings_create( @@ -1295,52 +1247,29 @@ async def _new_async_embeddings_create( model = kwargs.get("model") - if has_span_streaming_enabled(client.options): - with sentry_sdk.traces.start_span( - name=f"embeddings {model}", - attributes={ - "sentry.op": consts.OP.GEN_AI_EMBEDDINGS, - "sentry.origin": OpenAIIntegration.origin, - SPANDATA.GEN_AI_SYSTEM: "openai", - }, - ) as span: - _set_embeddings_input_data(span, kwargs, integration) - - try: - response = await f(*args, **kwargs) - except Exception as exc: - exc_info = sys.exc_info() - with capture_internal_exceptions(): - _capture_exception(exc) - reraise(*exc_info) - - _set_embeddings_output_data( - span, response, kwargs, integration, finish_span=False - ) + with sentry_sdk.traces.start_span( + name=f"embeddings {model}", + attributes={ + "sentry.op": consts.OP.GEN_AI_EMBEDDINGS, + "sentry.origin": OpenAIIntegration.origin, + SPANDATA.GEN_AI_SYSTEM: "openai", + }, + ) as span: + _set_embeddings_input_data(span, kwargs, integration) - return response - else: - with get_start_span_function()( - op=consts.OP.GEN_AI_EMBEDDINGS, - name=f"embeddings {model}", - origin=OpenAIIntegration.origin, - ) as span: - span.set_data(SPANDATA.GEN_AI_SYSTEM, "openai") - _set_embeddings_input_data(span, kwargs, integration) - - try: - response = await f(*args, **kwargs) - except Exception as exc: - exc_info = sys.exc_info() - with capture_internal_exceptions(): - _capture_exception(exc) - reraise(*exc_info) - - _set_embeddings_output_data( - span, response, kwargs, integration, finish_span=False - ) + try: + response = await f(*args, **kwargs) + except Exception as exc: + exc_info = sys.exc_info() + with capture_internal_exceptions(): + _capture_exception(exc) + reraise(*exc_info) + + _set_embeddings_output_data( + span, response, kwargs, integration, finish_span=False + ) - return response + return response def _wrap_embeddings_create(f: "Any") -> "Any": @@ -1378,26 +1307,15 @@ def _new_sync_responses_create(f: "Any", *args: "Any", **kwargs: "Any") -> "Any" # Same bool handling as in https://github.com/openai/openai-python/blob/acd0c54d8a68efeedde0e5b4e6c310eef1ce7867/src/openai/resources/responses/responses.py#L940 is_streaming_response = kwargs.get("stream", False) or False - if has_span_streaming_enabled(client.options): - span = sentry_sdk.traces.start_span( - name=f"responses {model}", - attributes={ - "sentry.op": consts.OP.GEN_AI_RESPONSES, - "sentry.origin": OpenAIIntegration.origin, - SPANDATA.GEN_AI_SYSTEM: "openai", - SPANDATA.GEN_AI_RESPONSE_STREAMING: is_streaming_response, - }, - ) - else: - span = get_start_span_function()( - op=consts.OP.GEN_AI_RESPONSES, - name=f"responses {model}", - origin=OpenAIIntegration.origin, - ) - span.__enter__() - - span.set_data(SPANDATA.GEN_AI_SYSTEM, "openai") - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, is_streaming_response) + span = sentry_sdk.traces.start_span( + name=f"responses {model}", + attributes={ + "sentry.op": consts.OP.GEN_AI_RESPONSES, + "sentry.origin": OpenAIIntegration.origin, + SPANDATA.GEN_AI_SYSTEM: "openai", + SPANDATA.GEN_AI_RESPONSE_STREAMING: is_streaming_response, + }, + ) _set_responses_api_input_data(span, kwargs, integration) @@ -1448,26 +1366,15 @@ async def _new_async_responses_create(f: "Any", *args: "Any", **kwargs: "Any") - # Same bool handling as in https://github.com/openai/openai-python/blob/acd0c54d8a68efeedde0e5b4e6c310eef1ce7867/src/openai/resources/responses/responses.py#L940 is_streaming_response = kwargs.get("stream", False) or False - if has_span_streaming_enabled(client.options): - span = sentry_sdk.traces.start_span( - name=f"responses {model}", - attributes={ - "sentry.op": consts.OP.GEN_AI_RESPONSES, - "sentry.origin": OpenAIIntegration.origin, - SPANDATA.GEN_AI_SYSTEM: "openai", - SPANDATA.GEN_AI_RESPONSE_STREAMING: is_streaming_response, - }, - ) - else: - span = get_start_span_function()( - op=consts.OP.GEN_AI_RESPONSES, - name=f"responses {model}", - origin=OpenAIIntegration.origin, - ) - span.__enter__() - - span.set_data(SPANDATA.GEN_AI_SYSTEM, "openai") - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, is_streaming_response) + span = sentry_sdk.traces.start_span( + name=f"responses {model}", + attributes={ + "sentry.op": consts.OP.GEN_AI_RESPONSES, + "sentry.origin": OpenAIIntegration.origin, + SPANDATA.GEN_AI_SYSTEM: "openai", + SPANDATA.GEN_AI_RESPONSE_STREAMING: is_streaming_response, + }, + ) _set_responses_api_input_data(span, kwargs, integration) diff --git a/sentry_sdk/integrations/openai_agents/patches/error_tracing.py b/sentry_sdk/integrations/openai_agents/patches/error_tracing.py index 68dadb3101..ef7e05924f 100644 --- a/sentry_sdk/integrations/openai_agents/patches/error_tracing.py +++ b/sentry_sdk/integrations/openai_agents/patches/error_tracing.py @@ -2,9 +2,7 @@ from typing import TYPE_CHECKING import sentry_sdk -from sentry_sdk.consts import SPANSTATUS from sentry_sdk.traces import SpanStatus -from sentry_sdk.tracing_utils import has_span_streaming_enabled if TYPE_CHECKING: from typing import Any @@ -56,15 +54,9 @@ def sentry_attach_error_to_current_span( the agents library swallows exceptions. """ # Set the current Sentry span to errored - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - current_span = sentry_sdk.get_current_scope().streamed_span - if current_span is not None: - current_span.status = SpanStatus.ERROR - else: - current_span = sentry_sdk.get_current_span() - if current_span is not None: - current_span.set_status(SPANSTATUS.INTERNAL_ERROR) + current_span = sentry_sdk.get_current_scope().streamed_span + if current_span is not None: + current_span.status = SpanStatus.ERROR # Call the original function return original_attach_error(error, *args, **kwargs) diff --git a/sentry_sdk/integrations/openai_agents/spans/agent_workflow.py b/sentry_sdk/integrations/openai_agents/spans/agent_workflow.py index 758f06db8d..549449a01f 100644 --- a/sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +++ b/sentry_sdk/integrations/openai_agents/spans/agent_workflow.py @@ -1,32 +1,19 @@ from typing import TYPE_CHECKING import sentry_sdk -from sentry_sdk.ai.utils import get_start_span_function -from sentry_sdk.tracing_utils import has_span_streaming_enabled from ..consts import SPAN_ORIGIN if TYPE_CHECKING: - from typing import Union - import agents def agent_workflow_span( agent: "agents.Agent", -) -> "Union[sentry_sdk.tracing.Span, sentry_sdk.traces.StreamedSpan]": +) -> "sentry_sdk.traces.StreamedSpan": # Create a transaction or a span if an transaction is already active - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - span = sentry_sdk.traces.start_span( - name=f"{agent.name} workflow", attributes={"sentry.origin": SPAN_ORIGIN} - ) - - return span - - span = get_start_span_function()( - name=f"{agent.name} workflow", - origin=SPAN_ORIGIN, + span = sentry_sdk.traces.start_span( + name=f"{agent.name} workflow", attributes={"sentry.origin": SPAN_ORIGIN} ) return span diff --git a/sentry_sdk/integrations/openai_agents/spans/ai_client.py b/sentry_sdk/integrations/openai_agents/spans/ai_client.py index f4f02cb674..6bd56608bf 100644 --- a/sentry_sdk/integrations/openai_agents/spans/ai_client.py +++ b/sentry_sdk/integrations/openai_agents/spans/ai_client.py @@ -3,7 +3,6 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing_utils import has_span_streaming_enabled from ..consts import SPAN_ORIGIN from ..utils import ( @@ -14,14 +13,14 @@ ) if TYPE_CHECKING: - from typing import Any, Optional, Union + from typing import Any, Optional from agents import Agent def ai_client_span( agent: "Agent", get_response_kwargs: "dict[str, Any]" -) -> "Union[sentry_sdk.tracing.Span, StreamedSpan]": +) -> "StreamedSpan": # TODO-anton: implement other types of operations. Now "chat" is hardcoded. # Get model name from agent.model or fall back to request model (for when agent.model is None/default) model_name = None @@ -30,24 +29,14 @@ def ai_client_span( elif hasattr(agent, "_sentry_request_model"): model_name = agent._sentry_request_model - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - span = sentry_sdk.traces.start_span( - name=f"chat {model_name}", - attributes={ - "sentry.op": OP.GEN_AI_CHAT, - "sentry.origin": SPAN_ORIGIN, - SPANDATA.GEN_AI_OPERATION_NAME: "chat", - }, - ) - else: - span = sentry_sdk.start_span( - op=OP.GEN_AI_CHAT, - name=f"chat {model_name}", - origin=SPAN_ORIGIN, - ) - # TODO-anton: remove hardcoded stuff and replace something that also works for embedding and so on - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "chat") + span = sentry_sdk.traces.start_span( + name=f"chat {model_name}", + attributes={ + "sentry.op": OP.GEN_AI_CHAT, + "sentry.origin": SPAN_ORIGIN, + SPANDATA.GEN_AI_OPERATION_NAME: "chat", + }, + ) _set_agent_data(span, agent) _set_input_data(span, get_response_kwargs) @@ -56,7 +45,7 @@ def ai_client_span( def update_ai_client_span( - span: "Union[sentry_sdk.tracing.Span, StreamedSpan]", + span: "StreamedSpan", response: "Any", response_model: "Optional[str]" = None, agent: "Optional[Agent]" = None, @@ -68,17 +57,13 @@ def update_ai_client_span( if hasattr(response, "output") and response.output: _set_output_data(span, response) - set_on_span = ( - span.set_attribute if isinstance(span, StreamedSpan) else span.set_data - ) - if response_model is not None: - set_on_span(SPANDATA.GEN_AI_RESPONSE_MODEL, response_model) + span.set_attribute(SPANDATA.GEN_AI_RESPONSE_MODEL, response_model) elif hasattr(response, "model") and response.model: - set_on_span(SPANDATA.GEN_AI_RESPONSE_MODEL, str(response.model)) + span.set_attribute(SPANDATA.GEN_AI_RESPONSE_MODEL, str(response.model)) # Set conversation ID from agent if available if agent: conv_id = getattr(agent, "_sentry_conversation_id", None) if conv_id: - set_on_span(SPANDATA.GEN_AI_CONVERSATION_ID, conv_id) + span.set_attribute(SPANDATA.GEN_AI_CONVERSATION_ID, conv_id) diff --git a/sentry_sdk/integrations/openai_agents/spans/execute_tool.py b/sentry_sdk/integrations/openai_agents/spans/execute_tool.py index fd3a430951..3fe8c1fb0b 100644 --- a/sentry_sdk/integrations/openai_agents/spans/execute_tool.py +++ b/sentry_sdk/integrations/openai_agents/spans/execute_tool.py @@ -1,60 +1,42 @@ from typing import TYPE_CHECKING import sentry_sdk -from sentry_sdk.consts import OP, SPANDATA, SPANSTATUS +from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import SpanStatus, StreamedSpan -from sentry_sdk.tracing_utils import has_span_streaming_enabled from ..consts import SPAN_ORIGIN from ..utils import _set_agent_data if TYPE_CHECKING: - from typing import Any, Union + from typing import Any import agents def execute_tool_span( tool: "agents.Tool", *args: "Any", **kwargs: "Any" -) -> "Union[sentry_sdk.tracing.Span, StreamedSpan]": - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - span = sentry_sdk.traces.start_span( - name=f"execute_tool {tool.name}", - attributes={ - "sentry.op": OP.GEN_AI_EXECUTE_TOOL, - "sentry.origin": SPAN_ORIGIN, - SPANDATA.GEN_AI_OPERATION_NAME: "execute_tool", - SPANDATA.GEN_AI_TOOL_NAME: tool.name, - SPANDATA.GEN_AI_TOOL_DESCRIPTION: tool.description, - }, - ) - - set_on_span = span.set_attribute - else: - span = sentry_sdk.start_span( - op=OP.GEN_AI_EXECUTE_TOOL, - name=f"execute_tool {tool.name}", - origin=SPAN_ORIGIN, - ) - - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "execute_tool") - - span.set_data(SPANDATA.GEN_AI_TOOL_NAME, tool.name) - span.set_data(SPANDATA.GEN_AI_TOOL_DESCRIPTION, tool.description) - - set_on_span = span.set_data +) -> "StreamedSpan": + span = sentry_sdk.traces.start_span( + name=f"execute_tool {tool.name}", + attributes={ + "sentry.op": OP.GEN_AI_EXECUTE_TOOL, + "sentry.origin": SPAN_ORIGIN, + SPANDATA.GEN_AI_OPERATION_NAME: "execute_tool", + SPANDATA.GEN_AI_TOOL_NAME: tool.name, + SPANDATA.GEN_AI_TOOL_DESCRIPTION: tool.description, + }, + ) if should_send_default_pii(): input = args[1] - set_on_span(SPANDATA.GEN_AI_TOOL_INPUT, input) + span.set_attribute(SPANDATA.GEN_AI_TOOL_INPUT, input) return span def update_execute_tool_span( - span: "Union[sentry_sdk.tracing.Span, StreamedSpan]", + span: "StreamedSpan", agent: "agents.Agent", tool: "agents.Tool", result: "Any", @@ -64,19 +46,12 @@ def update_execute_tool_span( if isinstance(result, str) and result.startswith( "An error occurred while running the tool" ): - if isinstance(span, StreamedSpan): - span.status = SpanStatus.ERROR - else: - span.set_status(SPANSTATUS.INTERNAL_ERROR) - - set_on_span = ( - span.set_attribute if isinstance(span, StreamedSpan) else span.set_data - ) + span.status = SpanStatus.ERROR if should_send_default_pii(): - set_on_span(SPANDATA.GEN_AI_TOOL_OUTPUT, result) + span.set_attribute(SPANDATA.GEN_AI_TOOL_OUTPUT, result) # Add conversation ID from agent conv_id = getattr(agent, "_sentry_conversation_id", None) if conv_id: - set_on_span(SPANDATA.GEN_AI_CONVERSATION_ID, conv_id) + span.set_attribute(SPANDATA.GEN_AI_CONVERSATION_ID, conv_id) diff --git a/sentry_sdk/integrations/openai_agents/spans/handoff.py b/sentry_sdk/integrations/openai_agents/spans/handoff.py index ea91464afb..9fa48b431d 100644 --- a/sentry_sdk/integrations/openai_agents/spans/handoff.py +++ b/sentry_sdk/integrations/openai_agents/spans/handoff.py @@ -2,7 +2,6 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA -from sentry_sdk.tracing_utils import has_span_streaming_enabled from ..consts import SPAN_ORIGIN @@ -13,29 +12,15 @@ def handoff_span( context: "agents.RunContextWrapper", from_agent: "agents.Agent", to_agent_name: str ) -> None: - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - with sentry_sdk.traces.start_span( - name=f"handoff from {from_agent.name} to {to_agent_name}", - attributes={ - "sentry.op": OP.GEN_AI_HANDOFF, - "sentry.origin": SPAN_ORIGIN, - SPANDATA.GEN_AI_OPERATION_NAME: "handoff", - }, - ) as span: - # Add conversation ID from agent - conv_id = getattr(from_agent, "_sentry_conversation_id", None) - if conv_id: - span.set_attribute(SPANDATA.GEN_AI_CONVERSATION_ID, conv_id) - else: - with sentry_sdk.start_span( - op=OP.GEN_AI_HANDOFF, - name=f"handoff from {from_agent.name} to {to_agent_name}", - origin=SPAN_ORIGIN, - ) as span: - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "handoff") - - # Add conversation ID from agent - conv_id = getattr(from_agent, "_sentry_conversation_id", None) - if conv_id: - span.set_data(SPANDATA.GEN_AI_CONVERSATION_ID, conv_id) + with sentry_sdk.traces.start_span( + name=f"handoff from {from_agent.name} to {to_agent_name}", + attributes={ + "sentry.op": OP.GEN_AI_HANDOFF, + "sentry.origin": SPAN_ORIGIN, + SPANDATA.GEN_AI_OPERATION_NAME: "handoff", + }, + ) as span: + # Add conversation ID from agent + conv_id = getattr(from_agent, "_sentry_conversation_id", None) + if conv_id: + span.set_attribute(SPANDATA.GEN_AI_CONVERSATION_ID, conv_id) diff --git a/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py b/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py index c21145ac4a..c059744b49 100644 --- a/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +++ b/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py @@ -2,7 +2,6 @@ import sentry_sdk from sentry_sdk.ai.utils import ( - get_start_span_function, normalize_message_roles, set_data_normalized, truncate_and_annotate_messages, @@ -10,44 +9,29 @@ from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing_utils import ( - has_span_streaming_enabled, - should_truncate_gen_ai_input, -) +from sentry_sdk.tracing_utils import should_truncate_gen_ai_input from sentry_sdk.utils import safe_serialize from ..consts import SPAN_ORIGIN from ..utils import _set_agent_data, _set_usage_data if TYPE_CHECKING: - from typing import Any, Union + from typing import Any import agents def invoke_agent_span( context: "agents.RunContextWrapper", agent: "agents.Agent", kwargs: "dict[str, Any]" -) -> "Union[sentry_sdk.tracing.Span, StreamedSpan]": - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - span = sentry_sdk.traces.start_span( - name=f"invoke_agent {agent.name}", - attributes={ - "sentry.op": OP.GEN_AI_INVOKE_AGENT, - "sentry.origin": SPAN_ORIGIN, - SPANDATA.GEN_AI_OPERATION_NAME: "invoke_agent", - }, - ) - else: - start_span_function = get_start_span_function() - span = start_span_function( - op=OP.GEN_AI_INVOKE_AGENT, - name=f"invoke_agent {agent.name}", - origin=SPAN_ORIGIN, - ) - span.__enter__() - - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "invoke_agent") +) -> "StreamedSpan": + span = sentry_sdk.traces.start_span( + name=f"invoke_agent {agent.name}", + attributes={ + "sentry.op": OP.GEN_AI_INVOKE_AGENT, + "sentry.origin": SPAN_ORIGIN, + SPANDATA.GEN_AI_OPERATION_NAME: "invoke_agent", + }, + ) if should_send_default_pii(): messages = [] @@ -101,7 +85,7 @@ def invoke_agent_span( def update_invoke_agent_span( - span: "Union[sentry_sdk.tracing.Span, StreamedSpan]", + span: "StreamedSpan", context: "agents.RunContextWrapper", agent: "agents.Agent", output: "Any" = None, @@ -116,7 +100,4 @@ def update_invoke_agent_span( # Add conversation ID from agent conv_id = getattr(agent, "_sentry_conversation_id", None) if conv_id: - if isinstance(span, StreamedSpan): - span.set_attribute(SPANDATA.GEN_AI_CONVERSATION_ID, conv_id) - else: - span.set_data(SPANDATA.GEN_AI_CONVERSATION_ID, conv_id) + span.set_attribute(SPANDATA.GEN_AI_CONVERSATION_ID, conv_id) diff --git a/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py b/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py index 27deb0c55c..b12f7a6ff7 100644 --- a/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py +++ b/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py @@ -9,10 +9,7 @@ ) from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing_utils import ( - has_span_streaming_enabled, - should_truncate_gen_ai_input, -) +from sentry_sdk.tracing_utils import should_truncate_gen_ai_input from sentry_sdk.utils import safe_serialize from ..consts import SPAN_ORIGIN @@ -32,7 +29,7 @@ ) if TYPE_CHECKING: - from typing import Any, Dict, List, Union + from typing import Any, Dict, List from pydantic_ai.messages import ModelMessage, SystemPromptPart # type: ignore @@ -102,9 +99,7 @@ def _get_system_instructions( return permanent_instructions, current_instructions -def _set_input_messages( - span: "Union[sentry_sdk.tracing.Span, StreamedSpan]", messages: "Any" -) -> None: +def _set_input_messages(span: "StreamedSpan", messages: "Any") -> None: """Set input messages data on a span.""" if not _should_send_prompts(): return @@ -114,24 +109,14 @@ def _set_input_messages( permanent_instructions, current_instructions = _get_system_instructions(messages) if len(permanent_instructions) > 0 or len(current_instructions) > 0: - if isinstance(span, StreamedSpan): - span.set_attribute( - SPANDATA.GEN_AI_SYSTEM_INSTRUCTIONS, - json.dumps( - _transform_system_instructions( - permanent_instructions, current_instructions - ) - ), - ) - else: - span.set_data( - SPANDATA.GEN_AI_SYSTEM_INSTRUCTIONS, - json.dumps( - _transform_system_instructions( - permanent_instructions, current_instructions - ) - ), - ) + span.set_attribute( + SPANDATA.GEN_AI_SYSTEM_INSTRUCTIONS, + json.dumps( + _transform_system_instructions( + permanent_instructions, current_instructions + ) + ), + ) try: formatted_messages = [] @@ -215,9 +200,7 @@ def _set_input_messages( pass -def _set_output_data( - span: "Union[sentry_sdk.tracing.Span, StreamedSpan]", response: "Any" -) -> None: +def _set_output_data(span: "StreamedSpan", response: "Any") -> None: """Set output data on a span.""" if not _should_send_prompts(): return @@ -225,10 +208,7 @@ def _set_output_data( if not response: return - set_on_span = ( - span.set_attribute if isinstance(span, StreamedSpan) else span.set_data - ) - set_on_span(SPANDATA.GEN_AI_RESPONSE_MODEL, response.model_name) + span.set_attribute(SPANDATA.GEN_AI_RESPONSE_MODEL, response.model_name) try: # Extract text from ModelResponse @@ -253,7 +233,7 @@ def _set_output_data( set_data_normalized(span, SPANDATA.GEN_AI_RESPONSE_TEXT, texts) if tool_calls: - set_on_span( + span.set_attribute( SPANDATA.GEN_AI_RESPONSE_TOOL_CALLS, safe_serialize(tool_calls) ) @@ -264,7 +244,7 @@ def _set_output_data( def ai_client_span( messages: "Any", agent: "Any", model: "Any", model_settings: "Any" -) -> "Union[sentry_sdk.tracing.Span, StreamedSpan]": +) -> "StreamedSpan": """Create a span for an AI client call (model request). Args: @@ -280,27 +260,15 @@ def ai_client_span( model_name = _get_model_name(model_obj) or "unknown" - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - span = sentry_sdk.traces.start_span( - name=f"chat {model_name}", - attributes={ - "sentry.op": OP.GEN_AI_CHAT, - "sentry.origin": SPAN_ORIGIN, - SPANDATA.GEN_AI_OPERATION_NAME: "chat", - SPANDATA.GEN_AI_RESPONSE_STREAMING: get_is_streaming(), - }, - ) - else: - span = sentry_sdk.start_span( - op=OP.GEN_AI_CHAT, - name=f"chat {model_name}", - origin=SPAN_ORIGIN, - ) - - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "chat") - # Set streaming flag from contextvar - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, get_is_streaming()) + span = sentry_sdk.traces.start_span( + name=f"chat {model_name}", + attributes={ + "sentry.op": OP.GEN_AI_CHAT, + "sentry.origin": SPAN_ORIGIN, + SPANDATA.GEN_AI_OPERATION_NAME: "chat", + SPANDATA.GEN_AI_RESPONSE_STREAMING: get_is_streaming(), + }, + ) _set_agent_data(span, agent) _set_model_data(span, model, model_settings) @@ -316,9 +284,7 @@ def ai_client_span( return span -def update_ai_client_span( - span: "Union[sentry_sdk.tracing.Span, StreamedSpan]", model_response: "Any" -) -> None: +def update_ai_client_span(span: "StreamedSpan", model_response: "Any") -> None: """Update the AI client span with response data.""" if not span: return diff --git a/sentry_sdk/integrations/pydantic_ai/spans/execute_tool.py b/sentry_sdk/integrations/pydantic_ai/spans/execute_tool.py index 7648c1418a..ee9a7e1c42 100644 --- a/sentry_sdk/integrations/pydantic_ai/spans/execute_tool.py +++ b/sentry_sdk/integrations/pydantic_ai/spans/execute_tool.py @@ -3,14 +3,13 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import safe_serialize from ..consts import SPAN_ORIGIN from ..utils import _set_agent_data, _should_send_prompts if TYPE_CHECKING: - from typing import Any, Optional, Union + from typing import Any, Optional from pydantic_ai._tool_manager import ToolDefinition # type: ignore @@ -20,7 +19,7 @@ def execute_tool_span( tool_args: "Any", agent: "Any", tool_definition: "Optional[ToolDefinition]" = None, -) -> "Union[sentry_sdk.tracing.Span, StreamedSpan]": +) -> "StreamedSpan": """Create a span for tool execution. Args: @@ -29,33 +28,18 @@ def execute_tool_span( agent: The agent executing the tool tool_definition: The definition of the tool, if available """ - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - span = sentry_sdk.traces.start_span( - name=f"execute_tool {tool_name}", - attributes={ - "sentry.op": OP.GEN_AI_EXECUTE_TOOL, - "sentry.origin": SPAN_ORIGIN, - SPANDATA.GEN_AI_OPERATION_NAME: "execute_tool", - SPANDATA.GEN_AI_TOOL_NAME: tool_name, - }, - ) - - set_on_span = span.set_attribute - else: - span = sentry_sdk.start_span( - op=OP.GEN_AI_EXECUTE_TOOL, - name=f"execute_tool {tool_name}", - origin=SPAN_ORIGIN, - ) - - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "execute_tool") - span.set_data(SPANDATA.GEN_AI_TOOL_NAME, tool_name) - - set_on_span = span.set_data + span = sentry_sdk.traces.start_span( + name=f"execute_tool {tool_name}", + attributes={ + "sentry.op": OP.GEN_AI_EXECUTE_TOOL, + "sentry.origin": SPAN_ORIGIN, + SPANDATA.GEN_AI_OPERATION_NAME: "execute_tool", + SPANDATA.GEN_AI_TOOL_NAME: tool_name, + }, + ) if tool_definition is not None and hasattr(tool_definition, "description"): - set_on_span( + span.set_attribute( SPANDATA.GEN_AI_TOOL_DESCRIPTION, tool_definition.description, ) @@ -63,14 +47,12 @@ def execute_tool_span( _set_agent_data(span, agent) if _should_send_prompts() and tool_args is not None: - set_on_span(SPANDATA.GEN_AI_TOOL_INPUT, safe_serialize(tool_args)) + span.set_attribute(SPANDATA.GEN_AI_TOOL_INPUT, safe_serialize(tool_args)) return span -def update_execute_tool_span( - span: "Union[sentry_sdk.tracing.Span, StreamedSpan]", result: "Any" -) -> None: +def update_execute_tool_span(span: "StreamedSpan", result: "Any") -> None: """Update the execute tool span with the result.""" if not span: return @@ -78,7 +60,4 @@ def update_execute_tool_span( if not _should_send_prompts() or result is None: return - if isinstance(span, StreamedSpan): - span.set_attribute(SPANDATA.GEN_AI_TOOL_OUTPUT, safe_serialize(result)) - else: - span.set_data(SPANDATA.GEN_AI_TOOL_OUTPUT, safe_serialize(result)) + span.set_attribute(SPANDATA.GEN_AI_TOOL_OUTPUT, safe_serialize(result)) diff --git a/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py b/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py index f0c68e85ba..312899e5c6 100644 --- a/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py +++ b/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py @@ -2,17 +2,13 @@ import sentry_sdk from sentry_sdk.ai.utils import ( - get_start_span_function, normalize_message_roles, set_data_normalized, truncate_and_annotate_messages, ) from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing_utils import ( - has_span_streaming_enabled, - should_truncate_gen_ai_input, -) +from sentry_sdk.tracing_utils import should_truncate_gen_ai_input from ..consts import SPAN_ORIGIN from ..utils import ( @@ -49,24 +45,14 @@ def invoke_agent_span( if agent and getattr(agent, "name", None): name = agent.name - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - span = sentry_sdk.traces.start_span( - name=f"invoke_agent {name}", - attributes={ - "sentry.op": OP.GEN_AI_INVOKE_AGENT, - "sentry.origin": SPAN_ORIGIN, - SPANDATA.GEN_AI_OPERATION_NAME: "invoke_agent", - }, - ) - else: - span = get_start_span_function()( - op=OP.GEN_AI_INVOKE_AGENT, - name=f"invoke_agent {name}", - origin=SPAN_ORIGIN, - ) - - span.set_data(SPANDATA.GEN_AI_OPERATION_NAME, "invoke_agent") + span = sentry_sdk.traces.start_span( + name=f"invoke_agent {name}", + attributes={ + "sentry.op": OP.GEN_AI_INVOKE_AGENT, + "sentry.origin": SPAN_ORIGIN, + SPANDATA.GEN_AI_OPERATION_NAME: "invoke_agent", + }, + ) _set_agent_data(span, agent) _set_model_data(span, model, model_settings) @@ -173,12 +159,7 @@ def update_invoke_agent_span( try: response = result.response if hasattr(response, "model_name") and response.model_name: - if isinstance(span, StreamedSpan): - span.set_attribute( - SPANDATA.GEN_AI_RESPONSE_MODEL, response.model_name - ) - else: - span.set_data(SPANDATA.GEN_AI_RESPONSE_MODEL, response.model_name) + span.set_attribute(SPANDATA.GEN_AI_RESPONSE_MODEL, response.model_name) except Exception: # If response access fails, continue without setting model name pass diff --git a/sentry_sdk/integrations/pymongo.py b/sentry_sdk/integrations/pymongo.py index 9f6401152d..459d4a08eb 100644 --- a/sentry_sdk/integrations/pymongo.py +++ b/sentry_sdk/integrations/pymongo.py @@ -2,12 +2,10 @@ import json import sentry_sdk -from sentry_sdk.consts import OP, SPANDATA, SPANSTATUS +from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import SpanStatus, StreamedSpan -from sentry_sdk.tracing import Span -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import capture_internal_exceptions try: @@ -18,7 +16,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from typing import Any, Dict, Union + from typing import Any, Dict from pymongo.monitoring import ( CommandFailedEvent, @@ -89,9 +87,6 @@ def _strip_pii(command: "Dict[str, Any]") -> "Dict[str, Any]": def _get_db_data(event: "Any") -> "Dict[str, Any]": data = {} - client = sentry_sdk.get_client() - is_span_streaming_enabled = has_span_streaming_enabled(client.options) - data[SPANDATA.DB_DRIVER_NAME] = "pymongo" db_name = event.database_name @@ -103,27 +98,21 @@ def _get_db_data(event: "Any") -> "Dict[str, Any]": if server_port is not None: data[SPANDATA.SERVER_PORT] = server_port - if is_span_streaming_enabled: - data["db.system.name"] = "mongodb" - - if db_name is not None: - data["db.namespace"] = db_name - else: - data[SPANDATA.DB_SYSTEM] = "mongodb" + data["db.system.name"] = "mongodb" - if db_name is not None: - data[SPANDATA.DB_NAME] = db_name + if db_name is not None: + data["db.namespace"] = db_name return data class CommandTracer(monitoring.CommandListener): def __init__(self) -> None: - self._ongoing_operations: "Dict[int, Union[Span, StreamedSpan]]" = {} + self._ongoing_operations: "Dict[int, StreamedSpan]" = {} def _operation_key( self, - event: "Union[CommandFailedEvent, CommandStartedEvent, CommandSucceededEvent]", + event: "CommandFailedEvent | CommandStartedEvent | CommandSucceededEvent", ) -> int: return event.request_id @@ -143,88 +132,34 @@ def started(self, event: "CommandStartedEvent") -> None: collection_name = command.get(event.command_name) operation_name = event.command_name - db_name = event.database_name - lsid = command.pop("lsid", None) + command.pop("lsid", None) if not should_send_default_pii(): command = _strip_pii(command) query = json.dumps(command, default=str) - if has_span_streaming_enabled(client.options): - span_first_data = { - "db.operation.name": operation_name, - "db.collection.name": collection_name, - SPANDATA.DB_QUERY_TEXT: query, - "sentry.op": OP.DB, - "sentry.origin": PyMongoIntegration.origin, - **db_data, - } - - with capture_internal_exceptions(): - sentry_sdk.add_breadcrumb( - message=query, - category="query", - type=OP.DB, - data=span_first_data, - ) - - if sentry_sdk.traces.get_current_span() is None: - return - - span = sentry_sdk.traces.start_span( - name=query, attributes=span_first_data + span_first_data = { + "db.operation.name": operation_name, + "db.collection.name": collection_name, + SPANDATA.DB_QUERY_TEXT: query, + "sentry.op": OP.DB, + "sentry.origin": PyMongoIntegration.origin, + **db_data, + } + + with capture_internal_exceptions(): + sentry_sdk.add_breadcrumb( + message=query, + category="query", + type=OP.DB, + data=span_first_data, ) - else: - tags = { - "db.name": db_name, - SPANDATA.DB_SYSTEM: "mongodb", - SPANDATA.DB_DRIVER_NAME: "pymongo", - SPANDATA.DB_OPERATION: operation_name, - # The below is a deprecated field, but leaving for legacy reasons. - # The v2 spans will use `db.collection.name` instead. - SPANDATA.DB_MONGODB_COLLECTION: collection_name, - } - - try: - tags["net.peer.name"] = event.connection_id[0] - tags["net.peer.port"] = str(event.connection_id[1]) - except TypeError: - pass - - data: "Dict[str, Any]" = {"operation_ids": {}} - data["operation_ids"]["operation"] = event.operation_id - data["operation_ids"]["request"] = event.request_id - - data.update(db_data) - - try: - if lsid: - lsid_id = lsid["id"] - data["operation_ids"]["session"] = str(lsid_id) - except KeyError: - pass - - span = sentry_sdk.start_span( - op=OP.DB, - name=query, - origin=PyMongoIntegration.origin, - ) - - for tag, value in tags.items(): - # set the tag for backwards-compatibility. - # TODO: remove the set_tag call in the next major release! - span.set_tag(tag, value) - span.set_data(tag, value) - - for key, value in data.items(): - span.set_data(key, value) + if sentry_sdk.traces.get_current_span() is None: + return - with capture_internal_exceptions(): - sentry_sdk.add_breadcrumb( - message=query, category="query", type=OP.DB, data=tags - ) + span = sentry_sdk.traces.start_span(name=query, attributes=span_first_data) self._ongoing_operations[self._operation_key(event)] = span.__enter__() @@ -237,8 +172,6 @@ def failed(self, event: "CommandFailedEvent") -> None: # Ignoring NoOpStreamedSpan as it will always have a status of "ok" if type(span) is StreamedSpan: span.status = SpanStatus.ERROR - elif type(span) is Span: - span.set_status(SPANSTATUS.INTERNAL_ERROR) span.__exit__(None, None, None) except KeyError: return @@ -249,8 +182,6 @@ def succeeded(self, event: "CommandSucceededEvent") -> None: try: span = self._ongoing_operations.pop(self._operation_key(event)) - if type(span) is Span: - span.set_status(SPANSTATUS.OK) span.__exit__(None, None, None) except KeyError: pass diff --git a/sentry_sdk/integrations/pyramid.py b/sentry_sdk/integrations/pyramid.py index 5ab6ef90e9..acc2d4b664 100644 --- a/sentry_sdk/integrations/pyramid.py +++ b/sentry_sdk/integrations/pyramid.py @@ -9,8 +9,6 @@ from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import SOURCE_FOR_STYLE as SEGMENT_SOURCE_FOR_STYLE -from sentry_sdk.tracing import SOURCE_FOR_STYLE as TRANSACTION_SOURCE_FOR_STYLE -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -87,16 +85,15 @@ def sentry_patched_call_view( scope = sentry_sdk.get_isolation_scope() - if has_span_streaming_enabled(client.options): - if has_data_collection_enabled(client.options): - if client.options["data_collection"]["user_info"]: - user_id = authenticated_userid(request) - if user_id: - scope.set_user({"id": user_id}) - elif should_send_default_pii(): + if has_data_collection_enabled(client.options): + if client.options["data_collection"]["user_info"]: user_id = authenticated_userid(request) if user_id: scope.set_user({"id": user_id}) + elif should_send_default_pii(): + user_id = authenticated_userid(request) + if user_id: + scope.set_user({"id": user_id}) scope.add_event_processor( _make_event_processor(weakref.ref(request), integration) @@ -174,14 +171,7 @@ def _set_transaction_name_and_source( "route_name": request.matched_route.name, "route_pattern": request.matched_route.pattern, } - is_span_streaming_enabled = has_span_streaming_enabled( - sentry_sdk.get_client().options - ) - source = ( - SEGMENT_SOURCE_FOR_STYLE[transaction_style] - if is_span_streaming_enabled - else TRANSACTION_SOURCE_FOR_STYLE[transaction_style] - ) + source = SEGMENT_SOURCE_FOR_STYLE[transaction_style] scope.set_transaction_name( name_for_style[transaction_style], source=source, diff --git a/sentry_sdk/integrations/pyreqwest.py b/sentry_sdk/integrations/pyreqwest.py index d25d03f470..2614d70775 100644 --- a/sentry_sdk/integrations/pyreqwest.py +++ b/sentry_sdk/integrations/pyreqwest.py @@ -2,23 +2,16 @@ from typing import Any, Generator import sentry_sdk -from sentry_sdk import start_span from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing import BAGGAGE_HEADER_NAME from sentry_sdk.tracing_utils import ( add_http_request_source, - add_sentry_baggage_to_headers, - has_span_streaming_enabled, propagate_trace_headers, - should_propagate_trace, ) from sentry_sdk.utils import ( SENSITIVE_DATA_SUBSTITUTE, capture_internal_exceptions, - logger, parse_url, ) @@ -87,67 +80,31 @@ def _sentry_pyreqwest_span(request: "Request") -> "Generator[Any, None, None]": with capture_internal_exceptions(): parsed_url = parse_url(str(request.url), sanitize=False) - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - propagate_trace_headers(client=sentry_sdk.get_client(), request=request) - yield None - return - - with sentry_sdk.traces.start_span( - name=f"{request.method} {parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE}", - attributes={ - "sentry.op": OP.HTTP_CLIENT, - "sentry.origin": PyreqwestIntegration.origin, - SPANDATA.HTTP_REQUEST_METHOD: request.method, - }, - ) as span: - if parsed_url is not None and should_send_default_pii(): - span.set_attribute(SPANDATA.URL_FULL, parsed_url.url) - span.set_attribute(SPANDATA.URL_QUERY, parsed_url.query) - span.set_attribute(SPANDATA.URL_FRAGMENT, parsed_url.fragment) - - propagate_trace_headers(client=sentry_sdk.get_client(), request=request) - - yield span - - if span is not None: - with capture_internal_exceptions(): - add_http_request_source(span) - - return - - with start_span( - op=OP.HTTP_CLIENT, + if sentry_sdk.traces.get_current_span() is None: + propagate_trace_headers(client=sentry_sdk.get_client(), request=request) + yield None + return + + with sentry_sdk.traces.start_span( name=f"{request.method} {parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE}", - origin=PyreqwestIntegration.origin, + attributes={ + "sentry.op": OP.HTTP_CLIENT, + "sentry.origin": PyreqwestIntegration.origin, + SPANDATA.HTTP_REQUEST_METHOD: request.method, + }, ) as span: - span.set_data(SPANDATA.HTTP_METHOD, request.method) - if parsed_url is not None: - span.set_data("url", parsed_url.url) - span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) - span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) - - if should_propagate_trace(sentry_sdk.get_client(), str(request.url)): - for ( - key, - value, - ) in sentry_sdk.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 - ) - ) - - if key == BAGGAGE_HEADER_NAME: - add_sentry_baggage_to_headers(request.headers, value) - else: - request.headers[key] = value + if parsed_url is not None and should_send_default_pii(): + span.set_attribute(SPANDATA.URL_FULL, parsed_url.url) + span.set_attribute(SPANDATA.URL_QUERY, parsed_url.query) + span.set_attribute(SPANDATA.URL_FRAGMENT, parsed_url.fragment) + + propagate_trace_headers(client=sentry_sdk.get_client(), request=request) yield span - with capture_internal_exceptions(): - add_http_request_source(span) + if span is not None: + with capture_internal_exceptions(): + add_http_request_source(span) async def sentry_async_middleware( @@ -158,14 +115,12 @@ async def sentry_async_middleware( with _sentry_pyreqwest_span(request) as span: response = await next_handler.run(request) - if isinstance(span, StreamedSpan): + if span is not None: span.status = "error" if response.status >= 400 else "ok" span.set_attribute( SPANDATA.HTTP_STATUS_CODE, response.status, ) - elif span is not None: - span.set_http_status(response.status) return response @@ -178,13 +133,11 @@ def sentry_sync_middleware( with _sentry_pyreqwest_span(request) as span: response = next_handler.run(request) - if isinstance(span, StreamedSpan): + if span is not None: span.status = "error" if response.status >= 400 else "ok" span.set_attribute( SPANDATA.HTTP_STATUS_CODE, response.status, ) - elif span is not None: - span.set_http_status(response.status) return response diff --git a/sentry_sdk/integrations/quart.py b/sentry_sdk/integrations/quart.py index 6ad19b19cc..867ec67e7e 100644 --- a/sentry_sdk/integrations/quart.py +++ b/sentry_sdk/integrations/quart.py @@ -12,8 +12,6 @@ from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import SOURCE_FOR_STYLE as SEGMENT_SOURCE_FOR_STYLE from sentry_sdk.traces import StreamedSpan, get_current_span -from sentry_sdk.tracing import SOURCE_FOR_STYLE as TRANSACTION_SOURCE_FOR_STYLE -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -123,15 +121,9 @@ def decorator(old_func: "Any") -> "Any": @wraps(old_func) @ensure_integration_enabled(QuartIntegration, old_func) def _sentry_func(*args: "Any", **kwargs: "Any") -> "Any": - client = sentry_sdk.get_client() - if has_span_streaming_enabled(client.options): - span = get_current_span() - if span is not None and hasattr(span, "_segment"): - span._segment._update_active_thread() - else: - current_scope = sentry_sdk.get_current_scope() - if current_scope.transaction is not None: - current_scope.transaction.update_active_thread() + span = get_current_span() + if span is not None and hasattr(span, "_segment"): + span._segment._update_active_thread() return old_func(*args, **kwargs) @@ -153,15 +145,9 @@ def _set_transaction_name_and_source( "endpoint": request.url_rule.endpoint, } - source = ( - SEGMENT_SOURCE_FOR_STYLE[transaction_style] - if has_span_streaming_enabled(sentry_sdk.get_client().options) - else TRANSACTION_SOURCE_FOR_STYLE[transaction_style] - ) - scope.set_transaction_name( name=name_for_style[transaction_style], - source=source, + source=SEGMENT_SOURCE_FOR_STYLE[transaction_style], ) except Exception: pass @@ -185,79 +171,50 @@ async def _request_websocket_started(app: "Quart", **kwargs: "Any") -> None: scope = sentry_sdk.get_isolation_scope() - if has_span_streaming_enabled(sentry_sdk.get_client().options): - current_span = get_current_span() - if type(current_span) is StreamedSpan: - segment = current_span._segment + current_span = get_current_span() + if type(current_span) is StreamedSpan: + segment = current_span._segment - segment.set_attribute("http.request.method", request_websocket.method) - header_attributes: "dict[str, Any]" = {} + segment.set_attribute("http.request.method", request_websocket.method) + header_attributes: "dict[str, Any]" = {} - for header, header_value in _filter_headers( - dict(request_websocket.headers), use_annotated_value=False - ).items(): - header_attributes[f"http.request.header.{header.lower()}"] = ( - header_value - ) + for header, header_value in _filter_headers( + dict(request_websocket.headers), use_annotated_value=False + ).items(): + header_attributes[f"http.request.header.{header.lower()}"] = header_value - segment.set_attributes(header_attributes) + segment.set_attributes(header_attributes) - client_options = sentry_sdk.get_client().options - filtered_query_string = None - if has_data_collection_enabled(client_options): - query_string = request_websocket.query_string.decode( - "utf-8", errors="replace" - ) - if query_string: - filtered_query_string = ( - _apply_data_collection_filtering_to_query_string( - query_string=query_string, - behaviour=client_options["data_collection"][ - "url_query_params" - ], - ) + client_options = sentry_sdk.get_client().options + filtered_query_string = None + if has_data_collection_enabled(client_options): + query_string = request_websocket.query_string.decode( + "utf-8", errors="replace" + ) + if query_string: + filtered_query_string = ( + _apply_data_collection_filtering_to_query_string( + query_string=query_string, + behaviour=client_options["data_collection"]["url_query_params"], ) - if filtered_query_string: - segment.set_attribute( - "url.query", - filtered_query_string, - ) - - parsed_url = parse_url(request_websocket.url) - segment.set_attribute( - "url.full", - f"{parsed_url.url}?{filtered_query_string}" - if filtered_query_string - else parsed_url.url, ) + if filtered_query_string: + segment.set_attribute( + "url.query", + filtered_query_string, + ) - if client_options["data_collection"]["user_info"]: - user_properties = {} - - if len(request_websocket.access_route) >= 1: - segment.set_attribute( - "client.address", request_websocket.access_route[0] - ) - user_properties["ip_address"] = request_websocket.access_route[ - 0 - ] - - current_user_id = _get_current_user_id_from_quart() - if current_user_id: - user_properties["id"] = current_user_id - - if user_properties: - existing_user_properties = scope._user or {} - scope.set_user({**existing_user_properties, **user_properties}) - - elif should_send_default_pii(): - segment.set_attribute("url.full", request_websocket.url) - segment.set_attribute( - "url.query", - request_websocket.query_string.decode("utf-8", errors="replace"), - ) + parsed_url = parse_url(request_websocket.url) + segment.set_attribute( + "url.full", + f"{parsed_url.url}?{filtered_query_string}" + if filtered_query_string + else parsed_url.url, + ) + if client_options["data_collection"]["user_info"]: user_properties = {} + if len(request_websocket.access_route) >= 1: segment.set_attribute( "client.address", request_websocket.access_route[0] @@ -272,6 +229,28 @@ async def _request_websocket_started(app: "Quart", **kwargs: "Any") -> None: existing_user_properties = scope._user or {} scope.set_user({**existing_user_properties, **user_properties}) + elif should_send_default_pii(): + segment.set_attribute("url.full", request_websocket.url) + segment.set_attribute( + "url.query", + request_websocket.query_string.decode("utf-8", errors="replace"), + ) + + user_properties = {} + if len(request_websocket.access_route) >= 1: + segment.set_attribute( + "client.address", request_websocket.access_route[0] + ) + user_properties["ip_address"] = request_websocket.access_route[0] + + current_user_id = _get_current_user_id_from_quart() + if current_user_id: + user_properties["id"] = current_user_id + + if user_properties: + existing_user_properties = scope._user or {} + scope.set_user({**existing_user_properties, **user_properties}) + evt_processor = _make_request_event_processor(app, request_websocket, integration) scope.add_event_processor(evt_processor) diff --git a/sentry_sdk/integrations/ray.py b/sentry_sdk/integrations/ray.py index 744cc266cf..33e12d1ca2 100644 --- a/sentry_sdk/integrations/ray.py +++ b/sentry_sdk/integrations/ray.py @@ -3,11 +3,9 @@ import sys import sentry_sdk -from sentry_sdk.consts import OP, SPANSTATUS +from sentry_sdk.consts import OP from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version from sentry_sdk.traces import SegmentNameSource -from sentry_sdk.tracing import TransactionSource -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( event_from_exception, logger, @@ -90,52 +88,26 @@ def new_func( ) -> "Any": _check_sentry_initialized() - span_streaming = has_span_streaming_enabled( - sentry_sdk.get_client().options - ) - if span_streaming: - sentry_sdk.traces.continue_trace(_sentry_tracing or {}) - - function_name = qualname_from_function(user_f) - with sentry_sdk.traces.start_span( - name="unknown Ray task" - if function_name is None - else function_name, - attributes={ - "sentry.op": OP.QUEUE_TASK_RAY, - "sentry.origin": RayIntegration.origin, - "sentry.segment.name.source": SegmentNameSource.TASK, - }, - parent_span=None, - ): - try: - result = user_f(*f_args, **f_kwargs) - except Exception: - exc_info = sys.exc_info() - _capture_exception(exc_info) - reraise(*exc_info) - - return result - else: - transaction = sentry_sdk.continue_trace( - _sentry_tracing or {}, - op=OP.QUEUE_TASK_RAY, - name=qualname_from_function(user_f), - origin=RayIntegration.origin, - source=TransactionSource.TASK, - ) - - with sentry_sdk.start_transaction(transaction) as transaction: - try: - result = user_f(*f_args, **f_kwargs) - transaction.set_status(SPANSTATUS.OK) - except Exception: - transaction.set_status(SPANSTATUS.INTERNAL_ERROR) - exc_info = sys.exc_info() - _capture_exception(exc_info) - reraise(*exc_info) - - return result + sentry_sdk.traces.continue_trace(_sentry_tracing or {}) + + function_name = qualname_from_function(user_f) + with sentry_sdk.traces.start_span( + name="unknown Ray task" if function_name is None else function_name, + attributes={ + "sentry.op": OP.QUEUE_TASK_RAY, + "sentry.origin": RayIntegration.origin, + "sentry.segment.name.source": SegmentNameSource.TASK, + }, + parent_span=None, + ): + try: + result = user_f(*f_args, **f_kwargs) + except Exception: + exc_info = sys.exc_info() + _capture_exception(exc_info) + reraise(*exc_info) + + return result _insert_sentry_tracing_in_signature(new_func) @@ -151,73 +123,45 @@ def _remote_method_with_header_propagation( """ Ray Client """ - span_streaming = has_span_streaming_enabled( - sentry_sdk.get_client().options - ) - if span_streaming: - function_name = qualname_from_function(user_f) - - if sentry_sdk.traces.get_current_span() is None: - tracing = { - k: v - for k, v in sentry_sdk.get_current_scope().iter_trace_propagation_headers() - } - try: - result = old_remote_method( - *args, **kwargs, _sentry_tracing=tracing - ) - except Exception: - exc_info = sys.exc_info() - _capture_exception(exc_info) - reraise(*exc_info) - - return result - - with sentry_sdk.traces.start_span( - name="unknown Ray task" - if function_name is None - else function_name, - attributes={ - "sentry.op": OP.QUEUE_SUBMIT_RAY, - "sentry.origin": RayIntegration.origin, - }, - ): - tracing = { - k: v - for k, v in sentry_sdk.get_current_scope().iter_trace_propagation_headers() - } - try: - result = old_remote_method( - *args, **kwargs, _sentry_tracing=tracing - ) - except Exception: - exc_info = sys.exc_info() - _capture_exception(exc_info) - reraise(*exc_info) - - return result - else: - with sentry_sdk.start_span( - op=OP.QUEUE_SUBMIT_RAY, - name=qualname_from_function(user_f), - origin=RayIntegration.origin, - ) as span: - tracing = { - k: v - for k, v in sentry_sdk.get_current_scope().iter_trace_propagation_headers() - } - try: - result = old_remote_method( - *args, **kwargs, _sentry_tracing=tracing - ) - span.set_status(SPANSTATUS.OK) - except Exception: - span.set_status(SPANSTATUS.INTERNAL_ERROR) - exc_info = sys.exc_info() - _capture_exception(exc_info) - reraise(*exc_info) - - return result + function_name = qualname_from_function(user_f) + + if sentry_sdk.traces.get_current_span() is None: + tracing = { + k: v + for k, v in sentry_sdk.get_current_scope().iter_trace_propagation_headers() + } + try: + result = old_remote_method( + *args, **kwargs, _sentry_tracing=tracing + ) + except Exception: + exc_info = sys.exc_info() + _capture_exception(exc_info) + reraise(*exc_info) + + return result + + with sentry_sdk.traces.start_span( + name="unknown Ray task" if function_name is None else function_name, + attributes={ + "sentry.op": OP.QUEUE_SUBMIT_RAY, + "sentry.origin": RayIntegration.origin, + }, + ): + tracing = { + k: v + for k, v in sentry_sdk.get_current_scope().iter_trace_propagation_headers() + } + try: + result = old_remote_method( + *args, **kwargs, _sentry_tracing=tracing + ) + except Exception: + exc_info = sys.exc_info() + _capture_exception(exc_info) + reraise(*exc_info) + + return result rv.remote = _remote_method_with_header_propagation diff --git a/sentry_sdk/integrations/redis/_async_common.py b/sentry_sdk/integrations/redis/_async_common.py index bd83d22191..fb782b2ef9 100644 --- a/sentry_sdk/integrations/redis/_async_common.py +++ b/sentry_sdk/integrations/redis/_async_common.py @@ -14,7 +14,6 @@ _set_pipeline_data, ) from sentry_sdk.tracing import Span -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import capture_internal_exceptions if TYPE_CHECKING: @@ -42,25 +41,17 @@ async def _sentry_execute(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": if client.get_integration(RedisIntegration) is None: return await old_execute(self, *args, **kwargs) - span_streaming = has_span_streaming_enabled(client.options) + if sentry_sdk.traces.get_current_span() is None: + return await old_execute(self, *args, **kwargs) span: "Union[Span, StreamedSpan]" - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return await old_execute(self, *args, **kwargs) - span = sentry_sdk.traces.start_span( - name="redis.pipeline.execute", - attributes={ - "sentry.origin": SPAN_ORIGIN, - "sentry.op": OP.DB_REDIS, - }, - ) - else: - span = sentry_sdk.start_span( - op=OP.DB_REDIS, - name="redis.pipeline.execute", - origin=SPAN_ORIGIN, - ) + span = sentry_sdk.traces.start_span( + name="redis.pipeline.execute", + attributes={ + "sentry.origin": SPAN_ORIGIN, + "sentry.op": OP.DB_REDIS, + }, + ) with span: with capture_internal_exceptions(): @@ -103,9 +94,7 @@ async def _sentry_execute_command( if integration is None: return await old_execute_command(self, name, *args, **kwargs) - span_streaming = has_span_streaming_enabled(client.options) - - if span_streaming and sentry_sdk.traces.get_current_span() is None: + if sentry_sdk.traces.get_current_span() is None: return await old_execute_command(self, name, *args, **kwargs) cache_properties = _compile_cache_span_properties( @@ -123,21 +112,14 @@ async def _sentry_execute_command( cache_span: "Optional[Union[Span, StreamedSpan]]" = None if cache_properties["is_cache_key"] and cache_properties["op"] is not None: - if span_streaming: - cache_span = sentry_sdk.traces.start_span( - name=cache_properties["description"], - attributes={ - "sentry.op": cache_properties["op"], - "sentry.origin": SPAN_ORIGIN, - **additional_cache_span_attributes, - }, - ) - else: - cache_span = sentry_sdk.start_span( - op=cache_properties["op"], - name=cache_properties["description"], - origin=SPAN_ORIGIN, - ) + cache_span = sentry_sdk.traces.start_span( + name=cache_properties["description"], + attributes={ + "sentry.op": cache_properties["op"], + "sentry.origin": SPAN_ORIGIN, + **additional_cache_span_attributes, + }, + ) cache_span.__enter__() db_properties = _compile_db_span_properties(integration, name, args) @@ -149,21 +131,14 @@ async def _sentry_execute_command( ) db_span: "Union[Span, StreamedSpan]" - if span_streaming: - db_span = sentry_sdk.traces.start_span( - name=db_properties["description"], - attributes={ - "sentry.op": db_properties["op"], - "sentry.origin": SPAN_ORIGIN, - **additional_db_span_attributes, - }, - ) - else: - db_span = sentry_sdk.start_span( - op=db_properties["op"], - name=db_properties["description"], - origin=SPAN_ORIGIN, - ) + db_span = sentry_sdk.traces.start_span( + name=db_properties["description"], + attributes={ + "sentry.op": db_properties["op"], + "sentry.origin": SPAN_ORIGIN, + **additional_db_span_attributes, + }, + ) db_span.__enter__() set_db_data_fn(db_span, self) diff --git a/sentry_sdk/integrations/redis/_sync_common.py b/sentry_sdk/integrations/redis/_sync_common.py index 3afa7f282c..a4155829c8 100644 --- a/sentry_sdk/integrations/redis/_sync_common.py +++ b/sentry_sdk/integrations/redis/_sync_common.py @@ -14,7 +14,6 @@ _set_pipeline_data, ) from sentry_sdk.tracing import Span -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import capture_internal_exceptions if TYPE_CHECKING: @@ -39,25 +38,17 @@ def sentry_patched_execute(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": if client.get_integration(RedisIntegration) is None: return old_execute(self, *args, **kwargs) - span_streaming = has_span_streaming_enabled(client.options) + if sentry_sdk.traces.get_current_span() is None: + return old_execute(self, *args, **kwargs) span: "Union[Span, StreamedSpan]" - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return old_execute(self, *args, **kwargs) - span = sentry_sdk.traces.start_span( - name="redis.pipeline.execute", - attributes={ - "sentry.origin": SPAN_ORIGIN, - "sentry.op": OP.DB_REDIS, - }, - ) - else: - span = sentry_sdk.start_span( - op=OP.DB_REDIS, - name="redis.pipeline.execute", - origin=SPAN_ORIGIN, - ) + span = sentry_sdk.traces.start_span( + name="redis.pipeline.execute", + attributes={ + "sentry.origin": SPAN_ORIGIN, + "sentry.op": OP.DB_REDIS, + }, + ) with span: with capture_internal_exceptions(): @@ -102,9 +93,7 @@ def sentry_patched_execute_command( if integration is None: return old_execute_command(self, name, *args, **kwargs) - span_streaming = has_span_streaming_enabled(client.options) - - if span_streaming and sentry_sdk.traces.get_current_span() is None: + if sentry_sdk.traces.get_current_span() is None: return old_execute_command(self, name, *args, **kwargs) cache_properties = _compile_cache_span_properties( @@ -122,21 +111,14 @@ def sentry_patched_execute_command( cache_span: "Optional[Union[Span, StreamedSpan]]" = None if cache_properties["is_cache_key"] and cache_properties["op"] is not None: - if span_streaming: - cache_span = sentry_sdk.traces.start_span( - name=cache_properties["description"], - attributes={ - "sentry.op": cache_properties["op"], - "sentry.origin": SPAN_ORIGIN, - **additional_cache_span_attributes, - }, - ) - else: - cache_span = sentry_sdk.start_span( - op=cache_properties["op"], - name=cache_properties["description"], - origin=SPAN_ORIGIN, - ) + cache_span = sentry_sdk.traces.start_span( + name=cache_properties["description"], + attributes={ + "sentry.op": cache_properties["op"], + "sentry.origin": SPAN_ORIGIN, + **additional_cache_span_attributes, + }, + ) cache_span.__enter__() db_properties = _compile_db_span_properties(integration, name, args) @@ -148,21 +130,14 @@ def sentry_patched_execute_command( ) db_span: "Union[Span, StreamedSpan]" - if span_streaming: - db_span = sentry_sdk.traces.start_span( - name=db_properties["description"], - attributes={ - "sentry.op": db_properties["op"], - "sentry.origin": SPAN_ORIGIN, - **additional_db_span_attributes, - }, - ) - else: - db_span = sentry_sdk.start_span( - op=db_properties["op"], - name=db_properties["description"], - origin=SPAN_ORIGIN, - ) + db_span = sentry_sdk.traces.start_span( + name=db_properties["description"], + attributes={ + "sentry.op": db_properties["op"], + "sentry.origin": SPAN_ORIGIN, + **additional_db_span_attributes, + }, + ) db_span.__enter__() set_db_data_fn(db_span, self) diff --git a/sentry_sdk/integrations/rq.py b/sentry_sdk/integrations/rq.py index d6b51ba77d..8e4319f79b 100644 --- a/sentry_sdk/integrations/rq.py +++ b/sentry_sdk/integrations/rq.py @@ -2,14 +2,11 @@ import weakref import sentry_sdk -from sentry_sdk.api import continue_trace from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version from sentry_sdk.integrations.logging import ignore_logger from sentry_sdk.scope import Scope, should_send_default_pii from sentry_sdk.traces import SegmentNameSource -from sentry_sdk.tracing import TransactionSource -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( SENSITIVE_DATA_SUBSTITUTE, capture_internal_exceptions, @@ -76,51 +73,31 @@ def sentry_patched_perform_job( scope.clear_breadcrumbs() scope.add_event_processor(_make_event_processor(weakref.ref(job))) - if has_span_streaming_enabled(client.options): - sentry_sdk.traces.continue_trace( - job.meta.get("_sentry_trace_headers") or {} - ) - - Scope.set_custom_sampling_context({"rq_job": job}) - - func_name = None - with capture_internal_exceptions(): - func_name = job.func_name - - with sentry_sdk.traces.start_span( - name="unknown RQ task" if func_name is None else func_name, - attributes={ - "sentry.op": OP.QUEUE_TASK_RQ, - "sentry.origin": RqIntegration.origin, - "sentry.segment.name.source": SegmentNameSource.TASK, - SPANDATA.MESSAGING_MESSAGE_ID: job.id, - SPANDATA.MESSAGING_DESTINATION_NAME: queue.name, - }, - parent_span=None, - ) as span: - if func_name is not None: - span.set_attribute(SPANDATA.CODE_FUNCTION_NAME, func_name) - - rv = old_perform_job(self, job, queue, *args, **kwargs) - else: - transaction = continue_trace( - job.meta.get("_sentry_trace_headers") or {}, - op=OP.QUEUE_TASK_RQ, - name="unknown RQ task", - source=TransactionSource.TASK, - origin=RqIntegration.origin, - ) + sentry_sdk.traces.continue_trace( + job.meta.get("_sentry_trace_headers") or {} + ) - with capture_internal_exceptions(): - transaction.name = job.func_name + Scope.set_custom_sampling_context({"rq_job": job}) - with sentry_sdk.start_transaction( - transaction, - custom_sampling_context={"rq_job": job}, - ) as span: - span.set_data(SPANDATA.MESSAGING_DESTINATION_NAME, queue.name) + func_name = None + with capture_internal_exceptions(): + func_name = job.func_name - rv = old_perform_job(self, job, queue, *args, **kwargs) + with sentry_sdk.traces.start_span( + name="unknown RQ task" if func_name is None else func_name, + attributes={ + "sentry.op": OP.QUEUE_TASK_RQ, + "sentry.origin": RqIntegration.origin, + "sentry.segment.name.source": SegmentNameSource.TASK, + SPANDATA.MESSAGING_MESSAGE_ID: job.id, + SPANDATA.MESSAGING_DESTINATION_NAME: queue.name, + }, + parent_span=None, + ) as span: + if func_name is not None: + span.set_attribute(SPANDATA.CODE_FUNCTION_NAME, func_name) + + rv = old_perform_job(self, job, queue, *args, **kwargs) if self.is_horse: # We're inside of a forked process and RQ is @@ -161,11 +138,7 @@ def sentry_patched_enqueue_job( return old_enqueue_job(self, job, **kwargs) scope = sentry_sdk.get_current_scope() - span = ( - scope.streamed_span - if has_span_streaming_enabled(client.options) - else scope.span - ) + span = scope.streamed_span if span is not None: job.meta["_sentry_trace_headers"] = dict( scope.iter_trace_propagation_headers() diff --git a/sentry_sdk/integrations/rust_tracing.py b/sentry_sdk/integrations/rust_tracing.py index d02b7fb5ab..f9d493c224 100644 --- a/sentry_sdk/integrations/rust_tracing.py +++ b/sentry_sdk/integrations/rust_tracing.py @@ -32,14 +32,12 @@ import json from enum import Enum, auto -from typing import Any, Callable, Dict, Optional, Union +from typing import Any, Callable, Dict, Optional import sentry_sdk from sentry_sdk.integrations import Integration from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing import Span as SentrySpan -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import SENSITIVE_DATA_SUBSTITUTE @@ -170,7 +168,7 @@ def _include_tracing_fields(self) -> bool: else self.include_tracing_fields ) - def on_event(self, event: str, sentry_span: "SentrySpan") -> None: + def on_event(self, event: str, sentry_span: "StreamedSpan") -> None: deserialized_event = json.loads(event) metadata = deserialized_event.get("metadata", {}) @@ -184,9 +182,7 @@ def on_event(self, event: str, sentry_span: "SentrySpan") -> None: elif event_type == EventTypeMapping.Event: process_event(deserialized_event) - def on_new_span( - self, attrs: str, span_id: str - ) -> "Optional[Union[SentrySpan, StreamedSpan]]": + def on_new_span(self, attrs: str, span_id: str) -> "Optional[StreamedSpan]": attrs = json.loads(attrs) metadata = attrs.get("metadata", {}) @@ -206,66 +202,41 @@ def on_new_span( else: sentry_span_name = "" - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return None - - sentry_span = sentry_sdk.traces.start_span( - name=sentry_span_name, - attributes={ - "sentry.op": "function", - "sentry.origin": self.origin, - }, - ) - fields = metadata.get("fields", []) - for field in fields: - if self._include_tracing_fields(): - sentry_span.set_attribute(field, attrs.get(field)) - else: - sentry_span.set_attribute(field, SENSITIVE_DATA_SUBSTITUTE) - - return sentry_span - - sentry_span = sentry_sdk.start_span( - op="function", + if sentry_sdk.traces.get_current_span() is None: + return None + + sentry_span = sentry_sdk.traces.start_span( name=sentry_span_name, - origin=self.origin, + attributes={ + "sentry.op": "function", + "sentry.origin": self.origin, + }, ) fields = metadata.get("fields", []) for field in fields: if self._include_tracing_fields(): - sentry_span.set_data(field, attrs.get(field)) + sentry_span.set_attribute(field, attrs.get(field)) else: - sentry_span.set_data(field, SENSITIVE_DATA_SUBSTITUTE) + sentry_span.set_attribute(field, SENSITIVE_DATA_SUBSTITUTE) - sentry_span.__enter__() return sentry_span - def on_close(self, span_id: str, sentry_span: "SentrySpan") -> None: + def on_close(self, span_id: str, sentry_span: "StreamedSpan") -> None: if sentry_span is None: return sentry_span.__exit__(None, None, None) - def on_record( - self, span_id: str, values: str, sentry_span: "Union[SentrySpan, StreamedSpan]" - ) -> None: + def on_record(self, span_id: str, values: str, sentry_span: "StreamedSpan") -> None: if sentry_span is None: return - set_on_span = ( - sentry_span.set_attribute - if isinstance(sentry_span, StreamedSpan) - else sentry_span.set_data - ) - deserialized_values = json.loads(values) for key, value in deserialized_values.items(): if self._include_tracing_fields(): - set_on_span(key, value) + sentry_span.set_attribute(key, value) else: - set_on_span(key, SENSITIVE_DATA_SUBSTITUTE) + sentry_span.set_attribute(key, SENSITIVE_DATA_SUBSTITUTE) class RustTracingIntegration(Integration): diff --git a/sentry_sdk/integrations/sanic.py b/sentry_sdk/integrations/sanic.py index 9f1ece76c8..c66d4cb75e 100644 --- a/sentry_sdk/integrations/sanic.py +++ b/sentry_sdk/integrations/sanic.py @@ -6,7 +6,6 @@ from urllib.parse import urlsplit import sentry_sdk -from sentry_sdk import continue_trace from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.data_collection import ( _apply_data_collection_filtering_to_query_string, @@ -15,9 +14,8 @@ from sentry_sdk.integrations._wsgi_common import RequestExtractor, _filter_headers from sentry_sdk.integrations.logging import ignore_logger from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import SegmentNameSource, StreamedSpan +from sentry_sdk.traces import SegmentNameSource from sentry_sdk.tracing import TransactionSource -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( CONTEXTVARS_ERROR_MESSAGE, HAS_REAL_CONTEXTVARS, @@ -174,7 +172,6 @@ async def _context_enter(request: "Request") -> None: return client = sentry_sdk.get_client() - is_span_streaming_enabled = has_span_streaming_enabled(client.options) weak_request = weakref.ref(request) request.ctx._sentry_scope = sentry_sdk.isolation_scope() @@ -182,51 +179,35 @@ async def _context_enter(request: "Request") -> None: scope.clear_breadcrumbs() scope.add_event_processor(_make_request_processor(weak_request)) - if is_span_streaming_enabled: - integration = client.get_integration(SanicIntegration) - if ( - isinstance(integration, SanicIntegration) - and integration._unsampled_statuses - ): - warnings.warn( - "The `unsampled_statuses` option of SanicIntegration has no effect when span streaming is enabled.", - stacklevel=2, - ) + integration = client.get_integration(SanicIntegration) + if isinstance(integration, SanicIntegration) and integration._unsampled_statuses: + warnings.warn( + "The `unsampled_statuses` option of SanicIntegration has no effect when span streaming is enabled.", + stacklevel=2, + ) - sentry_sdk.traces.continue_trace(dict(request.headers)) - scope.set_custom_sampling_context({"sanic_request": request}) + sentry_sdk.traces.continue_trace(dict(request.headers)) + scope.set_custom_sampling_context({"sanic_request": request}) - if request.remote_addr: - if has_data_collection_enabled(client.options): - if client.options["data_collection"]["user_info"]: - scope.set_attribute(SPANDATA.USER_IP_ADDRESS, request.remote_addr) - elif should_send_default_pii(): + if request.remote_addr: + if has_data_collection_enabled(client.options): + if client.options["data_collection"]["user_info"]: scope.set_attribute(SPANDATA.USER_IP_ADDRESS, request.remote_addr) - - span = sentry_sdk.traces.start_span( - # Unless the request results in a 404 error, the name and source - # will get overwritten in _set_transaction - name=request.path, - attributes={ - "sentry.op": OP.HTTP_SERVER, - "sentry.origin": SanicIntegration.origin, - "sentry.segment.name.source": SegmentNameSource.URL.value, - }, - parent_span=None, - ) - request.ctx._sentry_root_span = span - else: - transaction = continue_trace( - dict(request.headers), - 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=TransactionSource.URL, - origin=SanicIntegration.origin, - ) - request.ctx._sentry_root_span = sentry_sdk.start_transaction( - transaction - ).__enter__() + elif should_send_default_pii(): + scope.set_attribute(SPANDATA.USER_IP_ADDRESS, request.remote_addr) + + span = sentry_sdk.traces.start_span( + # Unless the request results in a 404 error, the name and source + # will get overwritten in _set_transaction + name=request.path, + attributes={ + "sentry.op": OP.HTTP_SERVER, + "sentry.origin": SanicIntegration.origin, + "sentry.segment.name.source": SegmentNameSource.URL.value, + }, + parent_span=None, + ) + request.ctx._sentry_root_span = span async def _context_exit( @@ -236,32 +217,20 @@ async def _context_exit( if not request.ctx._sentry_do_integration: return - integration = sentry_sdk.get_client().get_integration(SanicIntegration) - response_status = None if response is None else response.status # This capture_internal_exceptions block has been intentionally nested here, so that in case an exception # happens while trying to end the transaction, we still attempt to exit the scope. with capture_internal_exceptions(): span = request.ctx._sentry_root_span - if isinstance(span, StreamedSpan): - with capture_internal_exceptions(): - for attr, value in _get_request_attributes(request).items(): - span.set_attribute(attr, value) - if response_status is not None: - span.set_attribute(SPANDATA.HTTP_STATUS_CODE, response_status) - span.status = "error" if response_status >= 400 else "ok" - - span.end() - - else: - span.set_http_status(response_status) - span.sampled &= ( - isinstance(integration, SanicIntegration) - and response_status not in integration._unsampled_statuses - ) - - span.__exit__(None, None, None) + with capture_internal_exceptions(): + for attr, value in _get_request_attributes(request).items(): + span.set_attribute(attr, value) + if response_status is not None: + span.set_attribute(SPANDATA.HTTP_STATUS_CODE, response_status) + span.status = "error" if response_status >= 400 else "ok" + + span.end() request.ctx._sentry_scope.__exit__(None, None, None) diff --git a/sentry_sdk/integrations/socket.py b/sentry_sdk/integrations/socket.py index c719f14227..022f7c06e2 100644 --- a/sentry_sdk/integrations/socket.py +++ b/sentry_sdk/integrations/socket.py @@ -4,7 +4,6 @@ from sentry_sdk._types import MYPY from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import Integration -from sentry_sdk.tracing_utils import has_span_streaming_enabled if MYPY: from socket import AddressFamily, SocketKind @@ -56,37 +55,23 @@ def create_connection( if integration is None: return real_create_connection(address, timeout, source_address) - if has_span_streaming_enabled(client.options): - if sentry_sdk.traces.get_current_span() is None: - return real_create_connection(address, timeout, source_address) - - with sentry_sdk.traces.start_span( - name=_get_span_description(address[0], address[1]), - attributes={ - "sentry.op": OP.SOCKET_CONNECTION, - "sentry.origin": SocketIntegration.origin, - }, - ) as span: - if address[0] is not None: - span.set_attribute(SPANDATA.SERVER_ADDRESS, address[0]) - span.set_attribute(SPANDATA.SERVER_PORT, address[1]) - - return real_create_connection( - address=address, timeout=timeout, source_address=source_address - ) - else: - with sentry_sdk.start_span( - op=OP.SOCKET_CONNECTION, - name=_get_span_description(address[0], address[1]), - origin=SocketIntegration.origin, - ) as span: - span.set_data("address", address) - span.set_data("timeout", timeout) - span.set_data("source_address", source_address) - - return real_create_connection( - address=address, timeout=timeout, source_address=source_address - ) + if sentry_sdk.traces.get_current_span() is None: + return real_create_connection(address, timeout, source_address) + + with sentry_sdk.traces.start_span( + name=_get_span_description(address[0], address[1]), + attributes={ + "sentry.op": OP.SOCKET_CONNECTION, + "sentry.origin": SocketIntegration.origin, + }, + ) as span: + if address[0] is not None: + span.set_attribute(SPANDATA.SERVER_ADDRESS, address[0]) + span.set_attribute(SPANDATA.SERVER_PORT, address[1]) + + return real_create_connection( + address=address, timeout=timeout, source_address=source_address + ) socket.create_connection = create_connection # type: ignore @@ -107,42 +92,31 @@ def getaddrinfo( if integration is None: return real_getaddrinfo(host, port, family, type, proto, flags) - if has_span_streaming_enabled(client.options): - if sentry_sdk.traces.get_current_span() is None: - return real_getaddrinfo(host, port, family, type, proto, flags) - - with sentry_sdk.traces.start_span( - name=_get_span_description(host, port), - attributes={ - "sentry.op": OP.SOCKET_DNS, - "sentry.origin": SocketIntegration.origin, - }, - ) as span: - if isinstance(host, str): - span.set_attribute(SPANDATA.SERVER_ADDRESS, host) - elif isinstance(host, bytes): - span.set_attribute( - SPANDATA.SERVER_ADDRESS, host.decode(errors="replace") - ) - - if isinstance(port, int): - span.set_attribute(SPANDATA.SERVER_PORT, port) - elif port is not None: - try: - span.set_attribute(SPANDATA.SERVER_PORT, int(port)) - except (ValueError, TypeError): - pass - - return real_getaddrinfo(host, port, family, type, proto, flags) - else: - with sentry_sdk.start_span( - op=OP.SOCKET_DNS, - name=_get_span_description(host, port), - origin=SocketIntegration.origin, - ) as span: - span.set_data("host", host) - span.set_data("port", port) - - return real_getaddrinfo(host, port, family, type, proto, flags) + if sentry_sdk.traces.get_current_span() is None: + return real_getaddrinfo(host, port, family, type, proto, flags) + + with sentry_sdk.traces.start_span( + name=_get_span_description(host, port), + attributes={ + "sentry.op": OP.SOCKET_DNS, + "sentry.origin": SocketIntegration.origin, + }, + ) as span: + if isinstance(host, str): + span.set_attribute(SPANDATA.SERVER_ADDRESS, host) + elif isinstance(host, bytes): + span.set_attribute( + SPANDATA.SERVER_ADDRESS, host.decode(errors="replace") + ) + + if isinstance(port, int): + span.set_attribute(SPANDATA.SERVER_PORT, port) + elif port is not None: + try: + span.set_attribute(SPANDATA.SERVER_PORT, int(port)) + except (ValueError, TypeError): + pass + + return real_getaddrinfo(host, port, family, type, proto, flags) socket.getaddrinfo = getaddrinfo diff --git a/sentry_sdk/integrations/starlette.py b/sentry_sdk/integrations/starlette.py index 054cea6c12..6264effbbb 100644 --- a/sentry_sdk/integrations/starlette.py +++ b/sentry_sdk/integrations/starlette.py @@ -28,7 +28,6 @@ SOURCE_FOR_STYLE, TransactionSource, ) -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( AnnotatedValue, capture_internal_exceptions, @@ -177,40 +176,26 @@ async def _create_span_call( return await old_call(app, scope, receive, send, **kwargs) middleware_name = app.__class__.__name__ - is_span_streaming_enabled = has_span_streaming_enabled(client.options) def _start_middleware_span(op: str, name: str) -> "Any": - if is_span_streaming_enabled: - if sentry_sdk.traces.get_current_span() is None: - return nullcontext() - return sentry_sdk.traces.start_span( - name=name, - attributes={ - "sentry.op": op, - "sentry.origin": StarletteIntegration.origin, - "middleware.name": middleware_name, - }, - ) - return sentry_sdk.start_span( - op=op, + if sentry_sdk.traces.get_current_span() is None: + return nullcontext() + return sentry_sdk.traces.start_span( name=name, - origin=StarletteIntegration.origin, + attributes={ + "sentry.op": op, + "sentry.origin": StarletteIntegration.origin, + "middleware.name": middleware_name, + }, ) - with _start_middleware_span( - op=OP.MIDDLEWARE_STARLETTE, name=middleware_name - ) as middleware_span: - if not is_span_streaming_enabled: - middleware_span.set_tag("starlette.middleware_name", middleware_name) - + with _start_middleware_span(op=OP.MIDDLEWARE_STARLETTE, name=middleware_name): # Creating spans for the "receive" callback async def _sentry_receive(*args: "Any", **kwargs: "Any") -> "Any": with _start_middleware_span( op=OP.MIDDLEWARE_STARLETTE_RECEIVE, name=getattr(receive, "__qualname__", str(receive)), - ) as span: - if not is_span_streaming_enabled: - span.set_tag("starlette.middleware_name", middleware_name) + ): return await receive(*args, **kwargs) receive_name = getattr(receive, "__name__", str(receive)) @@ -222,9 +207,7 @@ async def _sentry_send(*args: "Any", **kwargs: "Any") -> "Any": with _start_middleware_span( op=OP.MIDDLEWARE_STARLETTE_SEND, name=getattr(send, "__qualname__", str(send)), - ) as span: - if not is_span_streaming_enabled: - span.set_tag("starlette.middleware_name", middleware_name) + ): return await send(*args, **kwargs) send_name = getattr(send, "__name__", str(send)) @@ -596,14 +579,10 @@ def _sentry_sync_func(*args: "Any", **kwargs: "Any") -> "Any": current_scope = sentry_sdk.get_current_scope() - span_streaming = has_span_streaming_enabled(client.options) - if span_streaming: - current_span = current_scope.streamed_span + current_span = current_scope.streamed_span - if type(current_span) is StreamedSpan: - current_span._segment._update_active_thread() - elif current_scope.transaction is not None: - current_scope.transaction.update_active_thread() + if type(current_span) is StreamedSpan: + current_span._segment._update_active_thread() sentry_scope = sentry_sdk.get_isolation_scope() diff --git a/sentry_sdk/integrations/starlite.py b/sentry_sdk/integrations/starlite.py index 8963fc9e53..cc4e6dff49 100644 --- a/sentry_sdk/integrations/starlite.py +++ b/sentry_sdk/integrations/starlite.py @@ -7,7 +7,6 @@ from sentry_sdk.integrations.asgi import SentryAsgiMiddleware from sentry_sdk.scope import should_send_default_pii from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( ensure_integration_enabled, event_from_exception, @@ -150,32 +149,20 @@ async def _create_span_call( return await old_call(self, scope, receive, send) middleware_name = self.__class__.__name__ - is_span_streaming_enabled = has_span_streaming_enabled(client.options) def _start_middleware_span(op: str, name: str) -> "Any": - if is_span_streaming_enabled: - if sentry_sdk.traces.get_current_span() is None: - return nullcontext() - return sentry_sdk.traces.start_span( - name=name, - attributes={ - "sentry.op": op, - "sentry.origin": StarliteIntegration.origin, - SPANDATA.MIDDLEWARE_NAME: middleware_name, - }, - ) - return sentry_sdk.start_span( - op=op, + if sentry_sdk.traces.get_current_span() is None: + return nullcontext() + return sentry_sdk.traces.start_span( name=name, - origin=StarliteIntegration.origin, + attributes={ + "sentry.op": op, + "sentry.origin": StarliteIntegration.origin, + SPANDATA.MIDDLEWARE_NAME: middleware_name, + }, ) - with _start_middleware_span( - op=OP.MIDDLEWARE_STARLITE, name=middleware_name - ) as middleware_span: - if not is_span_streaming_enabled: - middleware_span.set_tag("starlite.middleware_name", middleware_name) - + with _start_middleware_span(op=OP.MIDDLEWARE_STARLITE, name=middleware_name): # Creating spans for the "receive" callback async def _sentry_receive( *args: "Any", **kwargs: "Any" @@ -185,9 +172,7 @@ async def _sentry_receive( with _start_middleware_span( op=OP.MIDDLEWARE_STARLITE_RECEIVE, name=getattr(receive, "__qualname__", str(receive)), - ) as span: - if not is_span_streaming_enabled: - span.set_tag("starlite.middleware_name", middleware_name) + ): return await receive(*args, **kwargs) receive_name = getattr(receive, "__name__", str(receive)) @@ -201,9 +186,7 @@ async def _sentry_send(message: "Message") -> None: with _start_middleware_span( op=OP.MIDDLEWARE_STARLITE_SEND, name=getattr(send, "__qualname__", str(send)), - ) as span: - if not is_span_streaming_enabled: - span.set_tag("starlite.middleware_name", middleware_name) + ): return await send(message) send_name = getattr(send, "__name__", str(send)) diff --git a/sentry_sdk/integrations/stdlib.py b/sentry_sdk/integrations/stdlib.py index 4de3819a77..456d0b4af0 100644 --- a/sentry_sdk/integrations/stdlib.py +++ b/sentry_sdk/integrations/stdlib.py @@ -10,11 +10,9 @@ from sentry_sdk.integrations import Integration from sentry_sdk.scope import add_global_event_processor, should_send_default_pii from sentry_sdk.traces import StreamedSpan -from sentry_sdk.tracing import Span from sentry_sdk.tracing_utils import ( EnvironHeaders, add_http_request_source, - has_span_streaming_enabled, should_propagate_trace, ) from sentry_sdk.utils import ( @@ -28,7 +26,7 @@ ) if TYPE_CHECKING: - from typing import Any, Callable, Dict, List, Optional, Union + from typing import Any, Callable, Dict, List, Optional from sentry_sdk._types import Event, Hint @@ -61,15 +59,10 @@ def add_python_runtime_context( return event -def _complete_span(span: "Union[Span, StreamedSpan]") -> None: - if isinstance(span, StreamedSpan): - with capture_internal_exceptions(): - add_http_request_source(span) - span.end() - else: - span.finish() - with capture_internal_exceptions(): - add_http_request_source(span) +def _complete_span(span: "StreamedSpan") -> None: + with capture_internal_exceptions(): + add_http_request_source(span) + span.end() def _install_httplib() -> None: @@ -111,51 +104,32 @@ def putrequest( with capture_internal_exceptions(): parsed_url = parse_url(real_url, sanitize=False) - span_streaming = has_span_streaming_enabled(client.options) - span: "Union[Span, StreamedSpan, None]" - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - span = None - else: - span = sentry_sdk.traces.start_span( - name="%s %s" - % ( - method, - parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, - ), - attributes={ - "sentry.origin": "auto.http.stdlib.httplib", - "sentry.op": OP.HTTP_CLIENT, - SPANDATA.HTTP_REQUEST_METHOD: method, - }, - ) - - if parsed_url is not None and should_send_default_pii(): - span.set_attribute(SPANDATA.URL_FRAGMENT, parsed_url.fragment) - span.set_attribute(SPANDATA.URL_FULL, parsed_url.url) - span.set_attribute(SPANDATA.URL_QUERY, parsed_url.query) - - set_on_span = span.set_attribute + span: "Optional[StreamedSpan]" + if sentry_sdk.traces.get_current_span() is None: + span = None else: - span = sentry_sdk.start_span( - op=OP.HTTP_CLIENT, + span = sentry_sdk.traces.start_span( name="%s %s" - % (method, parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE), - origin="auto.http.stdlib.httplib", + % ( + method, + parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, + ), + attributes={ + "sentry.origin": "auto.http.stdlib.httplib", + "sentry.op": OP.HTTP_CLIENT, + SPANDATA.HTTP_REQUEST_METHOD: method, + }, ) - span.set_data(SPANDATA.HTTP_METHOD, method) - if parsed_url is not None: - span.set_data(SPANDATA.HTTP_FRAGMENT, parsed_url.fragment) - span.set_data("url", parsed_url.url) - span.set_data(SPANDATA.HTTP_QUERY, parsed_url.query) - - set_on_span = span.set_data + if parsed_url is not None and should_send_default_pii(): + span.set_attribute(SPANDATA.URL_FRAGMENT, parsed_url.fragment) + span.set_attribute(SPANDATA.URL_FULL, parsed_url.url) + span.set_attribute(SPANDATA.URL_QUERY, parsed_url.query) # for proxies, these point to the proxy host/port if span and tunnel_host: - set_on_span(SPANDATA.NETWORK_PEER_ADDRESS, self.host) - set_on_span(SPANDATA.NETWORK_PEER_PORT, self.port) + span.set_attribute(SPANDATA.NETWORK_PEER_ADDRESS, self.host) + span.set_attribute(SPANDATA.NETWORK_PEER_PORT, self.port) rv = real_putrequest(self, method, url, *args, **kwargs) @@ -189,13 +163,9 @@ def getresponse(self: "HTTPConnection", *args: "Any", **kwargs: "Any") -> "Any": _complete_span(span) raise - if isinstance(span, StreamedSpan): - status_code = int(rv.status) - span.status = "error" if status_code >= 400 else "ok" - span.set_attribute("http.response.status_code", status_code) - else: - span.set_http_status(int(rv.status)) - span.set_data("reason", rv.reason) + status_code = int(rv.status) + span.status = "error" if status_code >= 400 else "ok" + span.set_attribute("http.response.status_code", status_code) # getresponse doesn't include actually reading the response body. This # is done in read(). So if the metadata/headers suggest there's a body to @@ -285,7 +255,7 @@ def sentry_patched_popen_init( a = list(a) args = _init_argument(a, kw, "args", 0) or [] - cwd = _init_argument(a, kw, "cwd", 9) + _init_argument(a, kw, "cwd", 9) # if args is not a list or tuple (and e.g. some iterator instead), # let's not use it at all. There are too many things that can go wrong @@ -305,25 +275,16 @@ def sentry_patched_popen_init( env = None - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - span: "Union[Span, StreamedSpan]" - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return old_popen_init(self, *a, **kw) + if sentry_sdk.traces.get_current_span() is None: + return old_popen_init(self, *a, **kw) - span = sentry_sdk.traces.start_span( - name=description, - attributes={ - "sentry.op": OP.SUBPROCESS, - "sentry.origin": "auto.subprocess.stdlib.subprocess", - }, - ) - else: - span = sentry_sdk.start_span( - op=OP.SUBPROCESS, - name=description, - origin="auto.subprocess.stdlib.subprocess", - ) + span = sentry_sdk.traces.start_span( + name=description, + attributes={ + "sentry.op": OP.SUBPROCESS, + "sentry.origin": "auto.subprocess.stdlib.subprocess", + }, + ) with span: for k, v in sentry_sdk.get_current_scope().iter_trace_propagation_headers( @@ -339,15 +300,9 @@ def sentry_patched_popen_init( ) env["SUBPROCESS_" + k.upper().replace("-", "_")] = v - if cwd and isinstance(span, Span): - span.set_data("subprocess.cwd", cwd) - rv = old_popen_init(self, *a, **kw) - if isinstance(span, StreamedSpan): - span.set_attribute(SPANDATA.PROCESS_PID, self.pid) - else: - span.set_tag("subprocess.pid", self.pid) + span.set_attribute(SPANDATA.PROCESS_PID, self.pid) return rv @@ -359,26 +314,17 @@ def sentry_patched_popen_init( def sentry_patched_popen_wait( self: "subprocess.Popen[Any]", *a: "Any", **kw: "Any" ) -> "Any": - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return old_popen_wait(self, *a, **kw) - with sentry_sdk.traces.start_span( - name=OP.SUBPROCESS_WAIT, - attributes={ - "sentry.op": OP.SUBPROCESS_WAIT, - "sentry.origin": "auto.subprocess.stdlib.subprocess", - }, - ) as span: - span.set_attribute(SPANDATA.PROCESS_PID, self.pid) - return old_popen_wait(self, *a, **kw) - else: - with sentry_sdk.start_span( - op=OP.SUBPROCESS_WAIT, - origin="auto.subprocess.stdlib.subprocess", - ) as span: - span.set_tag("subprocess.pid", self.pid) - return old_popen_wait(self, *a, **kw) + if sentry_sdk.traces.get_current_span() is None: + return old_popen_wait(self, *a, **kw) + with sentry_sdk.traces.start_span( + name=OP.SUBPROCESS_WAIT, + attributes={ + "sentry.op": OP.SUBPROCESS_WAIT, + "sentry.origin": "auto.subprocess.stdlib.subprocess", + }, + ) as span: + span.set_attribute(SPANDATA.PROCESS_PID, self.pid) + return old_popen_wait(self, *a, **kw) subprocess.Popen.wait = sentry_patched_popen_wait # type: ignore @@ -388,26 +334,17 @@ def sentry_patched_popen_wait( def sentry_patched_popen_communicate( self: "subprocess.Popen[Any]", *a: "Any", **kw: "Any" ) -> "Any": - span_streaming = has_span_streaming_enabled(sentry_sdk.get_client().options) - if span_streaming: - if sentry_sdk.traces.get_current_span() is None: - return old_popen_communicate(self, *a, **kw) - with sentry_sdk.traces.start_span( - name=OP.SUBPROCESS_COMMUNICATE, - attributes={ - "sentry.op": OP.SUBPROCESS_COMMUNICATE, - "sentry.origin": "auto.subprocess.stdlib.subprocess", - }, - ) as span: - span.set_attribute(SPANDATA.PROCESS_PID, self.pid) - return old_popen_communicate(self, *a, **kw) - else: - with sentry_sdk.start_span( - op=OP.SUBPROCESS_COMMUNICATE, - origin="auto.subprocess.stdlib.subprocess", - ) as span: - span.set_tag("subprocess.pid", self.pid) - return old_popen_communicate(self, *a, **kw) + if sentry_sdk.traces.get_current_span() is None: + return old_popen_communicate(self, *a, **kw) + with sentry_sdk.traces.start_span( + name=OP.SUBPROCESS_COMMUNICATE, + attributes={ + "sentry.op": OP.SUBPROCESS_COMMUNICATE, + "sentry.origin": "auto.subprocess.stdlib.subprocess", + }, + ) as span: + span.set_attribute(SPANDATA.PROCESS_PID, self.pid) + return old_popen_communicate(self, *a, **kw) subprocess.Popen.communicate = sentry_patched_popen_communicate # type: ignore diff --git a/sentry_sdk/integrations/strawberry.py b/sentry_sdk/integrations/strawberry.py index d3cb77cc4f..55a69c818a 100644 --- a/sentry_sdk/integrations/strawberry.py +++ b/sentry_sdk/integrations/strawberry.py @@ -9,8 +9,7 @@ from sentry_sdk.integrations.logging import ignore_logger from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import SegmentNameSource -from sentry_sdk.tracing import Span, TransactionSource -from sentry_sdk.tracing_utils import StreamedSpan, has_span_streaming_enabled +from sentry_sdk.tracing_utils import StreamedSpan from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -187,55 +186,30 @@ def on_operation(self) -> "Generator[None, None, None]": scope.add_event_processor(event_processor) client = sentry_sdk.get_client() - is_span_streaming_enabled = has_span_streaming_enabled(client.options) - if is_span_streaming_enabled: - if sentry_sdk.traces.get_current_span() is None: - yield - return - - additional_attributes: "dict[str, Any]" = {} - if has_data_collection_enabled(client.options): - if client.options["data_collection"]["graphql"]["document"]: - additional_attributes["graphql.document"] = ( - self.execution_context.query - ) + if sentry_sdk.traces.get_current_span() is None: + yield + return - elif should_send_default_pii(): + additional_attributes: "dict[str, Any]" = {} + if has_data_collection_enabled(client.options): + if client.options["data_collection"]["graphql"]["document"]: additional_attributes["graphql.document"] = self.execution_context.query - if operation_name: - additional_attributes["graphql.operation.name"] = operation_name - - graphql_span = sentry_sdk.traces.start_span( - name=description, - attributes={ - "sentry.origin": StrawberryIntegration.origin, - "sentry.op": op, - "graphql.operation.type": operation_type, - **additional_attributes, - }, - ) - else: - graphql_span = sentry_sdk.start_span( - op=op, - name=description, - origin=StrawberryIntegration.origin, - ) - graphql_span.__enter__() - - if type(graphql_span) is Span: - if has_data_collection_enabled(client.options): - if client.options["data_collection"]["graphql"]["document"]: - graphql_span.set_data( - "graphql.document", self.execution_context.query - ) - elif should_send_default_pii(): - graphql_span.set_data("graphql.document", self.execution_context.query) + elif should_send_default_pii(): + additional_attributes["graphql.document"] = self.execution_context.query - graphql_span.set_data("graphql.operation.type", operation_type) - graphql_span.set_data("graphql.operation.name", operation_name) - # This attribute is being removed in streamed spans - graphql_span.set_data("graphql.resource_name", self._resource_name) + if operation_name: + additional_attributes["graphql.operation.name"] = operation_name + + graphql_span = sentry_sdk.traces.start_span( + name=description, + attributes={ + "sentry.origin": StrawberryIntegration.origin, + "sentry.op": op, + "graphql.operation.type": operation_type, + **additional_attributes, + }, + ) yield @@ -247,78 +221,46 @@ def on_operation(self) -> "Generator[None, None, None]": ) segment.set_attribute("sentry.op", op) segment.name = self.execution_context.operation_name - elif isinstance(graphql_span, Span): - transaction = graphql_span.containing_transaction - if transaction and self.execution_context.operation_name: - transaction.name = self.execution_context.operation_name - transaction.source = TransactionSource.COMPONENT - transaction.op = op graphql_span.__exit__(None, None, None) def on_validate(self) -> "Generator[None, None, None]": - client = sentry_sdk.get_client() - is_span_streaming_enabled = has_span_streaming_enabled(client.options) - - if is_span_streaming_enabled: - if sentry_sdk.traces.get_current_span() is None: - yield - return - - validation_span = sentry_sdk.traces.start_span( - name="validation", - attributes={ - "sentry.op": OP.GRAPHQL_VALIDATE, - "sentry.origin": StrawberryIntegration.origin, - }, - ) - else: - validation_span = sentry_sdk.start_span( - op=OP.GRAPHQL_VALIDATE, - name="validation", - origin=StrawberryIntegration.origin, - ) + if sentry_sdk.traces.get_current_span() is None: + yield + return + + validation_span = sentry_sdk.traces.start_span( + name="validation", + attributes={ + "sentry.op": OP.GRAPHQL_VALIDATE, + "sentry.origin": StrawberryIntegration.origin, + }, + ) # If an exception is raised during validation, we still need to close the span try: yield finally: - if isinstance(validation_span, StreamedSpan): - validation_span.end() - else: - validation_span.finish() + validation_span.end() def on_parse(self) -> "Generator[None, None, None]": - client = sentry_sdk.get_client() - is_span_streaming_enabled = has_span_streaming_enabled(client.options) - - if is_span_streaming_enabled: - if sentry_sdk.traces.get_current_span() is None: - yield - return - - parsing_span = sentry_sdk.traces.start_span( - name="parsing", - attributes={ - "sentry.op": OP.GRAPHQL_PARSE, - "sentry.origin": StrawberryIntegration.origin, - }, - ) - else: - parsing_span = sentry_sdk.start_span( - op=OP.GRAPHQL_PARSE, - name="parsing", - origin=StrawberryIntegration.origin, - ) + if sentry_sdk.traces.get_current_span() is None: + yield + return + + parsing_span = sentry_sdk.traces.start_span( + name="parsing", + attributes={ + "sentry.op": OP.GRAPHQL_PARSE, + "sentry.origin": StrawberryIntegration.origin, + }, + ) # If an exception is raised during parsing, we still need to close the span try: yield finally: - if isinstance(parsing_span, StreamedSpan): - parsing_span.end() - else: - parsing_span.finish() + parsing_span.end() def should_skip_tracing( self, @@ -355,31 +297,16 @@ async def resolve( field_path = "{}.{}".format(info.parent_type, info.field_name) - client = sentry_sdk.get_client() - is_span_streaming_enabled = has_span_streaming_enabled(client.options) - if is_span_streaming_enabled: - if sentry_sdk.traces.get_current_span() is None: - return await self._resolve(_next, root, info, *args, **kwargs) - - with sentry_sdk.traces.start_span( - name=f"resolving {field_path}", - attributes={ - "sentry.origin": StrawberryIntegration.origin, - "sentry.op": OP.GRAPHQL_RESOLVE, - }, - ): - return await self._resolve(_next, root, info, *args, **kwargs) - - with sentry_sdk.start_span( - op=OP.GRAPHQL_RESOLVE, - name="resolving {}".format(field_path), - origin=StrawberryIntegration.origin, - ) as span: - span.set_data("graphql.field_name", info.field_name) - span.set_data("graphql.parent_type", info.parent_type.name) - span.set_data("graphql.field_path", field_path) - span.set_data("graphql.path", ".".join(map(str, info.path.as_list()))) + if sentry_sdk.traces.get_current_span() is None: + return await self._resolve(_next, root, info, *args, **kwargs) + with sentry_sdk.traces.start_span( + name=f"resolving {field_path}", + attributes={ + "sentry.origin": StrawberryIntegration.origin, + "sentry.op": OP.GRAPHQL_RESOLVE, + }, + ): return await self._resolve(_next, root, info, *args, **kwargs) @@ -397,31 +324,16 @@ def resolve( field_path = "{}.{}".format(info.parent_type, info.field_name) - client = sentry_sdk.get_client() - is_span_streaming_enabled = has_span_streaming_enabled(client.options) - if is_span_streaming_enabled: - if sentry_sdk.traces.get_current_span() is None: - return _next(root, info, *args, **kwargs) - - with sentry_sdk.traces.start_span( - name=f"resolving {field_path}", - attributes={ - "sentry.origin": StrawberryIntegration.origin, - "sentry.op": OP.GRAPHQL_RESOLVE, - }, - ): - return _next(root, info, *args, **kwargs) - - with sentry_sdk.start_span( - op=OP.GRAPHQL_RESOLVE, - name="resolving {}".format(field_path), - origin=StrawberryIntegration.origin, - ) as span: - span.set_data("graphql.field_name", info.field_name) - span.set_data("graphql.parent_type", info.parent_type.name) - span.set_data("graphql.field_path", field_path) - span.set_data("graphql.path", ".".join(map(str, info.path.as_list()))) + if sentry_sdk.traces.get_current_span() is None: + return _next(root, info, *args, **kwargs) + with sentry_sdk.traces.start_span( + name=f"resolving {field_path}", + attributes={ + "sentry.origin": StrawberryIntegration.origin, + "sentry.op": OP.GRAPHQL_RESOLVE, + }, + ): return _next(root, info, *args, **kwargs) diff --git a/sentry_sdk/integrations/tornado.py b/sentry_sdk/integrations/tornado.py index e71bf94d12..fd808e4a64 100644 --- a/sentry_sdk/integrations/tornado.py +++ b/sentry_sdk/integrations/tornado.py @@ -3,7 +3,6 @@ from inspect import iscoroutinefunction import sentry_sdk -from sentry_sdk.api import continue_trace from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.data_collection import _apply_data_collection_filtering_to_query_string from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version @@ -17,7 +16,6 @@ from sentry_sdk.scope import should_send_default_pii from sentry_sdk.traces import SegmentNameSource, StreamedSpan from sentry_sdk.tracing import TransactionSource -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( CONTEXTVARS_ERROR_MESSAGE, HAS_REAL_CONTEXTVARS, @@ -40,10 +38,9 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from typing import Any, Callable, ContextManager, Dict, Generator, Optional, Union + from typing import Any, Callable, Dict, Generator, Optional, Union from sentry_sdk._types import Event, EventProcessor - from sentry_sdk.tracing import Span class TornadoIntegration(Integration): @@ -118,7 +115,6 @@ def _handle_request_impl(self: "RequestHandler") -> "Generator[None, None, None] weak_handler = weakref.ref(self) client = sentry_sdk.get_client() - is_span_streaming_enabled = has_span_streaming_enabled(client.options) with sentry_sdk.isolation_scope() as scope: headers = self.request.headers @@ -127,50 +123,27 @@ def _handle_request_impl(self: "RequestHandler") -> "Generator[None, None, None] processor = _make_event_processor(weak_handler) scope.add_event_processor(processor) - span_ctx: "ContextManager[Union[Span, StreamedSpan, None]]" + sentry_sdk.traces.continue_trace(dict(headers)) + scope.set_custom_sampling_context({"tornado_request": self.request}) - if is_span_streaming_enabled: - sentry_sdk.traces.continue_trace(dict(headers)) - scope.set_custom_sampling_context({"tornado_request": self.request}) - - if self.request.remote_ip: - if has_data_collection_enabled(client.options): - if client.options["data_collection"]["user_info"]: - scope.set_attribute( - SPANDATA.USER_IP_ADDRESS, self.request.remote_ip - ) - elif should_send_default_pii(): + if self.request.remote_ip: + if has_data_collection_enabled(client.options): + if client.options["data_collection"]["user_info"]: scope.set_attribute( SPANDATA.USER_IP_ADDRESS, self.request.remote_ip ) - - span_ctx = sentry_sdk.traces.start_span( - name=_DEFAULT_ROOT_SPAN_NAME, - attributes={ - "sentry.op": OP.HTTP_SERVER, - "sentry.origin": TornadoIntegration.origin, - "sentry.segment.name.source": SegmentNameSource.ROUTE, - }, - parent_span=None, - ) - else: - transaction = continue_trace( - headers, - op=OP.HTTP_SERVER, - # Like with all other integrations, this is our - # fallback transaction in case there is no route. - # sentry_urldispatcher_resolve is responsible for - # setting a transaction name later. - name=_DEFAULT_ROOT_SPAN_NAME, - source=TransactionSource.ROUTE, - origin=TornadoIntegration.origin, - ) - span_ctx = sentry_sdk.start_transaction( - transaction, - custom_sampling_context={"tornado_request": self.request}, - ) - - with span_ctx as span: + elif should_send_default_pii(): + scope.set_attribute(SPANDATA.USER_IP_ADDRESS, self.request.remote_ip) + + with sentry_sdk.traces.start_span( + name=_DEFAULT_ROOT_SPAN_NAME, + attributes={ + "sentry.op": OP.HTTP_SERVER, + "sentry.origin": TornadoIntegration.origin, + "sentry.segment.name.source": SegmentNameSource.ROUTE, + }, + parent_span=None, + ) as span: try: yield finally: diff --git a/sentry_sdk/integrations/wsgi.py b/sentry_sdk/integrations/wsgi.py index b0156a9829..1290ab24e1 100644 --- a/sentry_sdk/integrations/wsgi.py +++ b/sentry_sdk/integrations/wsgi.py @@ -4,7 +4,6 @@ import sentry_sdk from sentry_sdk._werkzeug import _get_headers, get_host -from sentry_sdk.api import continue_trace from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.data_collection import _apply_data_collection_filtering_to_query_string from sentry_sdk.integrations._wsgi_common import ( @@ -14,8 +13,6 @@ from sentry_sdk.scope import Scope, should_send_default_pii, use_isolation_scope from sentry_sdk.sessions import track_session from sentry_sdk.traces import SegmentNameSource, StreamedSpan -from sentry_sdk.tracing import Span, TransactionSource -from sentry_sdk.tracing_utils import has_span_streaming_enabled from sentry_sdk.utils import ( ContextVar, capture_internal_exceptions, @@ -36,7 +33,6 @@ Protocol, Tuple, TypeVar, - Union, ) from sentry_sdk._types import Event, EventProcessor @@ -111,7 +107,6 @@ def __call__( return self.app(environ, start_response) client = sentry_sdk.get_client() - span_streaming = has_span_streaming_enabled(client.options) _wsgi_middleware_applied.set(True) try: @@ -128,50 +123,32 @@ def __call__( method = environ.get("REQUEST_METHOD", "").upper() - span_ctx: "Optional[ContextManager[Union[Span, StreamedSpan, None]]]" = None + span_ctx: "Optional[ContextManager[Optional[StreamedSpan]]]" = None if method in self.http_methods_to_capture: - if span_streaming: - sentry_sdk.traces.continue_trace( - dict(_get_headers(environ)) - ) - Scope.set_custom_sampling_context({"wsgi_environ": environ}) - - if has_data_collection_enabled(client.options): - if client.options["data_collection"]["user_info"]: - client_ip = get_client_ip(environ) - if client_ip: - scope.set_attribute( - SPANDATA.USER_IP_ADDRESS, client_ip - ) - elif should_send_default_pii(): + sentry_sdk.traces.continue_trace(dict(_get_headers(environ))) + Scope.set_custom_sampling_context({"wsgi_environ": environ}) + + if has_data_collection_enabled(client.options): + if client.options["data_collection"]["user_info"]: client_ip = get_client_ip(environ) if client_ip: scope.set_attribute( SPANDATA.USER_IP_ADDRESS, client_ip ) - - span_ctx = sentry_sdk.traces.start_span( - name=_DEFAULT_TRANSACTION_NAME, - attributes={ - "sentry.segment.name.source": SegmentNameSource.ROUTE, - "sentry.origin": self.span_origin, - "sentry.op": OP.HTTP_SERVER, - }, - parent_span=None, - ) - else: - transaction = continue_trace( - environ, - op=OP.HTTP_SERVER, - name=_DEFAULT_TRANSACTION_NAME, - source=TransactionSource.ROUTE, - origin=self.span_origin, - ) - - span_ctx = sentry_sdk.start_transaction( - transaction, - custom_sampling_context={"wsgi_environ": environ}, - ) + elif should_send_default_pii(): + client_ip = get_client_ip(environ) + if client_ip: + scope.set_attribute(SPANDATA.USER_IP_ADDRESS, client_ip) + + span_ctx = sentry_sdk.traces.start_span( + name=_DEFAULT_TRANSACTION_NAME, + attributes={ + "sentry.segment.name.source": SegmentNameSource.ROUTE, + "sentry.origin": self.span_origin, + "sentry.op": OP.HTTP_SERVER, + }, + parent_span=None, + ) span_ctx = span_ctx or nullcontext() @@ -221,7 +198,7 @@ def __call__( def _sentry_start_response( old_start_response: "StartResponse", - span: "Optional[Union[Span, StreamedSpan]]", + span: "Optional[StreamedSpan]", status: str, response_headers: "WsgiResponseHeaders", exc_info: "Optional[WsgiExcInfo]" = None, @@ -229,11 +206,8 @@ def _sentry_start_response( with capture_internal_exceptions(): status_int = int(status.split(" ", 1)[0]) if span is not None: - if isinstance(span, StreamedSpan): - span.status = "error" if status_int >= 400 else "ok" - span.set_attribute("http.response.status_code", status_int) - else: - span.set_http_status(status_int) + span.status = "error" if status_int >= 400 else "ok" + span.set_attribute("http.response.status_code", status_int) if exc_info is None: # The Django Rest Framework WSGI test client, and likely other diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py index 105edb0ec7..a7d9590b17 100644 --- a/sentry_sdk/tracing_utils.py +++ b/sentry_sdk/tracing_utils.py @@ -106,29 +106,6 @@ def has_tracing_enabled(options: "Optional[Dict[str, Any]]") -> bool: ) -def has_span_streaming_enabled(options: "Optional[dict[str, Any]]") -> bool: - if options is None: - return False - - is_enabled_in_experiment_config = (options.get("_experiments") or {}).get( - "trace_lifecycle" - ) == "stream" - - if options.get("trace_lifecycle") is not None: - return options.get("trace_lifecycle") == "stream" - - return is_enabled_in_experiment_config - - -def should_truncate_gen_ai_input(options: "Optional[dict[str, Any]]") -> bool: - if options is None: - return True - - return not options.get( - "stream_gen_ai_spans", True - ) and not has_span_streaming_enabled(options) - - @contextlib.contextmanager def record_sql_queries( cursor: "Any", @@ -167,31 +144,19 @@ def record_sql_queries( with capture_internal_exceptions(): sentry_sdk.add_breadcrumb(message=query, category="query", data=data) - if has_span_streaming_enabled(client.options): - additional_attributes = {} - if query is not None: - additional_attributes["db.query.text"] = query - - with sentry_sdk.traces.start_span( - name="" if query is None else query, - attributes={ - "sentry.origin": span_origin, - "sentry.op": span_op_override_value - if span_op_override_value - else OP.DB, - **additional_attributes, - }, - ) as span: - yield span - else: - with sentry_sdk.start_span( - op=span_op_override_value if span_op_override_value is not None else OP.DB, - name=query, - origin=span_origin, - ) as span: - for k, v in data.items(): - span.set_data(k, v) - yield span + additional_attributes = {} + if query is not None: + additional_attributes["db.query.text"] = query + + with sentry_sdk.traces.start_span( + name="" if query is None else query, + attributes={ + "sentry.origin": span_origin, + "sentry.op": span_op_override_value if span_op_override_value else OP.DB, + **additional_attributes, + }, + ) as span: + yield span def maybe_create_breadcrumbs_from_span( @@ -1162,14 +1127,6 @@ def span_decorator(f: "Any") -> "Any": @functools.wraps(f) async def async_wrapper(*args: "Any", **kwargs: "Any") -> "Any": - client = sentry_sdk.get_client() - if client.is_active() and not has_span_streaming_enabled(client.options): - warnings.warn( - "Using span streaming API in non-span-streaming mode. Use " - "@sentry_sdk.trace instead.", - stacklevel=2, - ) - span_name = name or qualname_from_function(f) or "" with start_streaming_span( @@ -1185,14 +1142,6 @@ async def async_wrapper(*args: "Any", **kwargs: "Any") -> "Any": @functools.wraps(f) def sync_wrapper(*args: "Any", **kwargs: "Any") -> "Any": - client = sentry_sdk.get_client() - if client.is_active() and not has_span_streaming_enabled(client.options): - warnings.warn( - "Using span streaming API in non-span-streaming mode. Use " - "@sentry_sdk.trace instead.", - stacklevel=2, - ) - span_name = name or qualname_from_function(f) or "" with start_streaming_span(