1515from sentry_sdk .integrations .wsgi import SentryWsgiMiddleware
1616from sentry_sdk .scope import add_global_event_processor , should_send_default_pii
1717from sentry_sdk .serializer import add_global_repr_processor , add_repr_sequence_type
18+ from sentry_sdk .traces import StreamedSpan
1819from sentry_sdk .tracing import SOURCE_FOR_STYLE , TransactionSource
19- from sentry_sdk .tracing_utils import add_query_source , record_sql_queries
20+ from sentry_sdk .tracing_utils import (
21+ add_query_source ,
22+ has_span_streaming_enabled ,
23+ record_sql_queries ,
24+ )
2025from sentry_sdk .utils import (
2126 CONTEXTVARS_ERROR_MESSAGE ,
2227 HAS_REAL_CONTEXTVARS ,
8287
8388 from sentry_sdk ._types import Event , EventProcessor , Hint , NotImplementedType
8489 from sentry_sdk .integrations .wsgi import _ScopedResponse
90+ from sentry_sdk .traces import StreamedSpan
8591 from sentry_sdk .tracing import Span
8692
8793
@@ -639,8 +645,13 @@ def execute(
639645 _set_db_data (span , self )
640646 result = real_execute (self , sql , params )
641647
642- with capture_internal_exceptions ():
643- add_query_source (span )
648+ if isinstance (span , StreamedSpan ):
649+ with capture_internal_exceptions ():
650+ add_query_source (span )
651+
652+ if not isinstance (span , StreamedSpan ):
653+ with capture_internal_exceptions ():
654+ add_query_source (span )
644655
645656 return result
646657
@@ -660,8 +671,13 @@ def executemany(
660671
661672 result = real_executemany (self , sql , param_list )
662673
663- with capture_internal_exceptions ():
664- add_query_source (span )
674+ if isinstance (span , StreamedSpan ):
675+ with capture_internal_exceptions ():
676+ add_query_source (span )
677+
678+ if not isinstance (span , StreamedSpan ):
679+ with capture_internal_exceptions ():
680+ add_query_source (span )
665681
666682 return result
667683
@@ -670,41 +686,77 @@ def connect(self: "BaseDatabaseWrapper") -> None:
670686 with capture_internal_exceptions ():
671687 sentry_sdk .add_breadcrumb (message = "connect" , category = "query" )
672688
673- with sentry_sdk .start_span (
674- op = OP .DB ,
675- name = "connect" ,
676- origin = DjangoIntegration .origin_db ,
677- ) as span :
678- _set_db_data (span , self )
679- return real_connect (self )
689+ span_streaming = has_span_streaming_enabled (sentry_sdk .get_client ().options )
690+ if span_streaming :
691+ with sentry_sdk .traces .start_span (
692+ name = "connect" ,
693+ attributes = {
694+ "sentry.op" : OP .DB ,
695+ "sentry.origin" : DjangoIntegration .origin_db ,
696+ },
697+ ) as span :
698+ _set_db_data (span , self )
699+ return real_connect (self )
700+ else :
701+ with sentry_sdk .start_span (
702+ op = OP .DB ,
703+ name = "connect" ,
704+ origin = DjangoIntegration .origin_db ,
705+ ) as span :
706+ _set_db_data (span , self )
707+ return real_connect (self )
680708
681709 def _commit (self : "BaseDatabaseWrapper" ) -> None :
682710 integration = sentry_sdk .get_client ().get_integration (DjangoIntegration )
683711
684712 if integration is None or not integration .db_transaction_spans :
685713 return real_commit (self )
686714
687- with sentry_sdk .start_span (
688- op = OP .DB ,
689- name = SPANNAME .DB_COMMIT ,
690- origin = DjangoIntegration .origin_db ,
691- ) as span :
692- _set_db_data (span , self , SPANNAME .DB_COMMIT )
693- return real_commit (self )
715+ span_streaming = has_span_streaming_enabled (sentry_sdk .get_client ().options )
716+ if span_streaming :
717+ with sentry_sdk .traces .start_span (
718+ name = SPANNAME .DB_COMMIT ,
719+ attributes = {
720+ "sentry.op" : OP .DB ,
721+ "sentry.origin" : DjangoIntegration .origin_db ,
722+ },
723+ ) as span :
724+ _set_db_data (span , self , SPANNAME .DB_COMMIT )
725+ return real_commit (self )
726+ else :
727+ with sentry_sdk .start_span (
728+ op = OP .DB ,
729+ name = SPANNAME .DB_COMMIT ,
730+ origin = DjangoIntegration .origin_db ,
731+ ) as span :
732+ _set_db_data (span , self , SPANNAME .DB_COMMIT )
733+ return real_commit (self )
694734
695735 def _rollback (self : "BaseDatabaseWrapper" ) -> None :
696736 integration = sentry_sdk .get_client ().get_integration (DjangoIntegration )
697737
698738 if integration is None or not integration .db_transaction_spans :
699739 return real_rollback (self )
700740
701- with sentry_sdk .start_span (
702- op = OP .DB ,
703- name = SPANNAME .DB_ROLLBACK ,
704- origin = DjangoIntegration .origin_db ,
705- ) as span :
706- _set_db_data (span , self , SPANNAME .DB_ROLLBACK )
707- return real_rollback (self )
741+ span_streaming = has_span_streaming_enabled (sentry_sdk .get_client ().options )
742+ if span_streaming :
743+ with sentry_sdk .traces .start_span (
744+ name = SPANNAME .DB_ROLLBACK ,
745+ attributes = {
746+ "sentry.op" : OP .DB ,
747+ "sentry.origin" : DjangoIntegration .origin_db ,
748+ },
749+ ) as span :
750+ _set_db_data (span , self , SPANNAME .DB_ROLLBACK )
751+ return real_rollback (self )
752+ else :
753+ with sentry_sdk .start_span (
754+ op = OP .DB ,
755+ name = SPANNAME .DB_ROLLBACK ,
756+ origin = DjangoIntegration .origin_db ,
757+ ) as span :
758+ _set_db_data (span , self , SPANNAME .DB_ROLLBACK )
759+ return real_rollback (self )
708760
709761 CursorWrapper .execute = execute
710762 CursorWrapper .executemany = executemany
@@ -715,14 +767,22 @@ def _rollback(self: "BaseDatabaseWrapper") -> None:
715767
716768
717769def _set_db_data (
718- span : "Span" , cursor_or_db : "Any" , db_operation : "Optional[str]" = None
770+ span : "Union[Span, StreamedSpan]" ,
771+ cursor_or_db : "Any" ,
772+ db_operation : "Optional[str]" = None ,
719773) -> None :
720774 db = cursor_or_db .db if hasattr (cursor_or_db , "db" ) else cursor_or_db
721775 vendor = db .vendor
722- span .set_data (SPANDATA .DB_SYSTEM , vendor )
776+ if isinstance (span , StreamedSpan ):
777+ span .set_attribute (SPANDATA .DB_SYSTEM_NAME , vendor )
723778
724- if db_operation is not None :
725- span .set_data (SPANDATA .DB_OPERATION , db_operation )
779+ if db_operation is not None :
780+ span .set_attribute (SPANDATA .DB_OPERATION_NAME , db_operation )
781+ else :
782+ span .set_data (SPANDATA .DB_SYSTEM , vendor )
783+
784+ if db_operation is not None :
785+ span .set_data (SPANDATA .DB_OPERATION , db_operation )
726786
727787 # Some custom backends override `__getattr__`, making it look like `cursor_or_db`
728788 # actually has a `connection` and the `connection` has a `get_dsn_parameters`
@@ -754,20 +814,29 @@ def _set_db_data(
754814 connection_params = db .get_connection_params ()
755815
756816 db_name = connection_params .get ("dbname" ) or connection_params .get ("database" )
757- if db_name is not None :
758- span .set_data (SPANDATA .DB_NAME , db_name )
817+
818+ if isinstance (span , StreamedSpan ):
819+ if db_name is not None :
820+ span .set_attribute (SPANDATA .DB_NAMESPACE , db_name )
821+
822+ set_on_span = span .set_attribute
823+ else :
824+ if db_name is not None :
825+ span .set_data (SPANDATA .DB_NAME , db_name )
826+
827+ set_on_span = span .set_data
759828
760829 server_address = connection_params .get ("host" )
761830 if server_address is not None :
762- span . set_data (SPANDATA .SERVER_ADDRESS , server_address )
831+ set_on_span (SPANDATA .SERVER_ADDRESS , server_address )
763832
764833 server_port = connection_params .get ("port" )
765834 if server_port is not None :
766- span . set_data (SPANDATA .SERVER_PORT , str (server_port ))
835+ set_on_span (SPANDATA .SERVER_PORT , str (server_port ))
767836
768837 server_socket_address = connection_params .get ("unix_socket" )
769838 if server_socket_address is not None :
770- span . set_data (SPANDATA .SERVER_SOCKET_ADDRESS , server_socket_address )
839+ set_on_span (SPANDATA .SERVER_SOCKET_ADDRESS , server_socket_address )
771840
772841
773842def add_template_context_repr_sequence () -> None :
0 commit comments