From 68c57a54c36a059840b19cc45d831e651f2efd42 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Tue, 15 Sep 2026 13:12:51 +0200 Subject: [PATCH 1/5] chore: More transaction cleanup --- sentry_sdk/_types.py | 2 +- sentry_sdk/ai/monitoring.py | 4 +- sentry_sdk/ai/utils.py | 4 +- sentry_sdk/api.py | 6 +- sentry_sdk/client.py | 12 ++-- sentry_sdk/consts.py | 1 - sentry_sdk/integrations/aiohttp.py | 4 +- sentry_sdk/integrations/aiomysql.py | 10 +-- sentry_sdk/integrations/anthropic.py | 22 +++--- sentry_sdk/integrations/arq.py | 2 +- sentry_sdk/integrations/asgi.py | 4 +- sentry_sdk/integrations/asyncpg.py | 6 +- sentry_sdk/integrations/boto3.py | 8 +-- sentry_sdk/integrations/celery/__init__.py | 6 +- sentry_sdk/integrations/chalice.py | 4 +- sentry_sdk/integrations/clickhouse_driver.py | 6 +- sentry_sdk/integrations/cohere.py | 4 +- sentry_sdk/integrations/django/__init__.py | 4 +- sentry_sdk/integrations/django/asgi.py | 4 +- sentry_sdk/integrations/django/middleware.py | 4 +- sentry_sdk/integrations/django/views.py | 4 +- sentry_sdk/integrations/fastapi.py | 6 +- .../integrations/google_genai/streaming.py | 4 +- sentry_sdk/integrations/google_genai/utils.py | 12 ++-- sentry_sdk/integrations/huey.py | 6 +- sentry_sdk/integrations/langchain.py | 16 ++--- sentry_sdk/integrations/langgraph.py | 6 +- sentry_sdk/integrations/mcp.py | 4 +- sentry_sdk/integrations/openai.py | 28 ++++---- .../openai_agents/patches/agent_run.py | 4 +- .../openai_agents/patches/error_tracing.py | 2 +- .../openai_agents/patches/models.py | 4 +- .../openai_agents/spans/agent_workflow.py | 2 +- .../openai_agents/spans/ai_client.py | 4 +- .../openai_agents/spans/execute_tool.py | 6 +- .../openai_agents/spans/invoke_agent.py | 6 +- .../integrations/openai_agents/utils.py | 10 +-- .../pydantic_ai/spans/ai_client.py | 8 +-- .../pydantic_ai/spans/execute_tool.py | 6 +- .../pydantic_ai/spans/invoke_agent.py | 6 +- .../integrations/pydantic_ai/spans/utils.py | 4 +- sentry_sdk/integrations/pydantic_ai/utils.py | 8 +-- sentry_sdk/integrations/pymongo.py | 4 +- sentry_sdk/integrations/quart.py | 4 +- .../integrations/redis/_async_common.py | 8 +-- sentry_sdk/integrations/redis/_sync_common.py | 8 +-- .../integrations/redis/modules/caches.py | 4 +- .../integrations/redis/modules/queries.py | 6 +- .../integrations/redis/redis_cluster.py | 8 +-- sentry_sdk/integrations/redis/utils.py | 4 +- sentry_sdk/integrations/rq.py | 2 +- sentry_sdk/integrations/rust_tracing.py | 10 +-- sentry_sdk/integrations/sqlalchemy.py | 8 +-- sentry_sdk/integrations/starlette.py | 6 +- sentry_sdk/integrations/stdlib.py | 6 +- sentry_sdk/integrations/wsgi.py | 6 +- sentry_sdk/scope.py | 68 +++++++++---------- sentry_sdk/traces.py | 49 ++++++------- sentry_sdk/tracing_utils.py | 12 ++-- tests/conftest.py | 19 ++---- tests/integrations/aiohttp/test_aiohttp.py | 2 +- tests/integrations/django/test_basic.py | 4 +- tests/test_api.py | 18 ++--- tests/tracing/test_http_headers.py | 4 +- tests/tracing/test_misc.py | 12 ++-- tests/tracing/test_sampling.py | 4 +- tests/tracing/test_span_streaming.py | 28 ++++---- 67 files changed, 285 insertions(+), 292 deletions(-) diff --git a/sentry_sdk/_types.py b/sentry_sdk/_types.py index 4634a88156..3a32e379d4 100644 --- a/sentry_sdk/_types.py +++ b/sentry_sdk/_types.py @@ -367,7 +367,7 @@ class DataCollection(TypedDict): "start_timestamp": float, "end_timestamp": NotRequired[float], "attributes": NotRequired[Attributes], - "_segment_span": NotRequired["sentry_sdk.traces.StreamedSpan"], + "_segment_span": NotRequired["sentry_sdk.traces.Span"], }, ) diff --git a/sentry_sdk/ai/monitoring.py b/sentry_sdk/ai/monitoring.py index 9c9eb2856c..d0664adac4 100644 --- a/sentry_sdk/ai/monitoring.py +++ b/sentry_sdk/ai/monitoring.py @@ -5,13 +5,13 @@ if TYPE_CHECKING: from typing import Any, Awaitable, Callable, Optional, TypeVar, Union - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span F = TypeVar("F", bound=Union[Callable[..., Any], Callable[..., Awaitable[Any]]]) def record_token_usage( - span: "StreamedSpan", + span: "Span", input_tokens: "Optional[int]" = None, input_tokens_cached: "Optional[int]" = None, input_tokens_cache_write: "Optional[int]" = None, diff --git a/sentry_sdk/ai/utils.py b/sentry_sdk/ai/utils.py index 006c05bec3..4ec9806da8 100644 --- a/sentry_sdk/ai/utils.py +++ b/sentry_sdk/ai/utils.py @@ -5,7 +5,7 @@ if TYPE_CHECKING: from typing import Any, Dict, Optional, Tuple - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span import sentry_sdk from sentry_sdk.utils import logger @@ -448,7 +448,7 @@ def _normalize_data(data: "Any", unpack: bool = True) -> "Any": def set_data_normalized( - span: "StreamedSpan", + span: "Span", key: str, value: "Any", unpack: bool = True, diff --git a/sentry_sdk/api.py b/sentry_sdk/api.py index bae0526442..f89aeea809 100644 --- a/sentry_sdk/api.py +++ b/sentry_sdk/api.py @@ -28,7 +28,7 @@ LogLevelStr, ) from sentry_sdk.client import BaseClient - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span T = TypeVar("T") F = TypeVar("F", bound=Callable[..., Any]) @@ -267,11 +267,11 @@ async def flush_async( @scopemethod -def start_span(**kwargs: "Any") -> "StreamedSpan": +def start_span(**kwargs: "Any") -> "Span": return traces.start_span(**kwargs) -def get_current_span(scope: "Optional[Scope]" = None) -> "Optional[StreamedSpan]": +def get_current_span(scope: "Optional[Scope]" = None) -> "Optional[Span]": """ Returns the currently active span if there is one running, otherwise `None` """ diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index e2a63c1794..9114cf6b67 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -30,7 +30,7 @@ from sentry_sdk.scrubber import EventScrubber from sentry_sdk.serializer import serialize from sentry_sdk.sessions import SessionFlusher -from sentry_sdk.traces import StreamedSpan, trace +from sentry_sdk.traces import Span, trace from sentry_sdk.transport import ( AsyncHttpTransport, HttpTransportCore, @@ -70,7 +70,7 @@ from sentry_sdk.scope import Scope from sentry_sdk.session import Session from sentry_sdk.spotlight import SpotlightClient - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span from sentry_sdk.transport import Item, Transport from sentry_sdk.utils import Dsn @@ -215,7 +215,7 @@ def _capture_log(self, log: "Log", scope: "Scope") -> None: def _capture_metric(self, metric: "Metric", scope: "Scope") -> None: pass - def _capture_span(self, span: "StreamedSpan", scope: "Scope") -> None: + def _capture_span(self, span: "Span", scope: "Scope") -> None: pass def capture_session(self, *args: "Any", **kwargs: "Any") -> None: @@ -815,7 +815,7 @@ def capture_event( def _capture_telemetry( self, - telemetry: "Optional[Union[Log, Metric, StreamedSpan]]", + telemetry: "Optional[Union[Log, Metric, Span]]", ty: str, scope: "Scope", ) -> None: @@ -864,7 +864,7 @@ def _capture_telemetry( if serialized is None: return - elif ty == "span" and isinstance(telemetry, StreamedSpan): + elif ty == "span" and isinstance(telemetry, Span): # Reset the span to its original value before we attempted # to call the `before_send_span` callback if exception_raised_in_before_send_func: @@ -908,7 +908,7 @@ def _capture_log(self, log: "Optional[Log]", scope: "Scope") -> None: def _capture_metric(self, metric: "Optional[Metric]", scope: "Scope") -> None: self._capture_telemetry(metric, "metric", scope) - def _capture_span(self, span: "Optional[StreamedSpan]", scope: "Scope") -> None: + def _capture_span(self, span: "Optional[Span]", scope: "Scope") -> None: self._capture_telemetry(span, "span", scope) def capture_session( diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py index 665362f87a..3f3232d79f 100644 --- a/sentry_sdk/consts.py +++ b/sentry_sdk/consts.py @@ -1313,7 +1313,6 @@ def __init__( before_send_span: "Optional[Callable[[SpanJSON, Hint], Optional[SpanJSON]]]" = None, org_id: "Optional[str]" = None, strict_trace_continuation: bool = False, - stream_gen_ai_spans: bool = True, ) -> None: """Initialize the Sentry SDK with the given parameters. All parameters described here can be used in a call to `sentry_sdk.init()`. diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py index 9970dda6c7..48a91949e1 100644 --- a/sentry_sdk/integrations/aiohttp.py +++ b/sentry_sdk/integrations/aiohttp.py @@ -23,7 +23,7 @@ from sentry_sdk.traces import ( SegmentNameSource, SpanStatus, - StreamedSpan, + Span, ) from sentry_sdk.tracing import ( BAGGAGE_HEADER_NAME, @@ -342,7 +342,7 @@ async def on_request_start( parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE, ) - span: "Optional[StreamedSpan]" = None + span: "Optional[Span]" = None attributes: "Attributes" = { "sentry.op": OP.HTTP_CLIENT, "sentry.origin": AioHttpIntegration.origin, diff --git a/sentry_sdk/integrations/aiomysql.py b/sentry_sdk/integrations/aiomysql.py index d8d637c0c9..e85baa0b1a 100644 --- a/sentry_sdk/integrations/aiomysql.py +++ b/sentry_sdk/integrations/aiomysql.py @@ -6,7 +6,7 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.tracing_utils import ( add_query_source, record_sql_queries, @@ -105,11 +105,11 @@ async def _inner(*args: Any, **kwargs: Any) -> T: if conn: _set_db_data(span, conn) res = await f(*args, **kwargs) - if isinstance(span, StreamedSpan): + if isinstance(span, Span): with capture_internal_exceptions(): add_query_source(span) - if not isinstance(span, StreamedSpan): + if not isinstance(span, Span): with capture_internal_exceptions(): add_query_source(span) @@ -158,11 +158,11 @@ async def _inner(*args: Any, **kwargs: Any) -> T: if conn: _set_db_data(span, conn) res = await f(*args, **kwargs) - if isinstance(span, StreamedSpan): + if isinstance(span, Span): with capture_internal_exceptions(): add_query_source(span) - if not isinstance(span, StreamedSpan): + if not isinstance(span, Span): with capture_internal_exceptions(): add_query_source(span) diff --git a/sentry_sdk/integrations/anthropic.py b/sentry_sdk/integrations/anthropic.py index 984b60ff39..070fbbb0cc 100644 --- a/sentry_sdk/integrations/anthropic.py +++ b/sentry_sdk/integrations/anthropic.py @@ -15,7 +15,7 @@ from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.utils import ( capture_internal_exceptions, event_from_exception, @@ -83,7 +83,7 @@ from sentry_sdk._types import TextPart class _PatchedRawMessageStream(Stream[RawMessageStreamEvent]): - _span: StreamedSpan + _span: Span _integration: "AnthropicIntegration" _model: Optional[ModelParam] @@ -93,7 +93,7 @@ class _PatchedRawMessageStream(Stream[RawMessageStreamEvent]): _finish_reason: Optional[str] class _PatchedMessageStream(MessageStream): - _span: StreamedSpan + _span: Span _integration: "AnthropicIntegration" _model: Optional[ModelParam] @@ -103,7 +103,7 @@ class _PatchedMessageStream(MessageStream): _finish_reason: Optional[str] class _PatchedRawAsyncMessageStream(AsyncStream[RawMessageStreamEvent]): - _span: StreamedSpan + _span: Span _integration: "AnthropicIntegration" _model: Optional[ModelParam] @@ -113,7 +113,7 @@ class _PatchedRawAsyncMessageStream(AsyncStream[RawMessageStreamEvent]): _finish_reason: Optional[str] class _PatchedAsyncMessageStream(AsyncMessageStream): - _span: StreamedSpan + _span: Span _integration: "AnthropicIntegration" _model: Optional[ModelParam] @@ -123,7 +123,7 @@ class _PatchedAsyncMessageStream(AsyncMessageStream): _finish_reason: Optional[str] class _PatchedMessageStreamManager(MessageStreamManager): - _span: StreamedSpan + _span: Span _integration: "AnthropicIntegration" _max_tokens: int @@ -136,7 +136,7 @@ class _PatchedMessageStreamManager(MessageStreamManager): _tools: Optional[Iterable[ToolUnionParam]] class _PatchedAsyncMessageStreamManager(AsyncMessageStreamManager[Any]): - _span: StreamedSpan + _span: Span _integration: "AnthropicIntegration" _max_tokens: int @@ -441,7 +441,7 @@ def _transform_system_instructions( def _set_common_input_data( - span: "StreamedSpan", + span: "Span", integration: "AnthropicIntegration", max_tokens: "int", messages: "Iterable[MessageParam]", @@ -556,7 +556,7 @@ def _set_common_input_data( def _set_create_input_data( - span: "StreamedSpan", + span: "Span", kwargs: "dict[str, Any]", integration: "AnthropicIntegration", ) -> None: @@ -640,7 +640,7 @@ async def _wrap_asynchronous_message_iterator( def _set_output_data( - span: "StreamedSpan", + span: "Span", integration: "AnthropicIntegration", model: "str | None", input_tokens: "int | None", @@ -928,7 +928,7 @@ def _accumulate_event_data( def _set_streaming_output_data( - span: "StreamedSpan", + span: "Span", integration: "AnthropicIntegration", model: "Optional[str]", usage: "_RecordedUsage", diff --git a/sentry_sdk/integrations/arq.py b/sentry_sdk/integrations/arq.py index ba8c7bea90..021afdfa7b 100644 --- a/sentry_sdk/integrations/arq.py +++ b/sentry_sdk/integrations/arq.py @@ -180,7 +180,7 @@ async def _sentry_coroutine( return await coroutine(ctx, *args, **kwargs) scope = sentry_sdk.get_current_scope() - span = scope.streamed_span + span = scope.span if span is not None: span.name = name diff --git a/sentry_sdk/integrations/asgi.py b/sentry_sdk/integrations/asgi.py index ddb1c2a993..c9c86a4c03 100644 --- a/sentry_sdk/integrations/asgi.py +++ b/sentry_sdk/integrations/asgi.py @@ -33,7 +33,7 @@ ) from sentry_sdk.traces import ( SegmentNameSource, - StreamedSpan, + Span, ) from sentry_sdk.tracing import ( SOURCE_FOR_STYLE, @@ -218,7 +218,7 @@ async def _run_app( method = scope.get("method", "").upper() - span: "Optional[ContextManager[Optional[StreamedSpan]]]" = None + span: "Optional[ContextManager[Optional[Span]]]" = None attributes: "Attributes" = { "sentry.segment.name.source": getattr( transaction_source, "value", transaction_source diff --git a/sentry_sdk/integrations/asyncpg.py b/sentry_sdk/integrations/asyncpg.py index e99560eecf..eff4ca8f66 100644 --- a/sentry_sdk/integrations/asyncpg.py +++ b/sentry_sdk/integrations/asyncpg.py @@ -7,7 +7,7 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.tracing_utils import ( add_query_source, record_sql_queries, @@ -111,7 +111,7 @@ def _record( params_list: "tuple[Any, ...] | None", *, executemany: bool = False, -) -> "Iterator[StreamedSpan]": +) -> "Iterator[Span]": client = sentry_sdk.get_client() integration = client.get_integration(AsyncPGIntegration) if integration is not None and not integration._record_params: @@ -231,7 +231,7 @@ async def _inner(*args: "Any", **kwargs: "Any") -> "T": return _inner -def _set_db_data(span: "StreamedSpan", conn: "Any") -> None: +def _set_db_data(span: "Span", conn: "Any") -> None: addr = conn._addr database = conn._params.database user = conn._params.user diff --git a/sentry_sdk/integrations/boto3.py b/sentry_sdk/integrations/boto3.py index da0c87ce52..4ffe245f09 100644 --- a/sentry_sdk/integrations/boto3.py +++ b/sentry_sdk/integrations/boto3.py @@ -4,7 +4,7 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.tracing import BAGGAGE_HEADER_NAME from sentry_sdk.tracing_utils import ( add_http_breadcrumb, @@ -78,7 +78,7 @@ def _sentry_request_created( breadcrumb: "dict[str, Any]" = {} - span: "Optional[StreamedSpan]" = None + span: "Optional[Span]" = None url_attributes = get_url_attributes(client, parsed_url) breadcrumb.update(url_attributes) @@ -165,7 +165,7 @@ def _replace_header(request: "AWSRequest", key: str, value: str) -> None: def _sentry_after_call( context: "Dict[str, Any]", parsed: "Dict[str, Any]", **kwargs: "Any" ) -> None: - span: "Optional[StreamedSpan]" = context.pop("_sentrysdk_span", None) + span: "Optional[Span]" = context.pop("_sentrysdk_span", None) # Span could be absent if the integration is disabled. if span is None: @@ -213,7 +213,7 @@ def sentry_streaming_body_close(*args: "Any", **kwargs: "Any") -> None: def _sentry_after_call_error( context: "Dict[str, Any]", exception: "Type[BaseException]", **kwargs: "Any" ) -> None: - span: "Optional[StreamedSpan]" = context.pop("_sentrysdk_span", None) + span: "Optional[Span]" = context.pop("_sentrysdk_span", None) # Span could be absent if the integration is disabled. if span is None: diff --git a/sentry_sdk/integrations/celery/__init__.py b/sentry_sdk/integrations/celery/__init__.py index 46e4c5e41e..4ae0772b16 100644 --- a/sentry_sdk/integrations/celery/__init__.py +++ b/sentry_sdk/integrations/celery/__init__.py @@ -16,7 +16,7 @@ from sentry_sdk.integrations.celery.utils import _now_seconds_since_epoch from sentry_sdk.integrations.logging import ignore_logger_for_events from sentry_sdk.scope import Scope, should_send_default_pii -from sentry_sdk.traces import SegmentNameSource, StreamedSpan +from sentry_sdk.traces import SegmentNameSource, Span from sentry_sdk.tracing import BAGGAGE_HEADER_NAME from sentry_sdk.tracing_utils import Baggage from sentry_sdk.utils import ( @@ -170,7 +170,7 @@ def event_processor(event: "Event", hint: "Hint") -> "Optional[Event]": def _update_celery_task_headers( original_headers: "dict[str, Any]", - span: "Optional[StreamedSpan]", + span: "Optional[Span]", monitor_beat_tasks: bool, ) -> "dict[str, Any]": """ @@ -358,7 +358,7 @@ def _inner(*args: "Any", **kwargs: "Any") -> "Any": return _inner # type: ignore -def _set_messaging_destination_name(task: "Any", span: "StreamedSpan") -> None: +def _set_messaging_destination_name(task: "Any", span: "Span") -> None: """Set "messaging.destination.name" tag for span""" with capture_internal_exceptions(): delivery_info = task.request.delivery_info diff --git a/sentry_sdk/integrations/chalice.py b/sentry_sdk/integrations/chalice.py index 4b59d037aa..5dae03c0ae 100644 --- a/sentry_sdk/integrations/chalice.py +++ b/sentry_sdk/integrations/chalice.py @@ -8,7 +8,7 @@ from sentry_sdk.traces import ( SegmentNameSource, SpanStatus, - StreamedSpan, + Span, ) from sentry_sdk.utils import ( capture_internal_exceptions, @@ -84,7 +84,7 @@ def wrapped_view_function(**function_args: "Any") -> "Any": current_span = sentry_sdk.traces.get_current_span() segment = None - if type(current_span) is StreamedSpan: + if type(current_span) is Span: # A segment already exists (created by the AWS Lambda # integration), so decorate it with Chalice attributes # The AWS Lambda integration owns the span lifecycle diff --git a/sentry_sdk/integrations/clickhouse_driver.py b/sentry_sdk/integrations/clickhouse_driver.py index f74fc8ff31..224f621d75 100644 --- a/sentry_sdk/integrations/clickhouse_driver.py +++ b/sentry_sdk/integrations/clickhouse_driver.py @@ -5,7 +5,7 @@ from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.utils import has_data_collection_enabled # Hack to get new Python features working in older versions @@ -158,7 +158,7 @@ def _wrap_send_data() -> None: def _inner_send_data( # type: ignore[no-untyped-def] # clickhouse-driver does not type send_data self, sample_block, data, types_check=False, columnar=False, *args, **kwargs ): - span: "Optional[StreamedSpan]" = getattr(self.connection, "_sentry_span", None) + span: "Optional[Span]" = getattr(self.connection, "_sentry_span", None) _set_db_data(span, self.connection) return original_send_data( @@ -168,7 +168,7 @@ def _inner_send_data( # type: ignore[no-untyped-def] # clickhouse-driver does n Client.send_data = _inner_send_data -def _set_db_data(span: "Optional[StreamedSpan]", connection: "Connection") -> None: +def _set_db_data(span: "Optional[Span]", connection: "Connection") -> None: if span is None: return diff --git a/sentry_sdk/integrations/cohere.py b/sentry_sdk/integrations/cohere.py index 5cf5c4d885..5aa25acf4a 100644 --- a/sentry_sdk/integrations/cohere.py +++ b/sentry_sdk/integrations/cohere.py @@ -6,7 +6,7 @@ from sentry_sdk.ai.monitoring import record_token_usage from sentry_sdk.ai.utils import set_data_normalized from sentry_sdk.consts import SPANDATA -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span if TYPE_CHECKING: from typing import Any, Callable, Iterator @@ -112,7 +112,7 @@ def _capture_exception(exc: "Any") -> None: def _wrap_chat(f: "Callable[..., Any]", streaming: bool) -> "Callable[..., Any]": def collect_chat_response_fields( - span: "StreamedSpan", + span: "Span", res: "NonStreamedChatResponse", include_pii: bool, ) -> None: diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py index 8e59a64415..5602f91b5d 100644 --- a/sentry_sdk/integrations/django/__init__.py +++ b/sentry_sdk/integrations/django/__init__.py @@ -83,7 +83,7 @@ NotImplementedType, ) from sentry_sdk.integrations.wsgi import _ScopedResponse - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span TRANSACTION_STYLE_VALUES = ("function_name", "url") @@ -890,7 +890,7 @@ def _rollback(self: "BaseDatabaseWrapper") -> None: def _set_db_data( - span: "StreamedSpan", + span: "Span", cursor_or_db: "Any", db_operation: "Optional[str]" = None, ) -> None: diff --git a/sentry_sdk/integrations/django/asgi.py b/sentry_sdk/integrations/django/asgi.py index 99229aaba8..6d124549ad 100644 --- a/sentry_sdk/integrations/django/asgi.py +++ b/sentry_sdk/integrations/django/asgi.py @@ -17,7 +17,7 @@ from sentry_sdk.consts import OP 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.traces import Span from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -175,7 +175,7 @@ async def sentry_wrapped_callback( ) -> "Any": client = sentry_sdk.get_client() current_span = sentry_sdk.traces.get_current_span() - if type(current_span) is StreamedSpan: + if type(current_span) is Span: segment = current_span._segment segment._update_active_thread() diff --git a/sentry_sdk/integrations/django/middleware.py b/sentry_sdk/integrations/django/middleware.py index a567ec5045..6611337340 100644 --- a/sentry_sdk/integrations/django/middleware.py +++ b/sentry_sdk/integrations/django/middleware.py @@ -17,7 +17,7 @@ if TYPE_CHECKING: from typing import Any, Callable, Optional, TypeVar - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span F = TypeVar("F", bound=Callable[..., Any]) @@ -66,7 +66,7 @@ def _wrap_middleware(middleware: "Any", middleware_name: str) -> "Any": def _check_middleware_span( old_method: "Callable[..., Any]", - ) -> "Optional[StreamedSpan]": + ) -> "Optional[Span]": integration = sentry_sdk.get_client().get_integration(DjangoIntegration) if integration is None or not integration.middleware_spans: return None diff --git a/sentry_sdk/integrations/django/views.py b/sentry_sdk/integrations/django/views.py index 11c7adcb8e..d493a682dd 100644 --- a/sentry_sdk/integrations/django/views.py +++ b/sentry_sdk/integrations/django/views.py @@ -3,7 +3,7 @@ import sentry_sdk from sentry_sdk.consts import OP -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span if TYPE_CHECKING: from typing import Any @@ -63,7 +63,7 @@ def sentry_wrapped_callback(request: "Any", *args: "Any", **kwargs: "Any") -> "A client = sentry_sdk.get_client() current_span = sentry_sdk.traces.get_current_span() - if type(current_span) is StreamedSpan: + if type(current_span) is Span: segment = current_span._segment segment._update_active_thread() diff --git a/sentry_sdk/integrations/fastapi.py b/sentry_sdk/integrations/fastapi.py index e428e398cd..c1a0aab3f4 100644 --- a/sentry_sdk/integrations/fastapi.py +++ b/sentry_sdk/integrations/fastapi.py @@ -6,7 +6,7 @@ import sentry_sdk from sentry_sdk.consts import SPANDATA from sentry_sdk.integrations import DidNotEnable, _check_minimum_version -from sentry_sdk.traces import StreamedSpan, get_current_span +from sentry_sdk.traces import Span, get_current_span from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.utils import ( has_data_collection_enabled, @@ -164,7 +164,7 @@ def event_processor(event: "Event", hint: "Dict[str, Any]") -> "Event": finally: current_span = get_current_span() - if type(current_span) is StreamedSpan: + if type(current_span) is Span: attach_request_data = True if has_data_collection_enabled(client.options): attach_request_data = ( @@ -205,7 +205,7 @@ def _sentry_get_request_handler(*args: "Any", **kwargs: "Any") -> "Any": def _sentry_call(*args: "Any", **kwargs: "Any") -> "Any": current_span = sentry_sdk.traces.get_current_span() - if type(current_span) is StreamedSpan: + if type(current_span) is Span: segment = current_span._segment segment._update_active_thread() diff --git a/sentry_sdk/integrations/google_genai/streaming.py b/sentry_sdk/integrations/google_genai/streaming.py index e8e329e662..6ca84fc040 100644 --- a/sentry_sdk/integrations/google_genai/streaming.py +++ b/sentry_sdk/integrations/google_genai/streaming.py @@ -4,7 +4,7 @@ from sentry_sdk.ai.utils import set_data_normalized from sentry_sdk.consts import SPANDATA from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.utils import ( has_data_collection_enabled, safe_serialize, @@ -98,7 +98,7 @@ def accumulate_streaming_response( def set_span_data_for_streaming_response( - span: "StreamedSpan", + span: "Span", integration: "Any", accumulated_response: "AccumulatedResponse", ) -> None: diff --git a/sentry_sdk/integrations/google_genai/utils.py b/sentry_sdk/integrations/google_genai/utils.py index b795e7fa83..be93a8165c 100644 --- a/sentry_sdk/integrations/google_genai/utils.py +++ b/sentry_sdk/integrations/google_genai/utils.py @@ -51,7 +51,7 @@ ) from sentry_sdk._types import TextPart - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span _is_PIL_available = False try: @@ -679,7 +679,7 @@ def _capture_tool_input( return tool_input -def _create_tool_span(tool_name: str, tool_doc: "Optional[str]") -> "StreamedSpan": +def _create_tool_span(tool_name: str, tool_doc: "Optional[str]") -> "Span": """Create a span for tool execution.""" span = sentry_sdk.traces.start_span( name=f"execute_tool {tool_name}", @@ -897,7 +897,7 @@ def _transform_system_instructions( def set_span_data_for_request( - span: "StreamedSpan", + span: "Span", integration: "Any", model: str, contents: "ContentListUnion", @@ -989,7 +989,7 @@ def set_span_data_for_request( def set_span_data_for_response( - span: "StreamedSpan", + span: "Span", integration: "Any", response: "GenerateContentResponse", ) -> None: @@ -1103,7 +1103,7 @@ def prepare_embed_content_args( def set_span_data_for_embed_request( - span: "StreamedSpan", + span: "Span", integration: "Any", contents: "Any", kwargs: "dict[str, Any]", @@ -1146,7 +1146,7 @@ def set_span_data_for_embed_request( def set_span_data_for_embed_response( - span: "StreamedSpan", + span: "Span", integration: "Any", response: "EmbedContentResponse", ) -> None: diff --git a/sentry_sdk/integrations/huey.py b/sentry_sdk/integrations/huey.py index 4ef836d05a..f242873911 100644 --- a/sentry_sdk/integrations/huey.py +++ b/sentry_sdk/integrations/huey.py @@ -7,7 +7,7 @@ from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import SegmentNameSource, SpanStatus, StreamedSpan +from sentry_sdk.traces import SegmentNameSource, SpanStatus, Span from sentry_sdk.tracing import ( BAGGAGE_HEADER_NAME, SENTRY_TRACE_HEADER_NAME, @@ -151,11 +151,11 @@ def event_processor(event: "Event", hint: "Hint") -> "Optional[Event]": def _capture_exception(exc_info: "ExcInfo") -> None: scope = sentry_sdk.get_current_scope() if exc_info[0] in HUEY_CONTROL_FLOW_EXCEPTIONS: - if type(scope._span) is StreamedSpan: + if type(scope._span) is Span: scope._span._segment.status = SpanStatus.OK return - if type(scope._span) is StreamedSpan: + if type(scope._span) is Span: scope._span._segment.status = SpanStatus.ERROR event, hint = event_from_exception( diff --git a/sentry_sdk/integrations/langchain.py b/sentry_sdk/integrations/langchain.py index ae3c781308..a149b3a57f 100644 --- a/sentry_sdk/integrations/langchain.py +++ b/sentry_sdk/integrations/langchain.py @@ -15,7 +15,7 @@ from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import StreamedSpan, _AgentFrameworkChatGenerationContext +from sentry_sdk.traces import Span, _AgentFrameworkChatGenerationContext from sentry_sdk.tracing_utils import ( _get_value, ) @@ -211,7 +211,7 @@ class SentryLangchainCallback(BaseCallbackHandler): """Callback handler that creates Sentry spans.""" def __init__(self, include_prompts: bool) -> None: - self.span_map: "OrderedDict[UUID, Union[StreamedSpan, _AgentFrameworkChatGenerationContext]]" = OrderedDict() + self.span_map: "OrderedDict[UUID, Union[Span, _AgentFrameworkChatGenerationContext]]" = OrderedDict() self.include_prompts = include_prompts def _handle_error(self, run_id: "UUID", error: "Any") -> None: @@ -250,10 +250,10 @@ def _create_span( op: str, name: str, origin: str, - ) -> "StreamedSpan": + ) -> "Span": span = None if parent_id: - parent: "Optional[Union[StreamedSpan, _AgentFrameworkChatGenerationContext]]" = self.span_map.get( + parent: "Optional[Union[Span, _AgentFrameworkChatGenerationContext]]" = self.span_map.get( parent_id ) if parent: @@ -290,7 +290,7 @@ def _create_generation_span( ) -> "_AgentFrameworkChatGenerationContext": context = None if parent_id: - parent: "Optional[Union[StreamedSpan, _AgentFrameworkChatGenerationContext]]" = self.span_map.get( + parent: "Optional[Union[Span, _AgentFrameworkChatGenerationContext]]" = self.span_map.get( parent_id ) if parent: @@ -319,7 +319,7 @@ def _create_generation_span( def _exit_span( self: "SentryLangchainCallback", - span: "StreamedSpan", + span: "Span", run_id: "UUID", ) -> None: span.__exit__(None, None, None) @@ -854,7 +854,7 @@ def _get_token_usage(obj: "Any") -> "Optional[Dict[str, Any]]": return None -def _record_token_usage(span: "StreamedSpan", response: "LLMResult") -> None: +def _record_token_usage(span: "Span", response: "LLMResult") -> None: input_tokens = None output_tokens = None total_tokens = None @@ -1000,7 +1000,7 @@ def _simplify_langchain_tools(tools: "Any") -> "Optional[List[Any]]": return simplified_tools if simplified_tools else None -def _set_tools_on_span(span: "StreamedSpan", tools: "Any") -> None: +def _set_tools_on_span(span: "Span", tools: "Any") -> None: """Set available tools data on a span if tools are provided.""" if tools is None: return diff --git a/sentry_sdk/integrations/langgraph.py b/sentry_sdk/integrations/langgraph.py index f6a85f4dc3..32f9f32a10 100644 --- a/sentry_sdk/integrations/langgraph.py +++ b/sentry_sdk/integrations/langgraph.py @@ -19,7 +19,7 @@ ) if TYPE_CHECKING: - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span try: from langgraph.errors import GraphBubbleUp @@ -268,7 +268,7 @@ def _extract_tool_calls(messages: "Optional[List[Any]]") -> "Optional[List[Any]] return tool_calls if tool_calls else None -def _set_usage_data(span: "StreamedSpan", messages: "Any") -> None: +def _set_usage_data(span: "Span", messages: "Any") -> None: input_tokens = 0 output_tokens = 0 total_tokens = 0 @@ -299,7 +299,7 @@ def _set_usage_data(span: "StreamedSpan", messages: "Any") -> None: ) -def _set_response_model_name(span: "StreamedSpan", messages: "Any") -> None: +def _set_response_model_name(span: "Span", messages: "Any") -> None: if len(messages) == 0: return diff --git a/sentry_sdk/integrations/mcp.py b/sentry_sdk/integrations/mcp.py index a6fff93198..b30b10138a 100644 --- a/sentry_sdk/integrations/mcp.py +++ b/sentry_sdk/integrations/mcp.py @@ -68,7 +68,7 @@ ) from starlette.types import Receive, Scope, Send - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span class MCPIntegration(Integration): @@ -179,7 +179,7 @@ def _get_request_context_data( def _set_span_input_data( - span: "StreamedSpan", + span: "Span", handler_name: str, span_data_key: str, mcp_method_name: str, diff --git a/sentry_sdk/integrations/openai.py b/sentry_sdk/integrations/openai.py index fb0b1d6dfa..41a5a07be7 100644 --- a/sentry_sdk/integrations/openai.py +++ b/sentry_sdk/integrations/openai.py @@ -42,7 +42,7 @@ from sentry_sdk.consts import SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.utils import ( capture_internal_exceptions, event_from_exception, @@ -174,7 +174,7 @@ def _has_attr_and_is_int( def _calculate_completions_token_usage( messages: "Optional[Union[Iterable[ChatCompletionMessageParam], list[str]]]", response: "Any", - span: "StreamedSpan", + span: "Span", streaming_message_responses: "Optional[List[str]]", streaming_message_total_token_usage: "Optional[CompletionUsage]", count_tokens: "Callable[..., Any]", @@ -256,7 +256,7 @@ def _calculate_completions_token_usage( def _calculate_responses_token_usage( input: "Any", response: "Any", - span: "StreamedSpan", + span: "Span", streaming_message_responses: "Optional[List[str]]", count_tokens: "Callable[..., Any]", ) -> None: @@ -332,7 +332,7 @@ def _calculate_responses_token_usage( def _set_responses_api_input_data( - span: "StreamedSpan", + span: "Span", kwargs: "dict[str, Any]", integration: "OpenAIIntegration", ) -> None: @@ -465,7 +465,7 @@ def _set_responses_api_input_data( def _set_completions_api_input_data( - span: "StreamedSpan", + span: "Span", kwargs: "dict[str, Any]", integration: "OpenAIIntegration", ) -> None: @@ -574,7 +574,7 @@ def _set_completions_api_input_data( def _set_embeddings_input_data( - span: "StreamedSpan", + span: "Span", kwargs: "dict[str, Any]", integration: "OpenAIIntegration", ) -> None: @@ -630,7 +630,7 @@ def _set_embeddings_input_data( def _set_common_output_data( - span: "StreamedSpan", + span: "Span", response: "Union[ChatCompletion, Stream[ChatCompletionChunk], AsyncStream[ChatCompletionChunk], Response, Stream[ResponseStreamEvent], AsyncStream[ResponseStreamEvent], CreateEmbeddingResponse]", input: "Any", integration: "OpenAIIntegration", @@ -922,7 +922,7 @@ async def _new_async_chat_completion( def _set_completions_api_output_data( - span: "StreamedSpan", + span: "Span", response: "Union[ChatCompletion, Stream[ChatCompletionChunk], AsyncStream[ChatCompletionChunk]]", kwargs: "dict[str, Any]", integration: "OpenAIIntegration", @@ -943,7 +943,7 @@ def _set_completions_api_output_data( def _wrap_synchronous_completions_chunk_iterator( - span: "StreamedSpan", + span: "Span", integration: "OpenAIIntegration", start_time: "Optional[float]", messages: "Optional[Union[Iterable[ChatCompletionMessageParam], list[str]]]", @@ -1011,7 +1011,7 @@ def _wrap_synchronous_completions_chunk_iterator( async def _wrap_asynchronous_completions_chunk_iterator( - span: "StreamedSpan", + span: "Span", integration: "OpenAIIntegration", start_time: "Optional[float]", messages: "Optional[Union[Iterable[ChatCompletionMessageParam], list[str]]]", @@ -1079,7 +1079,7 @@ async def _wrap_asynchronous_completions_chunk_iterator( def _wrap_synchronous_responses_event_iterator( - span: "StreamedSpan", + span: "Span", integration: "OpenAIIntegration", start_time: "Optional[float]", input: "Optional[Union[str, list[str], ResponseInputParam]]", @@ -1149,7 +1149,7 @@ def _wrap_synchronous_responses_event_iterator( async def _wrap_asynchronous_responses_event_iterator( - span: "StreamedSpan", + span: "Span", integration: "OpenAIIntegration", start_time: "Optional[float]", input: "Optional[Union[str, list[str], ResponseInputParam]]", @@ -1219,7 +1219,7 @@ async def _wrap_asynchronous_responses_event_iterator( def _set_responses_api_output_data( - span: "StreamedSpan", + span: "Span", response: "Union[Response, Stream[ResponseStreamEvent], AsyncStream[ResponseStreamEvent]]", kwargs: "dict[str, Any]", integration: "OpenAIIntegration", @@ -1240,7 +1240,7 @@ def _set_responses_api_output_data( def _set_embeddings_output_data( - span: "StreamedSpan", + span: "Span", response: "CreateEmbeddingResponse", kwargs: "dict[str, Any]", integration: "OpenAIIntegration", diff --git a/sentry_sdk/integrations/openai_agents/patches/agent_run.py b/sentry_sdk/integrations/openai_agents/patches/agent_run.py index a5208fbe63..17e825f779 100644 --- a/sentry_sdk/integrations/openai_agents/patches/agent_run.py +++ b/sentry_sdk/integrations/openai_agents/patches/agent_run.py @@ -3,7 +3,7 @@ from sentry_sdk.consts import SPANDATA from sentry_sdk.integrations import DidNotEnable -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.utils import capture_internal_exceptions, reraise from ..spans import ( @@ -50,7 +50,7 @@ def _maybe_start_agent_span( should_run_agent_start_hooks: bool, span_kwargs: "dict[str, Any]", is_streaming: bool = False, -) -> "Optional[StreamedSpan]": +) -> "Optional[Span]": """ Start an agent invocation span if conditions are met. Handles ending any existing span for a different agent. diff --git a/sentry_sdk/integrations/openai_agents/patches/error_tracing.py b/sentry_sdk/integrations/openai_agents/patches/error_tracing.py index 59d1c0858a..f1a561a33d 100644 --- a/sentry_sdk/integrations/openai_agents/patches/error_tracing.py +++ b/sentry_sdk/integrations/openai_agents/patches/error_tracing.py @@ -54,7 +54,7 @@ def sentry_attach_error_to_current_span( the agents library swallows exceptions. """ # Set the current Sentry span to errored - current_span = sentry_sdk.get_current_scope().streamed_span + current_span = sentry_sdk.get_current_scope().span if current_span is not None: current_span.status = SpanStatus.ERROR diff --git a/sentry_sdk/integrations/openai_agents/patches/models.py b/sentry_sdk/integrations/openai_agents/patches/models.py index d7429e4c8e..116306de60 100644 --- a/sentry_sdk/integrations/openai_agents/patches/models.py +++ b/sentry_sdk/integrations/openai_agents/patches/models.py @@ -6,7 +6,7 @@ import sentry_sdk from sentry_sdk.consts import SPANDATA from sentry_sdk.integrations import DidNotEnable -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.tracing import BAGGAGE_HEADER_NAME from sentry_sdk.tracing_utils import ( add_sentry_baggage_to_headers, @@ -28,7 +28,7 @@ def _inject_trace_propagation_headers( - hosted_tool: "HostedMCPTool", span: "StreamedSpan" + hosted_tool: "HostedMCPTool", span: "Span" ) -> None: headers = hosted_tool.tool_config.get("headers") if headers is None: diff --git a/sentry_sdk/integrations/openai_agents/spans/agent_workflow.py b/sentry_sdk/integrations/openai_agents/spans/agent_workflow.py index 5c68e338b1..3748f82e2a 100644 --- a/sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +++ b/sentry_sdk/integrations/openai_agents/spans/agent_workflow.py @@ -10,7 +10,7 @@ def agent_workflow_span( agent: "agents.Agent", -) -> "sentry_sdk.traces.StreamedSpan": +) -> "sentry_sdk.traces.Span": return sentry_sdk.traces.start_span( name=f"{agent.name} workflow", attributes={"sentry.origin": SPAN_ORIGIN} ) diff --git a/sentry_sdk/integrations/openai_agents/spans/ai_client.py b/sentry_sdk/integrations/openai_agents/spans/ai_client.py index e70644e57e..203e4efd74 100644 --- a/sentry_sdk/integrations/openai_agents/spans/ai_client.py +++ b/sentry_sdk/integrations/openai_agents/spans/ai_client.py @@ -4,7 +4,7 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable -from sentry_sdk.traces import StreamedSpan, _AgentFrameworkChatGenerationContext +from sentry_sdk.traces import Span, _AgentFrameworkChatGenerationContext from sentry_sdk.utils import has_data_collection_enabled try: @@ -239,7 +239,7 @@ def ai_client_context( def update_ai_client_span( - span: "StreamedSpan", + span: "Span", response: "Any", response_model: "Optional[str]" = None, agent: "Optional[Agent]" = None, diff --git a/sentry_sdk/integrations/openai_agents/spans/execute_tool.py b/sentry_sdk/integrations/openai_agents/spans/execute_tool.py index 05a8b9246e..e1f06e15e2 100644 --- a/sentry_sdk/integrations/openai_agents/spans/execute_tool.py +++ b/sentry_sdk/integrations/openai_agents/spans/execute_tool.py @@ -3,7 +3,7 @@ import sentry_sdk 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.traces import SpanStatus, Span from sentry_sdk.utils import has_data_collection_enabled from ..consts import SPAN_ORIGIN @@ -17,7 +17,7 @@ def execute_tool_span( tool: "agents.FunctionTool", *args: "Any", **kwargs: "Any" -) -> "StreamedSpan": +) -> "Span": return sentry_sdk.traces.start_span( name=f"execute_tool {tool.name}", attributes={ @@ -31,7 +31,7 @@ def execute_tool_span( def update_execute_tool_span( - span: "StreamedSpan", + span: "Span", agent: "agents.Agent", tool: "agents.Tool", result: "Any", diff --git a/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py b/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py index 4d71e0c245..f902d867b1 100644 --- a/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +++ b/sentry_sdk/integrations/openai_agents/spans/invoke_agent.py @@ -7,7 +7,7 @@ ) 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.traces import Span from sentry_sdk.utils import has_data_collection_enabled, safe_serialize from ..consts import SPAN_ORIGIN @@ -21,7 +21,7 @@ def invoke_agent_span( context: "agents.RunContextWrapper", agent: "agents.Agent", kwargs: "dict[str, Any]" -) -> "StreamedSpan": +) -> "Span": client_options = sentry_sdk.get_client().options span = sentry_sdk.traces.start_span( @@ -84,7 +84,7 @@ def invoke_agent_span( def update_invoke_agent_span( - span: "StreamedSpan", + span: "Span", context: "Optional[agents.RunContextWrapper]", agent: "Optional[agents.Agent]", output: "Any" = None, diff --git a/sentry_sdk/integrations/openai_agents/utils.py b/sentry_sdk/integrations/openai_agents/utils.py index 6a772a15cf..b104b2c042 100644 --- a/sentry_sdk/integrations/openai_agents/utils.py +++ b/sentry_sdk/integrations/openai_agents/utils.py @@ -16,7 +16,7 @@ from sentry_sdk.consts import SPANDATA from sentry_sdk.integrations import DidNotEnable from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.utils import ( event_from_exception, has_data_collection_enabled, @@ -46,7 +46,7 @@ def _capture_exception(exc: "Any") -> None: sentry_sdk.capture_event(event, hint=hint) -def _set_agent_data(span: "StreamedSpan", agent: "agents.Agent") -> None: +def _set_agent_data(span: "Span", agent: "agents.Agent") -> None: span.set_attribute( SPANDATA.GEN_AI_PROVIDER_NAME, "openai" ) # See footnote for https://opentelemetry.io/docs/specs/semconv/registry/attributes/gen-ai/#gen-ai-system for explanation why. @@ -90,7 +90,7 @@ def _set_agent_data(span: "StreamedSpan", agent: "agents.Agent") -> None: ) -def _set_usage_data(span: "StreamedSpan", usage: "Usage") -> None: +def _set_usage_data(span: "Span", usage: "Usage") -> None: span.set_attribute(SPANDATA.GEN_AI_USAGE_INPUT_TOKENS, usage.input_tokens) span.set_attribute( SPANDATA.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, @@ -105,7 +105,7 @@ def _set_usage_data(span: "StreamedSpan", usage: "Usage") -> None: def _set_input_data( - span: "StreamedSpan", + span: "Span", get_response_kwargs: "dict[str, Any]", ) -> None: client = sentry_sdk.get_client() @@ -182,7 +182,7 @@ def _set_input_data( ) -def _set_output_data(span: "StreamedSpan", result: "Any") -> None: +def _set_output_data(span: "Span", result: "Any") -> None: client = sentry_sdk.get_client() record_outputs = False if has_data_collection_enabled(client.options): diff --git a/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py b/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py index 09c02b0591..1a0fdb6dde 100644 --- a/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py +++ b/sentry_sdk/integrations/pydantic_ai/spans/ai_client.py @@ -6,7 +6,7 @@ set_data_normalized, ) from sentry_sdk.consts import OP, SPANDATA -from sentry_sdk.traces import StreamedSpan, _AgentFrameworkChatGenerationContext +from sentry_sdk.traces import Span, _AgentFrameworkChatGenerationContext from sentry_sdk.utils import safe_serialize from ..consts import SPAN_ORIGIN @@ -99,7 +99,7 @@ def _get_system_instructions( return permanent_instructions, current_instructions -def _set_input_messages(span: "StreamedSpan", messages: "list[ModelMessage]") -> None: +def _set_input_messages(span: "Span", messages: "list[ModelMessage]") -> None: """Set input messages data on a span.""" if not _should_send_inputs(): return @@ -212,7 +212,7 @@ def _set_input_messages(span: "StreamedSpan", messages: "list[ModelMessage]") -> def _set_output_data( - span: "StreamedSpan", + span: "Span", response: "Optional[ModelResponse]", ) -> None: """Set output data on a span.""" @@ -304,7 +304,7 @@ def ai_client_context( def update_ai_client_span( - span: "StreamedSpan", + span: "Span", model_response: "Optional[ModelResponse]", ) -> None: """Update the AI client span with response data.""" diff --git a/sentry_sdk/integrations/pydantic_ai/spans/execute_tool.py b/sentry_sdk/integrations/pydantic_ai/spans/execute_tool.py index 045367ae88..d239a9be2a 100644 --- a/sentry_sdk/integrations/pydantic_ai/spans/execute_tool.py +++ b/sentry_sdk/integrations/pydantic_ai/spans/execute_tool.py @@ -2,7 +2,7 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.utils import safe_serialize from ..consts import SPAN_ORIGIN @@ -20,7 +20,7 @@ def execute_tool_span( tool_args: "dict[str, Any]", agent: "Optional[Agent[Any, Any]]", tool_definition: "ToolDefinition", -) -> "StreamedSpan": +) -> "Span": """Create a span for tool execution. Args: @@ -53,7 +53,7 @@ def execute_tool_span( return span -def update_execute_tool_span(span: "StreamedSpan", result: "Any") -> None: +def update_execute_tool_span(span: "Span", result: "Any") -> None: """Update the execute tool span with the result.""" if not span: return diff --git a/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py b/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py index daef200cb9..ab95179d44 100644 --- a/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py +++ b/sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py @@ -6,7 +6,7 @@ set_data_normalized, ) from sentry_sdk.consts import OP, SPANDATA -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from ..consts import SPAN_ORIGIN from ..utils import ( @@ -41,7 +41,7 @@ def invoke_agent_span( agent: "Optional[Agent]", model: "AbstractModel", model_settings: "Optional[Union[ModelSettings, RealtimeModelSettings]]", -) -> "StreamedSpan": +) -> "Span": """Create a span for invoking the agent.""" # Determine agent name for span name = "agent" @@ -137,7 +137,7 @@ def invoke_agent_span( def update_invoke_agent_span( - span: "StreamedSpan", + span: "Span", result: "Any", ) -> None: """Update and close the invoke agent span.""" diff --git a/sentry_sdk/integrations/pydantic_ai/spans/utils.py b/sentry_sdk/integrations/pydantic_ai/spans/utils.py index ba77b05b5a..b48fc788fa 100644 --- a/sentry_sdk/integrations/pydantic_ai/spans/utils.py +++ b/sentry_sdk/integrations/pydantic_ai/spans/utils.py @@ -12,7 +12,7 @@ from pydantic_ai.usage import RequestUsage, RunUsage - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span def _serialize_image_url_item(item: "Any") -> "Dict[str, Any]": @@ -47,7 +47,7 @@ def _serialize_binary_content_item(item: "Any") -> "Dict[str, Any]": def _set_usage_data( - span: "StreamedSpan", + span: "Span", usage: "Union[RequestUsage, RunUsage]", ) -> None: """Set token usage data on a span. diff --git a/sentry_sdk/integrations/pydantic_ai/utils.py b/sentry_sdk/integrations/pydantic_ai/utils.py index d6bf7a8872..5567e36a97 100644 --- a/sentry_sdk/integrations/pydantic_ai/utils.py +++ b/sentry_sdk/integrations/pydantic_ai/utils.py @@ -3,7 +3,7 @@ import sentry_sdk from sentry_sdk.consts import SPANDATA from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.utils import ( event_from_exception, has_data_collection_enabled, @@ -56,7 +56,7 @@ def _should_send_outputs() -> bool: return _should_send_prompts_legacy() -def _set_agent_data(span: "StreamedSpan", agent: "Optional[Agent]") -> None: +def _set_agent_data(span: "Span", agent: "Optional[Agent]") -> None: """Set agent-related data on a span. Args: @@ -95,7 +95,7 @@ def _get_model_name( def _set_model_data( - span: "StreamedSpan", + span: "Span", agent: "Optional[Agent]", model: "Union[Model, AbstractModel]", model_settings: "Optional[Union[ModelSettings, RealtimeModelSettings]]", @@ -152,7 +152,7 @@ def _set_model_data( def _set_available_tools( - span: "StreamedSpan", agent: "Optional[Agent[Any, Any]]" + span: "Span", agent: "Optional[Agent[Any, Any]]" ) -> None: """Set available tools data on a span from an agent's function toolset. diff --git a/sentry_sdk/integrations/pymongo.py b/sentry_sdk/integrations/pymongo.py index ac66d4b12c..be65cf8be1 100644 --- a/sentry_sdk/integrations/pymongo.py +++ b/sentry_sdk/integrations/pymongo.py @@ -29,7 +29,7 @@ CommandSucceededEvent, ) - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span SAFE_COMMAND_ATTRIBUTES = [ @@ -115,7 +115,7 @@ def _get_db_data(event: "Any") -> "Dict[str, Any]": class CommandTracer(monitoring.CommandListener): def __init__(self) -> None: - self._ongoing_operations: "dict[int, StreamedSpan]" = {} + self._ongoing_operations: "dict[int, Span]" = {} def _operation_key( self, diff --git a/sentry_sdk/integrations/quart.py b/sentry_sdk/integrations/quart.py index cf9c492dcb..1343867fc3 100644 --- a/sentry_sdk/integrations/quart.py +++ b/sentry_sdk/integrations/quart.py @@ -12,7 +12,7 @@ from sentry_sdk.integrations.asgi import SentryAsgiMiddleware 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.traces import Span, get_current_span from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, @@ -181,7 +181,7 @@ async def _request_websocket_started(app: "Quart", **kwargs: "Any") -> None: scope = sentry_sdk.get_isolation_scope() current_span = get_current_span() - if type(current_span) is StreamedSpan: + if type(current_span) is Span: segment = current_span._segment segment.set_attribute("http.request.method", request_websocket.method) diff --git a/sentry_sdk/integrations/redis/_async_common.py b/sentry_sdk/integrations/redis/_async_common.py index a5db08f982..8e3fd26001 100644 --- a/sentry_sdk/integrations/redis/_async_common.py +++ b/sentry_sdk/integrations/redis/_async_common.py @@ -24,14 +24,14 @@ from redis.asyncio.client import Pipeline, Redis from redis.asyncio.cluster import ClusterPipeline, RedisCluster - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span def patch_redis_async_pipeline( pipeline_cls: "Union[type[Pipeline[Any]], type[ClusterPipeline[Any]]]", is_cluster: bool, get_command_args_fn: "Any", - set_db_data_fn: "Callable[[StreamedSpan, Any], None]", + set_db_data_fn: "Callable[[Span, Any], None]", ) -> None: old_execute = pipeline_cls.execute @@ -75,7 +75,7 @@ async def _sentry_execute(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": def patch_redis_async_client( cls: "Union[type[Redis[Any]], type[RedisCluster[Any]]]", is_cluster: bool, - set_db_data_fn: "Callable[[StreamedSpan, Any], None]", + set_db_data_fn: "Callable[[Span, Any], None]", ) -> None: old_execute_command = cls.execute_command @@ -123,7 +123,7 @@ async def _sentry_execute_command( _get_safe_command(name, args) ) - cache_span: "Optional[StreamedSpan]" = None + cache_span: "Optional[Span]" = None if cache_properties["is_cache_key"] and cache_properties["op"] is not None: cache_span = sentry_sdk.traces.start_span( name=cache_properties["description"], diff --git a/sentry_sdk/integrations/redis/_sync_common.py b/sentry_sdk/integrations/redis/_sync_common.py index d6a649cad2..fbe3841c71 100644 --- a/sentry_sdk/integrations/redis/_sync_common.py +++ b/sentry_sdk/integrations/redis/_sync_common.py @@ -21,14 +21,14 @@ from collections.abc import Callable from typing import Any, Optional - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span def patch_redis_pipeline( pipeline_cls: "Any", is_cluster: bool, get_command_args_fn: "Any", - set_db_data_fn: "Callable[[StreamedSpan, Any], None]", + set_db_data_fn: "Callable[[Span, Any], None]", ) -> None: old_execute = pipeline_cls.execute @@ -72,7 +72,7 @@ def sentry_patched_execute(self: "Any", *args: "Any", **kwargs: "Any") -> "Any": def patch_redis_client( cls: "Any", is_cluster: bool, - set_db_data_fn: "Callable[[StreamedSpan, Any], None]", + set_db_data_fn: "Callable[[Span, Any], None]", ) -> None: """ This function can be used to instrument custom redis client classes or @@ -124,7 +124,7 @@ def sentry_patched_execute_command( _get_safe_command(name, args) ) - cache_span: "Optional[StreamedSpan]" = None + cache_span: "Optional[Span]" = None if cache_properties["is_cache_key"] and cache_properties["op"] is not None: cache_span = sentry_sdk.traces.start_span( name=cache_properties["description"], diff --git a/sentry_sdk/integrations/redis/modules/caches.py b/sentry_sdk/integrations/redis/modules/caches.py index 9f618ef26d..134c9983f9 100644 --- a/sentry_sdk/integrations/redis/modules/caches.py +++ b/sentry_sdk/integrations/redis/modules/caches.py @@ -15,7 +15,7 @@ from typing import Any, Optional from sentry_sdk.integrations.redis import RedisIntegration - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span def _get_op(name: str) -> "Optional[str]": @@ -77,7 +77,7 @@ def _get_cache_span_description( def _set_cache_data( - span: "StreamedSpan", + span: "Span", redis_client: "Any", properties: "dict[str, Any]", return_value: "Optional[Any]", diff --git a/sentry_sdk/integrations/redis/modules/queries.py b/sentry_sdk/integrations/redis/modules/queries.py index 3b41cfd69e..4d301dea2f 100644 --- a/sentry_sdk/integrations/redis/modules/queries.py +++ b/sentry_sdk/integrations/redis/modules/queries.py @@ -14,7 +14,7 @@ from redis import Redis from sentry_sdk.integrations.redis import RedisIntegration - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span def _compile_db_span_properties( @@ -42,7 +42,7 @@ def _get_db_span_description( def _set_db_data_on_span( - span: "StreamedSpan", connection_params: "dict[str, Any]" + span: "Span", connection_params: "dict[str, Any]" ) -> None: db = connection_params.get("db") host = connection_params.get("host") @@ -61,7 +61,7 @@ def _set_db_data_on_span( span.set_attribute(SPANDATA.SERVER_PORT, port) -def _set_db_data(span: "StreamedSpan", redis_instance: "Redis[Any]") -> None: +def _set_db_data(span: "Span", redis_instance: "Redis[Any]") -> None: try: _set_db_data_on_span(span, redis_instance.connection_pool.connection_kwargs) except AttributeError: diff --git a/sentry_sdk/integrations/redis/redis_cluster.py b/sentry_sdk/integrations/redis/redis_cluster.py index 74cd12cab7..bb2e8fe0ca 100644 --- a/sentry_sdk/integrations/redis/redis_cluster.py +++ b/sentry_sdk/integrations/redis/redis_cluster.py @@ -26,11 +26,11 @@ RedisCluster as AsyncRedisCluster, ) - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span def _set_async_cluster_db_data( - span: "StreamedSpan", + span: "Span", async_redis_cluster_instance: "AsyncRedisCluster[Any]", ) -> None: default_node = async_redis_cluster_instance.get_default_node() @@ -39,7 +39,7 @@ def _set_async_cluster_db_data( def _set_async_cluster_pipeline_db_data( - span: "StreamedSpan", + span: "Span", async_redis_cluster_pipeline_instance: "AsyncClusterPipeline[Any]", ) -> None: with capture_internal_exceptions(): @@ -60,7 +60,7 @@ def _set_async_cluster_pipeline_db_data( def _set_cluster_db_data( - span: "StreamedSpan", redis_cluster_instance: "RedisCluster[Any]" + span: "Span", redis_cluster_instance: "RedisCluster[Any]" ) -> None: default_node = redis_cluster_instance.get_default_node() diff --git a/sentry_sdk/integrations/redis/utils.py b/sentry_sdk/integrations/redis/utils.py index b14626a62d..a67923a232 100644 --- a/sentry_sdk/integrations/redis/utils.py +++ b/sentry_sdk/integrations/redis/utils.py @@ -9,7 +9,7 @@ _SINGLE_KEY_COMMANDS, ) from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.utils import SENSITIVE_DATA_SUBSTITUTE, has_data_collection_enabled if TYPE_CHECKING: @@ -109,7 +109,7 @@ def _parse_rediscluster_command(command: "Any") -> "Sequence[Any]": def _set_client_data( - span: "StreamedSpan", is_cluster: bool, name: str, *args: "Any" + span: "Span", is_cluster: bool, name: str, *args: "Any" ) -> None: if name: span.set_attribute(SPANDATA.DB_OPERATION_NAME, name) diff --git a/sentry_sdk/integrations/rq.py b/sentry_sdk/integrations/rq.py index b361e15371..4cf021d5ab 100644 --- a/sentry_sdk/integrations/rq.py +++ b/sentry_sdk/integrations/rq.py @@ -138,7 +138,7 @@ def sentry_patched_enqueue_job( return old_enqueue_job(self, job, **kwargs) scope = sentry_sdk.get_current_scope() - if scope.streamed_span is not None: + if scope.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 cde4b4716f..f0fef5d3c9 100644 --- a/sentry_sdk/integrations/rust_tracing.py +++ b/sentry_sdk/integrations/rust_tracing.py @@ -40,7 +40,7 @@ from sentry_sdk.utils import SENSITIVE_DATA_SUBSTITUTE if TYPE_CHECKING: - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span class RustTracingLevel(Enum): @@ -170,7 +170,7 @@ def _include_tracing_fields(self) -> bool: else self.include_tracing_fields ) - def on_event(self, event: str, sentry_span: "StreamedSpan") -> None: + def on_event(self, event: str, sentry_span: "Span") -> None: deserialized_event = json.loads(event) metadata = deserialized_event.get("metadata", {}) @@ -184,7 +184,7 @@ def on_event(self, event: str, sentry_span: "StreamedSpan") -> None: elif event_type == EventTypeMapping.Event: process_event(deserialized_event) - def on_new_span(self, attrs: str, span_id: str) -> "Optional[StreamedSpan]": + def on_new_span(self, attrs: str, span_id: str) -> "Optional[Span]": attrs = json.loads(attrs) metadata = attrs.get("metadata", {}) @@ -223,13 +223,13 @@ def on_new_span(self, attrs: str, span_id: str) -> "Optional[StreamedSpan]": return sentry_span - def on_close(self, span_id: str, sentry_span: "StreamedSpan") -> None: + def on_close(self, span_id: str, sentry_span: "Span") -> None: if sentry_span is None: return sentry_span.__exit__(None, None, None) - def on_record(self, span_id: str, values: str, sentry_span: "StreamedSpan") -> None: + def on_record(self, span_id: str, values: str, sentry_span: "Span") -> None: if sentry_span is None: return diff --git a/sentry_sdk/integrations/sqlalchemy.py b/sentry_sdk/integrations/sqlalchemy.py index 9066e033ed..16eda89af5 100644 --- a/sentry_sdk/integrations/sqlalchemy.py +++ b/sentry_sdk/integrations/sqlalchemy.py @@ -1,6 +1,6 @@ from sentry_sdk.consts import SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version -from sentry_sdk.traces import SpanStatus, StreamedSpan +from sentry_sdk.traces import SpanStatus, Span from sentry_sdk.tracing_utils import ( add_query_source, record_sql_queries, @@ -78,7 +78,7 @@ def _after_cursor_execute( ) # Record query source immediately before span is finished: accurate end timestamp and before the span is flushed. - span: "Optional[StreamedSpan]" = getattr(context, "_sentry_sql_span", None) + span: "Optional[Span]" = getattr(context, "_sentry_sql_span", None) if span is not None: with capture_internal_exceptions(): add_query_source(span) @@ -93,7 +93,7 @@ def _handle_error(context: "Any", *args: "Any") -> None: if execution_context is None: return - span: "Optional[StreamedSpan]" = getattr( + span: "Optional[Span]" = getattr( execution_context, "_sentry_sql_span", None ) @@ -146,7 +146,7 @@ def _get_db_system(name: str) -> "Optional[str]": return None -def _set_db_data(span: "StreamedSpan", conn: "Any") -> None: +def _set_db_data(span: "Span", conn: "Any") -> None: db_system = _get_db_system(conn.engine.name) if db_system is not None: diff --git a/sentry_sdk/integrations/starlette.py b/sentry_sdk/integrations/starlette.py index 7463751fa3..9234a22d1f 100644 --- a/sentry_sdk/integrations/starlette.py +++ b/sentry_sdk/integrations/starlette.py @@ -25,7 +25,7 @@ ) 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.traces import Span from sentry_sdk.tracing import ( SOURCE_FOR_STYLE, TransactionSource, @@ -568,7 +568,7 @@ def event_processor(event: "Event", hint: "Dict[str, Any]") -> "Event": finally: current_span = sentry_sdk.traces.get_current_span() - if type(current_span) is StreamedSpan: + if type(current_span) is Span: attach_request_data = True if has_data_collection_enabled(client.options): attach_request_data = ( @@ -613,7 +613,7 @@ def _sentry_sync_func(*args: "Any", **kwargs: "Any") -> "Any": current_span = sentry_sdk.traces.get_current_span() - if type(current_span) is StreamedSpan: + if type(current_span) is Span: current_span._segment._update_active_thread() sentry_scope = sentry_sdk.get_isolation_scope() diff --git a/sentry_sdk/integrations/stdlib.py b/sentry_sdk/integrations/stdlib.py index dc3cda8e5a..2dc174b617 100644 --- a/sentry_sdk/integrations/stdlib.py +++ b/sentry_sdk/integrations/stdlib.py @@ -9,7 +9,7 @@ from sentry_sdk.consts import _SENTRY_HEADER_NAMES, OP, SPANDATA from sentry_sdk.integrations import Integration from sentry_sdk.scope import add_global_event_processor -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.tracing import SENTRY_TRACE_HEADER_NAME from sentry_sdk.tracing_utils import ( EnvironHeaders, @@ -69,7 +69,7 @@ def add_python_runtime_context( return event -def _complete_span(span: "StreamedSpan") -> None: +def _complete_span(span: "Span") -> None: with capture_internal_exceptions(): add_http_request_source(span) span.end() @@ -272,7 +272,7 @@ def putrequest( with capture_internal_exceptions(): parsed_url = parse_url(real_url, sanitize=False) - span: "Optional[StreamedSpan]" = None + span: "Optional[Span]" = None breadcrumb: "dict[str, Any]" = {} url_attributes = get_url_attributes(client, parsed_url) diff --git a/sentry_sdk/integrations/wsgi.py b/sentry_sdk/integrations/wsgi.py index 74dae369f7..6468d6d6a0 100644 --- a/sentry_sdk/integrations/wsgi.py +++ b/sentry_sdk/integrations/wsgi.py @@ -37,7 +37,7 @@ ) from sentry_sdk._types import Event, EventProcessor - from sentry_sdk.traces import StreamedSpan + from sentry_sdk.traces import Span from sentry_sdk.utils import ExcInfo WsgiResponseIter = TypeVar("WsgiResponseIter") @@ -127,7 +127,7 @@ def __call__( method = environ.get("REQUEST_METHOD", "").upper() - span_ctx: "ContextManager[Union[StreamedSpan, None]]" = ( + span_ctx: "ContextManager[Union[Span, None]]" = ( nullcontext() ) if method in self.http_methods_to_capture: @@ -203,7 +203,7 @@ def __call__( def _sentry_start_response( old_start_response: "StartResponse", - span: "Optional[Union[StreamedSpan]]", + span: "Optional[Union[Span]]", status: str, response_headers: "WsgiResponseHeaders", exc_info: "Optional[WsgiExcInfo]" = None, diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index 64135476ca..7d2cc3d5a9 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -23,8 +23,8 @@ from sentry_sdk.session import Session from sentry_sdk.traces import ( _DEFAULT_PARENT_SPAN, - NoOpStreamedSpan, - StreamedSpan, + NoOpSpan, + Span, ) from sentry_sdk.tracing import ( BAGGAGE_HEADER_NAME, @@ -243,7 +243,7 @@ def __init__( self._propagation_context: "Optional[PropagationContext]" = None self._n_breadcrumbs_truncated: int = 0 - self._server_segment_span: "Optional[StreamedSpan]" = None + self._server_segment_span: "Optional[Span]" = None self._agent_framework_chat_generation_entered: "bool" = False self.client: "sentry_sdk.client.BaseClient" = NonRecordingClient() @@ -574,8 +574,8 @@ def get_traceparent(self, *args: "Any", **kwargs: "Any") -> "Optional[str]": return self.get_active_propagation_context().to_traceparent() # If we have an active span, return traceparent from there - if self.streamed_span is not None: - return self.streamed_span._to_traceparent() + if self.span is not None: + return self.span._to_traceparent() # else return traceparent from the propagation context return self.get_active_propagation_context().to_traceparent() @@ -591,8 +591,8 @@ def get_baggage(self, *args: "Any", **kwargs: "Any") -> "Optional[Baggage]": return self.get_active_propagation_context().get_baggage() # If we have an active span, return baggage from there - if self.streamed_span is not None: - return self.streamed_span._to_baggage() + if self.span is not None: + return self.span._to_baggage() # else return baggage from the propagation context return self.get_active_propagation_context().get_baggage() @@ -642,7 +642,7 @@ def iter_trace_propagation_headers( """ client = self.get_client() - span = kwargs.pop("span", None) or self.streamed_span + span = kwargs.pop("span", None) or self.span if has_tracing_enabled(client.options) and span is not None: for header in span._iter_headers(): @@ -693,7 +693,7 @@ def clear(self) -> None: self.clear_breadcrumbs() self._should_capture: bool = True - self._span: "Optional[StreamedSpan]" = None + self._span: "Optional[Span]" = None self._session: "Optional[Session]" = None self._force_auto_session_tracking: "Optional[bool]" = None @@ -742,20 +742,20 @@ def set_user(self, value: "Optional[Dict[str, Any]]") -> None: session.update(user=value) @property - def streamed_span(self) -> "Optional[StreamedSpan]": + def span(self) -> "Optional[Span]": """Get/set current tracing span.""" - return self._span if isinstance(self._span, StreamedSpan) else None + return self._span if isinstance(self._span, Span) else None - @streamed_span.setter - def streamed_span(self, span: "Optional[StreamedSpan]") -> None: + @span.setter + def span(self, span: "Optional[Span]") -> None: self._span = span # Also set _transaction and _transaction_info in streaming mode as this # is used for populating events and linking them to segments - if not isinstance(span, StreamedSpan) or not span._is_segment(): + if not isinstance(span, Span) or not span._is_segment(): return - if type(span) is StreamedSpan: + if type(span) is Span: self._transaction = span.name if span._attributes.get("sentry.segment.name.source"): self._transaction_info["source"] = str( @@ -763,7 +763,7 @@ def streamed_span(self, span: "Optional[StreamedSpan]") -> None: ) return - if type(span) is NoOpStreamedSpan: + if type(span) is NoOpSpan: if span._name is not None: self._transaction = span.name if span._attributes.get("sentry.segment.name.source"): @@ -937,10 +937,10 @@ def start_span( self, name: str, attributes: "Optional[Attributes]", - parent_span: "Optional[StreamedSpan]", + parent_span: "Optional[Span]", active: bool, - ) -> "StreamedSpan": - if isinstance(parent_span, NoOpStreamedSpan): + ) -> "Span": + if isinstance(parent_span, NoOpSpan): # parent_span is only set if the user explicitly set it logger.debug( "Ignored parent span provided. Span will be parented to the " @@ -948,9 +948,9 @@ def start_span( ) if parent_span is _DEFAULT_PARENT_SPAN or isinstance( - parent_span, NoOpStreamedSpan + parent_span, NoOpSpan ): - parent_span = self.streamed_span + parent_span = self.span # If no eligible parent_span was provided and there is no currently # active span, this is a new segment @@ -958,7 +958,7 @@ def start_span( propagation_context = self.get_active_propagation_context() if is_ignored_span(name, attributes): - return NoOpStreamedSpan( + return NoOpSpan( name=name, attributes=attributes, scope=self, @@ -980,7 +980,7 @@ def start_span( self._update_sample_rate(sample_rate) if sampled is False or sampled is None: - return NoOpStreamedSpan( + return NoOpSpan( name=name, attributes=attributes, scope=self, @@ -995,7 +995,7 @@ def start_span( sample_rate=sample_rate, ) - return StreamedSpan( + return Span( name=name, attributes=attributes, active=active, @@ -1012,7 +1012,7 @@ def start_span( # This is a child span; take propagation context from the parent span with new_scope(): if is_ignored_span(name, attributes): - return NoOpStreamedSpan( + return NoOpSpan( name=name, attributes=attributes, segment=parent_span._segment, @@ -1022,8 +1022,8 @@ def start_span( unsampled_reason="ignored", ) - if isinstance(parent_span, NoOpStreamedSpan): - return NoOpStreamedSpan( + if isinstance(parent_span, NoOpSpan): + return NoOpSpan( name=name, attributes=attributes, segment=parent_span._segment, @@ -1033,7 +1033,7 @@ def start_span( unsampled_reason=parent_span._unsampled_reason, ) - return StreamedSpan( + return Span( name=name, attributes=attributes, active=active, @@ -1122,7 +1122,7 @@ def _capture_metric(self, metric: "Optional[Metric]") -> None: client._capture_metric(metric, scope=merged_scope) - def _capture_span(self, span: "Optional[StreamedSpan]") -> None: + def _capture_span(self, span: "Optional[Span]") -> None: if span is None: return @@ -1375,7 +1375,7 @@ def _apply_flags_to_event( ) def _apply_scope_attributes_to_telemetry( - self, telemetry: "Union[Log, Metric, StreamedSpan]" + self, telemetry: "Union[Log, Metric, Span]" ) -> None: # TODO: turn Logs, Metrics into actual classes if isinstance(telemetry, dict): @@ -1388,7 +1388,7 @@ def _apply_scope_attributes_to_telemetry( attributes[attribute] = value def _apply_user_attributes_to_telemetry( - self, telemetry: "Union[Log, Metric, StreamedSpan]" + self, telemetry: "Union[Log, Metric, Span]" ) -> None: if isinstance(telemetry, dict): attributes = telemetry["attributes"] @@ -1518,10 +1518,10 @@ def apply_to_event( return event @_disable_capture - def apply_to_telemetry(self, telemetry: "Union[Log, Metric, StreamedSpan]") -> None: + def apply_to_telemetry(self, telemetry: "Union[Log, Metric, Span]") -> None: # Attributes-based events and telemetry go through here (logs, metrics, # spansV2) - if not isinstance(telemetry, StreamedSpan): + if not isinstance(telemetry, Span): trace_context = self.get_trace_context() trace_id = trace_context.get("trace_id") if telemetry.get("trace_id") is None and trace_id is not None: @@ -1532,7 +1532,7 @@ def apply_to_telemetry(self, telemetry: "Union[Log, Metric, StreamedSpan]") -> N # isn't one if telemetry.get("span_id") is None: if self._span is not None and not isinstance( - self._span, NoOpStreamedSpan + self._span, NoOpSpan ): telemetry["span_id"] = self._span.span_id else: diff --git a/sentry_sdk/traces.py b/sentry_sdk/traces.py index c5ab27aa24..b4d15d8c7e 100644 --- a/sentry_sdk/traces.py +++ b/sentry_sdk/traces.py @@ -107,7 +107,7 @@ def __init__( self, name: str, attributes: "Optional[Attributes]" = None, - parent_span: "Optional[StreamedSpan]" = _DEFAULT_PARENT_SPAN, # type: ignore[assignment] + parent_span: "Optional[Span]" = _DEFAULT_PARENT_SPAN, # type: ignore[assignment] active: bool = True, ): self._span = start_span( @@ -116,13 +116,13 @@ def __init__( parent_span=parent_span, active=active, ) - if type(self._span) is not StreamedSpan: + if type(self._span) is not Span: return self.span._scope._agent_framework_chat_generation_entered = True @property - def span(self) -> "StreamedSpan": + def span(self) -> "Span": return self._span def __enter__(self) -> "_AgentFrameworkChatGenerationContext": @@ -131,7 +131,7 @@ def __enter__(self) -> "_AgentFrameworkChatGenerationContext": def __exit__( self, ty: "Optional[Any]", value: "Optional[Any]", tb: "Optional[Any]" ) -> None: - if type(self._span) is not StreamedSpan: + if type(self._span) is not Span: self._span.__exit__(ty, value, tb) try: @@ -143,9 +143,9 @@ def __exit__( def start_span( name: str, attributes: "Optional[Attributes]" = None, - parent_span: "Optional[StreamedSpan]" = _DEFAULT_PARENT_SPAN, # type: ignore[assignment] + parent_span: "Optional[Span]" = _DEFAULT_PARENT_SPAN, # type: ignore[assignment] active: bool = True, -) -> "StreamedSpan": +) -> "Span": """ Start a span. @@ -189,7 +189,7 @@ def start_span( parent. If not provided, the parent will be set to the currently active span, if any. If set to `None`, this span will become a new root-level span. - :type parent_span: "Optional[StreamedSpan]" + :type parent_span: "Optional[Span]" :param active: Controls whether spans started while this span is running will automatically become its children. That's the default behavior. If @@ -198,7 +198,7 @@ def start_span( :type active: bool :return: The span that has been started. - :rtype: StreamedSpan + :rtype: Span """ return sentry_sdk.get_current_scope().start_span( name, attributes, parent_span, active @@ -243,7 +243,7 @@ def new_trace() -> None: sentry_sdk.get_current_scope().set_new_propagation_context() -class StreamedSpan: +class Span: """ A span holds timing information of a block of code. @@ -281,7 +281,7 @@ def __init__( attributes: "Optional[Attributes]" = None, active: bool = True, scope: "sentry_sdk.Scope", - segment: "Optional[StreamedSpan]" = None, + segment: "Optional[Span]" = None, trace_id: "Optional[str]" = None, parent_span_id: "Optional[str]" = None, parent_sampled: "Optional[bool]" = None, @@ -342,7 +342,7 @@ def __repr__(self) -> str: f"active={self._active})>" ) - def __enter__(self) -> "StreamedSpan": + def __enter__(self) -> "Span": return self def __exit__( @@ -375,8 +375,8 @@ def finish(self, end_timestamp: "Optional[Union[float, datetime]]" = None) -> No def _start(self) -> None: if self._active: - old_span = self._scope.streamed_span - self._scope.streamed_span = self + old_span = self._scope.span + self._scope.span = self self._previous_span_on_scope = old_span def _end(self, end_timestamp: "Optional[Union[float, datetime]]" = None) -> None: @@ -394,7 +394,7 @@ def _end(self, end_timestamp: "Optional[Union[float, datetime]]" = None) -> None with capture_internal_exceptions(): old_span = self._previous_span_on_scope del self._previous_span_on_scope - self._scope.streamed_span = old_span + self._scope.span = old_span # Set attributes from the segment. These are set on span end on purpose # so that we have the best chance to capture the segment's final name @@ -639,7 +639,7 @@ def _to_json(self) -> "SpanJSON": return res -class NoOpStreamedSpan(StreamedSpan): +class NoOpSpan(Span): __slots__ = ( "_sampled", "_finished", @@ -650,7 +650,7 @@ def __init__( self, name: "Optional[str]" = None, attributes: "Optional[Attributes]" = None, - segment: "Optional[StreamedSpan]" = None, + segment: "Optional[Span]" = None, trace_id: "Optional[str]" = None, parent_span_id: "Optional[str]" = None, parent_sampled: "Optional[bool]" = None, @@ -690,7 +690,7 @@ def __init__( def __repr__(self) -> str: return f"<{self.__class__.__name__}(name={self.name}, sampled={self.sampled})>" - def __enter__(self) -> "NoOpStreamedSpan": + def __enter__(self) -> "NoOpSpan": return self def __exit__( @@ -702,8 +702,8 @@ def _start(self) -> None: if self._scope is None: return - old_span = self._scope.streamed_span - self._scope.streamed_span = self + old_span = self._scope.span + self._scope.span = self self._previous_span_on_scope = old_span def _end(self, end_timestamp: "Optional[Union[float, datetime]]" = None) -> None: @@ -726,7 +726,7 @@ def _end(self, end_timestamp: "Optional[Union[float, datetime]]" = None) -> None with capture_internal_exceptions(): old_span = self._previous_span_on_scope del self._previous_span_on_scope - self._scope.streamed_span = old_span + self._scope.span = old_span self._finished = True @@ -799,6 +799,9 @@ def _get_trace_context(self) -> "dict[str, Any]": "dynamic_sampling_context": self._dynamic_sampling_context(), } +# backwards compat +StreamedSpan = Span +NoOpStreamedSpan = NoOpSpan if TYPE_CHECKING: @@ -892,12 +895,12 @@ def make_db_query(sql): def get_current_span( scope: "Optional[sentry_sdk.Scope]" = None, -) -> "Optional[StreamedSpan]": +) -> "Optional[Span]": """ - Returns the currently active span on the scope if the span is a `StreamedSpan`, otherwise `None`. + Returns the currently active span on the scope if the span is a `Span`, otherwise `None`. """ scope = scope or sentry_sdk.get_current_scope() - current_span = scope.streamed_span + current_span = scope.span return current_span diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py index 756f934dc3..3c16c3cb14 100644 --- a/sentry_sdk/tracing_utils.py +++ b/sentry_sdk/tracing_utils.py @@ -121,7 +121,7 @@ def record_sql_queries( record_cursor_repr: bool = False, span_origin: str = "manual", span_op_override_value: "Optional[str]" = None, -) -> "Generator[sentry_sdk.traces.StreamedSpan, None, None]": +) -> "Generator[sentry_sdk.traces.Span, None, None]": # TODO: Bring back capturing of params by default client = sentry_sdk.get_client() if has_data_collection_enabled(client.options): @@ -258,7 +258,7 @@ def _should_be_included( def add_source( - span: "sentry_sdk.traces.StreamedSpan", + span: "sentry_sdk.traces.Span", project_root: "Optional[str]", in_app_include: "Optional[list[str]]", in_app_exclude: "Optional[list[str]]", @@ -333,7 +333,7 @@ def add_source( def add_query_source( - span: "sentry_sdk.traces.StreamedSpan", + span: "sentry_sdk.traces.Span", ) -> None: """ Adds OTel compatible source code information to a database query span @@ -366,7 +366,7 @@ def add_query_source( ) -def add_http_request_source(span: "sentry_sdk.traces.StreamedSpan") -> None: +def add_http_request_source(span: "sentry_sdk.traces.Span") -> None: """ Adds OTel compatible source code information to a span for an outgoing HTTP request """ @@ -760,7 +760,7 @@ def populate_from_propagation_context( return Baggage(sentry_items, third_party_items, mutable) @classmethod - def populate_from_segment(cls, segment: "StreamedSpan") -> "Baggage": + def populate_from_segment(cls, segment: "Span") -> "Baggage": """ Populate fresh baggage entry with sentry_items and make it immutable if this is the head SDK which originates traces. @@ -1297,7 +1297,7 @@ def _matches(rule: "Any", value: "Any") -> bool: # Circular imports from sentry_sdk.traces import ( LOW_QUALITY_SEGMENT_SOURCES, - StreamedSpan, + Span, ) from sentry_sdk.tracing import ( BAGGAGE_HEADER_NAME, diff --git a/tests/conftest.py b/tests/conftest.py index 01f3bf6d8b..3980845097 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -599,11 +599,7 @@ def maybe_monkeypatched_threading(request): @pytest.fixture def render_span_tree(): - def inner(spans, root_span=None): - streamed_spans = False - if root_span is None: - streamed_spans = True - + def inner(spans): by_parent = {} for span in spans: if "parent_span_id" not in span: @@ -613,15 +609,10 @@ def inner(spans, root_span=None): by_parent.setdefault(span["parent_span_id"], []).append(span) def render_span(span): - if streamed_spans: - yield "- sentry.op={}: name={}".format( - json.dumps(span["attributes"].get("sentry.op")), - json.dumps(span["name"]), - ) - else: - yield "- op={}: description={}".format( - json.dumps(span.get("op")), json.dumps(span.get("description")) - ) + yield "- sentry.op={}: name={}".format( + json.dumps(span["attributes"].get("sentry.op")), + json.dumps(span["name"]), + ) for subspan in by_parent.get(span["span_id"]) or (): for line in render_span(subspan): diff --git a/tests/integrations/aiohttp/test_aiohttp.py b/tests/integrations/aiohttp/test_aiohttp.py index 274d18d535..f0fcce6c5a 100644 --- a/tests/integrations/aiohttp/test_aiohttp.py +++ b/tests/integrations/aiohttp/test_aiohttp.py @@ -1843,7 +1843,7 @@ async def hello(request): server_span = items[1].payload # The integration's generic Exception path reraises without recording - # http.response.status_code on the server span. StreamedSpan.__exit__ + # http.response.status_code on the server span. Span.__exit__ # observes the propagating exception and sets status to "error". assert server_span["attributes"]["sentry.op"] == "http.server" assert "http.response.status_code" not in server_span["attributes"] diff --git a/tests/integrations/django/test_basic.py b/tests/integrations/django/test_basic.py index 3875707f18..cb071c390f 100644 --- a/tests/integrations/django/test_basic.py +++ b/tests/integrations/django/test_basic.py @@ -34,7 +34,7 @@ from sentry_sdk.integrations.django.signals_handlers import _get_receiver_name from sentry_sdk.integrations.executing import ExecutingIntegration from sentry_sdk.profiler.utils import get_frame_name -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from tests.conftest import unpack_werkzeug_response from tests.integrations.django.myapp.signals import myapp_custom_signal_silenced from tests.integrations.django.myapp.wsgi import application @@ -852,7 +852,7 @@ def get_connection_params(self): try: _set_db_data( - StreamedSpan(name="name", scope=sentry_sdk.Scope()), DummyBackend() + Span(name="name", scope=sentry_sdk.Scope()), DummyBackend() ) except TypeError: pytest.fail("A TypeError was raised") diff --git a/tests/test_api.py b/tests/test_api.py index 1d5d31c14e..dc323731f5 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -15,25 +15,25 @@ set_tags, ) from sentry_sdk.client import Client, NonRecordingClient -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from tests.conftest import TestTransportWithOptions def test_get_current_span(): fake_scope = mock.MagicMock() - fake_scope.streamed_span = mock.MagicMock() - assert get_current_span(fake_scope) == fake_scope.streamed_span + fake_scope.span = mock.MagicMock() + assert get_current_span(fake_scope) == fake_scope.span - fake_scope.streamed_span = None + fake_scope.span = None assert get_current_span(fake_scope) is None def test_get_current_span_via_traces(): fake_scope = mock.MagicMock() - fake_scope.streamed_span = mock.MagicMock() - assert sentry_sdk.traces.get_current_span(fake_scope) == fake_scope.streamed_span + fake_scope.span = mock.MagicMock() + assert sentry_sdk.traces.get_current_span(fake_scope) == fake_scope.span - fake_scope.streamed_span = None + fake_scope.span = None assert sentry_sdk.traces.get_current_span(fake_scope) is None @@ -43,9 +43,9 @@ def test_get_current_span_current_scope_via_traces(sentry_init): assert sentry_sdk.traces.get_current_span() is None scope = get_current_scope() - fake_span = StreamedSpan(name="abc", scope=scope) + fake_span = Span(name="abc", scope=scope) - assert scope.streamed_span == fake_span + assert scope.span == fake_span assert sentry_sdk.traces.get_current_span() == fake_span diff --git a/tests/tracing/test_http_headers.py b/tests/tracing/test_http_headers.py index d89537e7e3..8dd92fd2da 100644 --- a/tests/tracing/test_http_headers.py +++ b/tests/tracing/test_http_headers.py @@ -3,7 +3,7 @@ import pytest import sentry_sdk -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.tracing_utils import extract_sentrytrace_data @@ -71,7 +71,7 @@ def test_iter_headers(sentry_init, monkeypatch): traces_sample_rate=0.0, ) monkeypatch.setattr( - StreamedSpan, + Span, "_to_traceparent", mock.Mock(return_value="12312012123120121231201212312012-0415201309082013-0"), ) diff --git a/tests/tracing/test_misc.py b/tests/tracing/test_misc.py index 2161eb5d49..cf77da5dd3 100644 --- a/tests/tracing/test_misc.py +++ b/tests/tracing/test_misc.py @@ -4,7 +4,7 @@ import sentry_sdk from sentry_sdk.consts import MATCH_ALL -from sentry_sdk.traces import StreamedSpan +from sentry_sdk.traces import Span from sentry_sdk.tracing_utils import should_propagate_trace from sentry_sdk.utils import Dsn @@ -16,12 +16,12 @@ def test_finds_segment_on_scope(sentry_init): with sentry_sdk.traces.start_span(name="dogpark"): scope = sentry_sdk.get_current_scope() - assert scope.streamed_span is not None - assert isinstance(scope.streamed_span, StreamedSpan) - assert scope.streamed_span.name == "dogpark" + assert scope.span is not None + assert isinstance(scope.span, Span) + assert scope.span.name == "dogpark" assert scope._span is not None - assert isinstance(scope._span, StreamedSpan) + assert isinstance(scope._span, Span) assert scope._span.name == "dogpark" @@ -36,7 +36,7 @@ def test_finds_span_on_scope(sentry_init): scope = sentry_sdk.get_current_scope() assert scope._span is not None - assert isinstance(scope._span, StreamedSpan) + assert isinstance(scope._span, Span) assert scope._span.name == "sniffing" diff --git a/tests/tracing/test_sampling.py b/tests/tracing/test_sampling.py index bd95164458..dbbde25e63 100644 --- a/tests/tracing/test_sampling.py +++ b/tests/tracing/test_sampling.py @@ -55,10 +55,10 @@ def test_get_span_from_scope_regardless_of_sampling_decision( with sentry_sdk.traces.start_span(name="child-child-span"): scope = sentry_sdk.get_current_scope() if sampling_decision is True: - assert scope.streamed_span.name == "child-child-span" + assert scope.span.name == "child-child-span" else: # noop spans are not set on the scope unless they're segments - assert scope.streamed_span.name == "/" + assert scope.span.name == "/" assert scope._transaction == "/" diff --git a/tests/tracing/test_span_streaming.py b/tests/tracing/test_span_streaming.py index e565c84b5b..1dde80b01b 100644 --- a/tests/tracing/test_span_streaming.py +++ b/tests/tracing/test_span_streaming.py @@ -8,9 +8,9 @@ import sentry_sdk from sentry_sdk.profiler.continuous_profiler import get_profiler_id from sentry_sdk.traces import ( - NoOpStreamedSpan, + NoOpSpan, SpanStatus, - StreamedSpan, + Span, ) minimum_python_38 = pytest.mark.skipif( @@ -1345,15 +1345,15 @@ def test_ignore_spans_ignored_segment_drops_whole_tree( with sentry_sdk.traces.start_span(name="ignored") as ignored_span: assert ignored_span.sampled is False - assert isinstance(ignored_span, NoOpStreamedSpan) + assert isinstance(ignored_span, NoOpSpan) with sentry_sdk.traces.start_span(name="not ignored") as span1: assert span1.sampled is False - assert isinstance(span1, NoOpStreamedSpan) + assert isinstance(span1, NoOpSpan) with sentry_sdk.traces.start_span(name="not ignored") as span2: assert span2.sampled is False - assert isinstance(span2, NoOpStreamedSpan) + assert isinstance(span2, NoOpSpan) sentry_sdk.get_client().flush() spans = [item.payload for item in items] @@ -1378,15 +1378,15 @@ def test_ignore_spans_ignored_segment_drops_whole_tree_explicit_parent_span( lost_event_calls = capture_record_lost_event_calls() ignored_span = sentry_sdk.traces.start_span(name="ignored") - assert isinstance(ignored_span, NoOpStreamedSpan) + assert isinstance(ignored_span, NoOpSpan) assert ignored_span.sampled is False span1 = sentry_sdk.traces.start_span(name="not ignored 1", parent_span=ignored_span) - assert isinstance(span1, NoOpStreamedSpan) + assert isinstance(span1, NoOpSpan) assert span1.sampled is False span2 = sentry_sdk.traces.start_span(name="not ignored 2", parent_span=ignored_span) - assert isinstance(span2, NoOpStreamedSpan) + assert isinstance(span2, NoOpSpan) assert span2.sampled is False span1.end() @@ -1456,22 +1456,22 @@ def test_ignore_spans_set_ignored_child_span_as_parent_explicit_parent_span( lost_event_calls = capture_record_lost_event_calls() segment = sentry_sdk.traces.start_span(name="segment") - assert not isinstance(segment, NoOpStreamedSpan) + assert not isinstance(segment, NoOpSpan) assert segment.sampled is True assert segment._parent_span_id is None ignored_span1 = sentry_sdk.traces.start_span(name="ignored", parent_span=segment) - assert isinstance(ignored_span1, NoOpStreamedSpan) + assert isinstance(ignored_span1, NoOpSpan) assert ignored_span1.sampled is False ignored_span2 = sentry_sdk.traces.start_span( name="ignored", parent_span=ignored_span1 ) - assert isinstance(ignored_span2, NoOpStreamedSpan) + assert isinstance(ignored_span2, NoOpSpan) assert ignored_span2.sampled is False span = sentry_sdk.traces.start_span(name="child", parent_span=ignored_span2) - assert not isinstance(span, NoOpStreamedSpan) + assert not isinstance(span, NoOpSpan) assert span.sampled is True assert span._parent_span_id == segment.span_id span.end() @@ -1726,10 +1726,10 @@ def test_ignore_spans_top_level( with sentry_sdk.traces.start_span(name=name, attributes=attributes) as span: if ignored: assert span.sampled is False - assert isinstance(span, NoOpStreamedSpan) + assert isinstance(span, NoOpSpan) else: assert span.sampled is True - assert isinstance(span, StreamedSpan) + assert isinstance(span, Span) sentry_sdk.get_client().flush() spans = [item.payload for item in items] From 367e607d39dec307ff8245123c827cddafbf11d7 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Tue, 15 Sep 2026 13:21:22 +0200 Subject: [PATCH 2/5] . --- sentry_sdk/integrations/aiohttp.py | 2 +- sentry_sdk/integrations/chalice.py | 2 +- sentry_sdk/integrations/huey.py | 2 +- sentry_sdk/integrations/openai_agents/spans/execute_tool.py | 2 +- sentry_sdk/integrations/sqlalchemy.py | 6 ++---- tests/tracing/test_span_streaming.py | 2 +- 6 files changed, 7 insertions(+), 9 deletions(-) diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py index 48a91949e1..84551db868 100644 --- a/sentry_sdk/integrations/aiohttp.py +++ b/sentry_sdk/integrations/aiohttp.py @@ -22,8 +22,8 @@ from sentry_sdk.sessions import track_session from sentry_sdk.traces import ( SegmentNameSource, - SpanStatus, Span, + SpanStatus, ) from sentry_sdk.tracing import ( BAGGAGE_HEADER_NAME, diff --git a/sentry_sdk/integrations/chalice.py b/sentry_sdk/integrations/chalice.py index 5dae03c0ae..f161d82bfc 100644 --- a/sentry_sdk/integrations/chalice.py +++ b/sentry_sdk/integrations/chalice.py @@ -7,8 +7,8 @@ from sentry_sdk.integrations.aws_lambda import _make_request_event_processor from sentry_sdk.traces import ( SegmentNameSource, - SpanStatus, Span, + SpanStatus, ) from sentry_sdk.utils import ( capture_internal_exceptions, diff --git a/sentry_sdk/integrations/huey.py b/sentry_sdk/integrations/huey.py index f242873911..f158bfceec 100644 --- a/sentry_sdk/integrations/huey.py +++ b/sentry_sdk/integrations/huey.py @@ -7,7 +7,7 @@ from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import SegmentNameSource, SpanStatus, Span +from sentry_sdk.traces import SegmentNameSource, Span, SpanStatus from sentry_sdk.tracing import ( BAGGAGE_HEADER_NAME, SENTRY_TRACE_HEADER_NAME, diff --git a/sentry_sdk/integrations/openai_agents/spans/execute_tool.py b/sentry_sdk/integrations/openai_agents/spans/execute_tool.py index e1f06e15e2..b90b089ebe 100644 --- a/sentry_sdk/integrations/openai_agents/spans/execute_tool.py +++ b/sentry_sdk/integrations/openai_agents/spans/execute_tool.py @@ -3,7 +3,7 @@ import sentry_sdk from sentry_sdk.consts import OP, SPANDATA from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.traces import SpanStatus, Span +from sentry_sdk.traces import Span, SpanStatus from sentry_sdk.utils import has_data_collection_enabled from ..consts import SPAN_ORIGIN diff --git a/sentry_sdk/integrations/sqlalchemy.py b/sentry_sdk/integrations/sqlalchemy.py index 16eda89af5..2e13302f99 100644 --- a/sentry_sdk/integrations/sqlalchemy.py +++ b/sentry_sdk/integrations/sqlalchemy.py @@ -1,6 +1,6 @@ from sentry_sdk.consts import SPANDATA from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version -from sentry_sdk.traces import SpanStatus, Span +from sentry_sdk.traces import Span, SpanStatus from sentry_sdk.tracing_utils import ( add_query_source, record_sql_queries, @@ -93,9 +93,7 @@ def _handle_error(context: "Any", *args: "Any") -> None: if execution_context is None: return - span: "Optional[Span]" = getattr( - execution_context, "_sentry_sql_span", None - ) + span: "Optional[Span]" = getattr(execution_context, "_sentry_sql_span", None) if span is not None: span.status = SpanStatus.ERROR diff --git a/tests/tracing/test_span_streaming.py b/tests/tracing/test_span_streaming.py index 1dde80b01b..ebadefa17d 100644 --- a/tests/tracing/test_span_streaming.py +++ b/tests/tracing/test_span_streaming.py @@ -9,8 +9,8 @@ from sentry_sdk.profiler.continuous_profiler import get_profiler_id from sentry_sdk.traces import ( NoOpSpan, - SpanStatus, Span, + SpanStatus, ) minimum_python_38 = pytest.mark.skipif( From ff71b69cbf9ff7d9607f31b454846510b1f176c2 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Tue, 15 Sep 2026 13:27:06 +0200 Subject: [PATCH 3/5] . --- sentry_sdk/integrations/langchain.py | 8 ++++---- sentry_sdk/integrations/pydantic_ai/utils.py | 4 +--- sentry_sdk/integrations/redis/modules/queries.py | 4 +--- sentry_sdk/integrations/redis/utils.py | 4 +--- sentry_sdk/integrations/wsgi.py | 4 +--- sentry_sdk/scope.py | 8 ++------ sentry_sdk/traces.py | 1 + 7 files changed, 11 insertions(+), 22 deletions(-) diff --git a/sentry_sdk/integrations/langchain.py b/sentry_sdk/integrations/langchain.py index a149b3a57f..73d0d55575 100644 --- a/sentry_sdk/integrations/langchain.py +++ b/sentry_sdk/integrations/langchain.py @@ -253,8 +253,8 @@ def _create_span( ) -> "Span": span = None if parent_id: - parent: "Optional[Union[Span, _AgentFrameworkChatGenerationContext]]" = self.span_map.get( - parent_id + parent: "Optional[Union[Span, _AgentFrameworkChatGenerationContext]]" = ( + self.span_map.get(parent_id) ) if parent: span = sentry_sdk.traces.start_span( @@ -290,8 +290,8 @@ def _create_generation_span( ) -> "_AgentFrameworkChatGenerationContext": context = None if parent_id: - parent: "Optional[Union[Span, _AgentFrameworkChatGenerationContext]]" = self.span_map.get( - parent_id + parent: "Optional[Union[Span, _AgentFrameworkChatGenerationContext]]" = ( + self.span_map.get(parent_id) ) if parent: context = _AgentFrameworkChatGenerationContext( diff --git a/sentry_sdk/integrations/pydantic_ai/utils.py b/sentry_sdk/integrations/pydantic_ai/utils.py index 5567e36a97..7e1c06d0a5 100644 --- a/sentry_sdk/integrations/pydantic_ai/utils.py +++ b/sentry_sdk/integrations/pydantic_ai/utils.py @@ -151,9 +151,7 @@ def _set_model_data( span.set_attribute(spandata_key, value) -def _set_available_tools( - span: "Span", agent: "Optional[Agent[Any, Any]]" -) -> None: +def _set_available_tools(span: "Span", agent: "Optional[Agent[Any, Any]]") -> None: """Set available tools data on a span from an agent's function toolset. Args: diff --git a/sentry_sdk/integrations/redis/modules/queries.py b/sentry_sdk/integrations/redis/modules/queries.py index 4d301dea2f..3199df62cd 100644 --- a/sentry_sdk/integrations/redis/modules/queries.py +++ b/sentry_sdk/integrations/redis/modules/queries.py @@ -41,9 +41,7 @@ def _get_db_span_description( return description -def _set_db_data_on_span( - span: "Span", connection_params: "dict[str, Any]" -) -> None: +def _set_db_data_on_span(span: "Span", connection_params: "dict[str, Any]") -> None: db = connection_params.get("db") host = connection_params.get("host") port = connection_params.get("port") diff --git a/sentry_sdk/integrations/redis/utils.py b/sentry_sdk/integrations/redis/utils.py index a67923a232..a8c782018d 100644 --- a/sentry_sdk/integrations/redis/utils.py +++ b/sentry_sdk/integrations/redis/utils.py @@ -108,9 +108,7 @@ def _parse_rediscluster_command(command: "Any") -> "Sequence[Any]": return command.args -def _set_client_data( - span: "Span", is_cluster: bool, name: str, *args: "Any" -) -> None: +def _set_client_data(span: "Span", is_cluster: bool, name: str, *args: "Any") -> None: if name: span.set_attribute(SPANDATA.DB_OPERATION_NAME, name) diff --git a/sentry_sdk/integrations/wsgi.py b/sentry_sdk/integrations/wsgi.py index 6468d6d6a0..0ceba9ee01 100644 --- a/sentry_sdk/integrations/wsgi.py +++ b/sentry_sdk/integrations/wsgi.py @@ -127,9 +127,7 @@ def __call__( method = environ.get("REQUEST_METHOD", "").upper() - span_ctx: "ContextManager[Union[Span, None]]" = ( - nullcontext() - ) + span_ctx: "ContextManager[Union[Span, None]]" = nullcontext() if method in self.http_methods_to_capture: sentry_sdk.traces.continue_trace(dict(_get_headers(environ))) Scope.set_custom_sampling_context({"wsgi_environ": environ}) diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index 7d2cc3d5a9..843a2ec07f 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -947,9 +947,7 @@ def start_span( "currently active span instead." ) - if parent_span is _DEFAULT_PARENT_SPAN or isinstance( - parent_span, NoOpSpan - ): + if parent_span is _DEFAULT_PARENT_SPAN or isinstance(parent_span, NoOpSpan): parent_span = self.span # If no eligible parent_span was provided and there is no currently @@ -1531,9 +1529,7 @@ def apply_to_telemetry(self, telemetry: "Union[Log, Metric, Span]") -> None: # use the trace_context here because it synthesizes a span_id if there # isn't one if telemetry.get("span_id") is None: - if self._span is not None and not isinstance( - self._span, NoOpSpan - ): + if self._span is not None and not isinstance(self._span, NoOpSpan): telemetry["span_id"] = self._span.span_id else: external_propagation_context = get_external_propagation_context() diff --git a/sentry_sdk/traces.py b/sentry_sdk/traces.py index b4d15d8c7e..24966634c0 100644 --- a/sentry_sdk/traces.py +++ b/sentry_sdk/traces.py @@ -799,6 +799,7 @@ def _get_trace_context(self) -> "dict[str, Any]": "dynamic_sampling_context": self._dynamic_sampling_context(), } + # backwards compat StreamedSpan = Span NoOpStreamedSpan = NoOpSpan From affb2490b4da342ed5618316dae907ac9a4e193c Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Tue, 15 Sep 2026 13:27:55 +0200 Subject: [PATCH 4/5] . --- tests/integrations/django/test_basic.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/integrations/django/test_basic.py b/tests/integrations/django/test_basic.py index cb071c390f..710eb1f5a9 100644 --- a/tests/integrations/django/test_basic.py +++ b/tests/integrations/django/test_basic.py @@ -851,9 +851,7 @@ def get_connection_params(self): return {} try: - _set_db_data( - Span(name="name", scope=sentry_sdk.Scope()), DummyBackend() - ) + _set_db_data(Span(name="name", scope=sentry_sdk.Scope()), DummyBackend()) except TypeError: pytest.fail("A TypeError was raised") From 781945fae3e53eb63b80a392f2965ee1f91d70e6 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Tue, 15 Sep 2026 13:51:36 +0200 Subject: [PATCH 5/5] migration guide --- MIGRATION_GUIDE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index faa9ed1bf2..d717e1782b 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -157,6 +157,7 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh - `SanicIntegration` no longer accepts `unsampled_statuses`. - The `trace_ignore_status_codes` option was removed. - `add_attachment` no longer accepts an `add_to_transactions` argument. +- The `stream_gen_ai_spans` option was removed. All spans are streamed now. ## Deprecated