11from sentry_sdk .consts import SPANSTATUS , SPANDATA
22from sentry_sdk .integrations import _check_minimum_version , Integration , DidNotEnable
3- from sentry_sdk .tracing_utils import add_query_source , record_sql_queries
3+ from sentry_sdk .tracing_utils import (
4+ add_query_source ,
5+ record_sql_queries_supporting_streaming ,
6+ )
47from sentry_sdk .utils import (
58 capture_internal_exceptions ,
69 ensure_integration_enabled ,
710 parse_version ,
811)
12+ from sentry_sdk .traces import StreamedSpan , SpanStatus
13+ from sentry_sdk .tracing import Span
914
1015try :
1116 from sqlalchemy .engine import Engine # type: ignore
2025 from typing import Any
2126 from typing import ContextManager
2227 from typing import Optional
23-
24- from sentry_sdk .tracing import Span
28+ from typing import Union
2529
2630
2731class SqlalchemyIntegration (Integration ):
@@ -48,7 +52,7 @@ def _before_cursor_execute(
4852 executemany : bool ,
4953 * args : "Any" ,
5054) -> None :
51- ctx_mgr = record_sql_queries (
55+ ctx_mgr = record_sql_queries_supporting_streaming (
5256 cursor ,
5357 statement ,
5458 parameters ,
@@ -78,12 +82,19 @@ def _after_cursor_execute(
7882 context , "_sentry_sql_span_manager" , None
7983 )
8084
85+ # Record query source immediately before span is finished: accurate end timestamp and before the span is flushed.
86+ span : "Optional[Union[Span, StreamedSpan]]" = getattr (
87+ context , "_sentry_sql_span" , None
88+ )
89+ if isinstance (span , StreamedSpan ):
90+ with capture_internal_exceptions ():
91+ add_query_source (span )
92+
8193 if ctx_mgr is not None :
8294 context ._sentry_sql_span_manager = None
8395 ctx_mgr .__exit__ (None , None , None )
8496
85- span : "Optional[Span]" = getattr (context , "_sentry_sql_span" , None )
86- if span is not None :
97+ if isinstance (span , Span ):
8798 with capture_internal_exceptions ():
8899 add_query_source (span )
89100
@@ -96,7 +107,10 @@ def _handle_error(context: "Any", *args: "Any") -> None:
96107 span : "Optional[Span]" = getattr (execution_context , "_sentry_sql_span" , None )
97108
98109 if span is not None :
99- span .set_status (SPANSTATUS .INTERNAL_ERROR )
110+ if isinstance (span , StreamedSpan ):
111+ span .status = SpanStatus .ERROR
112+ else :
113+ span .set_status (SPANSTATUS .INTERNAL_ERROR )
100114
101115 # _after_cursor_execute does not get called for crashing SQL stmts. Judging
102116 # from SQLAlchemy codebase it does seem like any error coming into this
@@ -132,29 +146,43 @@ def _get_db_system(name: str) -> "Optional[str]":
132146 return None
133147
134148
135- def _set_db_data (span : "Span" , conn : "Any" ) -> None :
149+ def _set_db_data (span : "Union[ Span, StreamedSpan] " , conn : "Any" ) -> None :
136150 db_system = _get_db_system (conn .engine .name )
137- if db_system is not None :
138- span .set_data (SPANDATA .DB_SYSTEM , db_system )
151+
152+ if isinstance (span , StreamedSpan ):
153+ if db_system is not None :
154+ span .set_attribute (SPANDATA .DB_SYSTEM_NAME , db_system )
155+ else :
156+ if db_system is not None :
157+ span .set_data (SPANDATA .DB_SYSTEM , db_system )
158+
159+ if isinstance (span , StreamedSpan ):
160+ set_on_span = span .set_attribute
161+ else :
162+ set_on_span = span .set_data
139163
140164 try :
141165 driver = conn .dialect .driver
142166 if driver :
143- span . set_data (SPANDATA .DB_DRIVER_NAME , driver )
167+ set_on_span (SPANDATA .DB_DRIVER_NAME , driver )
144168 except Exception :
145169 pass
146170
147171 if conn .engine .url is None :
148172 return
149173
150174 db_name = conn .engine .url .database
151- if db_name is not None :
152- span .set_data (SPANDATA .DB_NAME , db_name )
175+ if isinstance (span , StreamedSpan ):
176+ if db_name is not None :
177+ span .set_attribute (SPANDATA .DB_NAMESPACE , db_name )
178+ else :
179+ if db_name is not None :
180+ span .set_data (SPANDATA .DB_NAME , db_name )
153181
154182 server_address = conn .engine .url .host
155183 if server_address is not None :
156- span . set_data (SPANDATA .SERVER_ADDRESS , server_address )
184+ set_on_span (SPANDATA .SERVER_ADDRESS , server_address )
157185
158186 server_port = conn .engine .url .port
159187 if server_port is not None :
160- span . set_data (SPANDATA .SERVER_PORT , server_port )
188+ set_on_span (SPANDATA .SERVER_PORT , server_port )
0 commit comments