Skip to content
8 changes: 1 addition & 7 deletions sentry_sdk/integrations/django/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@
)
from sentry_sdk.integrations.wsgi import _ScopedResponse
from sentry_sdk.traces import StreamedSpan
from sentry_sdk.tracing import Span


TRANSACTION_STYLE_VALUES = ("function_name", "url")
Expand Down Expand Up @@ -845,15 +844,10 @@ def _rollback(self: "BaseDatabaseWrapper") -> None:


def _set_db_data(
span: "Union[Span, StreamedSpan]",
span: "StreamedSpan",
cursor_or_db: "Any",
db_operation: "Optional[str]" = None,
) -> None:
# TODO: remove this once record_sql_queries drops support for old spans
from sentry_sdk.traces import StreamedSpan

if not isinstance(span, StreamedSpan):
return
db = cursor_or_db.db if hasattr(cursor_or_db, "db") else cursor_or_db
vendor = db.vendor
span.set_attribute(SPANDATA.DB_SYSTEM_NAME, vendor)
Expand Down
53 changes: 16 additions & 37 deletions sentry_sdk/integrations/sqlalchemy.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from sentry_sdk.consts import SPANDATA, SPANSTATUS
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.tracing import Span
from sentry_sdk.tracing_utils import (
add_query_source,
record_sql_queries,
Expand All @@ -22,7 +21,7 @@
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from typing import Any, ContextManager, Optional, Union
from typing import Any, ContextManager, Optional


class SqlalchemyIntegration(Integration):
Expand Down Expand Up @@ -79,34 +78,27 @@ def _after_cursor_execute(
)

# Record query source immediately before span is finished: accurate end timestamp and before the span is flushed.
span: "Optional[Union[Span, StreamedSpan]]" = getattr(
context, "_sentry_sql_span", None
)
if isinstance(span, StreamedSpan):
span: "Optional[StreamedSpan]" = getattr(context, "_sentry_sql_span", None)
if span is not None:
with capture_internal_exceptions():
add_query_source(span)

if ctx_mgr is not None:
context._sentry_sql_span_manager = None
ctx_mgr.__exit__(None, None, None)

if isinstance(span, Span):
with capture_internal_exceptions():
add_query_source(span)


def _handle_error(context: "Any", *args: "Any") -> None:
execution_context = context.execution_context
if execution_context is None:
return

span: "Optional[Span]" = getattr(execution_context, "_sentry_sql_span", None)
span: "Optional[StreamedSpan]" = getattr(
execution_context, "_sentry_sql_span", None
)

if span is not None:
if isinstance(span, StreamedSpan):
span.status = SpanStatus.ERROR
else:
span.set_status(SPANSTATUS.INTERNAL_ERROR)
span.status = SpanStatus.ERROR

# _after_cursor_execute does not get called for crashing SQL stmts. Judging
# from SQLAlchemy codebase it does seem like any error coming into this
Expand Down Expand Up @@ -142,43 +134,30 @@ def _get_db_system(name: str) -> "Optional[str]":
return None


def _set_db_data(span: "Union[Span, StreamedSpan]", conn: "Any") -> None:
def _set_db_data(span: "StreamedSpan", conn: "Any") -> None:
db_system = _get_db_system(conn.engine.name)

if isinstance(span, StreamedSpan):
if db_system is not None:
span.set_attribute(SPANDATA.DB_SYSTEM_NAME, db_system)
else:
if db_system is not None:
span.set_data(SPANDATA.DB_SYSTEM, db_system)

if isinstance(span, StreamedSpan):
set_on_span = span.set_attribute
else:
set_on_span = span.set_data
if db_system is not None:
span.set_attribute(SPANDATA.DB_SYSTEM_NAME, db_system)

try:
driver = conn.dialect.driver
if driver:
set_on_span(SPANDATA.DB_DRIVER_NAME, driver)
span.set_attribute(SPANDATA.DB_DRIVER_NAME, driver)
except Exception:
pass

if conn.engine.url is None:
return

db_name = conn.engine.url.database
if isinstance(span, StreamedSpan):
if db_name is not None:
span.set_attribute(SPANDATA.DB_NAMESPACE, db_name)
else:
if db_name is not None:
span.set_data(SPANDATA.DB_NAME, db_name)
if db_name is not None:
span.set_attribute(SPANDATA.DB_NAMESPACE, db_name)

server_address = conn.engine.url.host
if server_address is not None:
set_on_span(SPANDATA.SERVER_ADDRESS, server_address)
span.set_attribute(SPANDATA.SERVER_ADDRESS, server_address)

server_port = conn.engine.url.port
if server_port is not None:
set_on_span(SPANDATA.SERVER_PORT, server_port)
span.set_attribute(SPANDATA.SERVER_PORT, server_port)
58 changes: 16 additions & 42 deletions sentry_sdk/tracing_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,8 @@ def record_sql_queries(
record_cursor_repr: bool = False,
span_origin: str = "manual",
span_op_override_value: "Optional[str]" = None,
) -> "Generator[Union[sentry_sdk.tracing.Span, sentry_sdk.traces.StreamedSpan], None, None]":
) -> "Generator[sentry_sdk.traces.StreamedSpan, None, None]":
# TODO: Bring back capturing of params by default
# TODO: Once we drop span streaming from this, remove the hack from django's
# _set_db_data
client = sentry_sdk.get_client()
if has_data_collection_enabled(client.options):
if client.options["data_collection"]["database_query_data"]:
Expand Down Expand Up @@ -176,31 +174,19 @@ def record_sql_queries(
with capture_internal_exceptions():
sentry_sdk.add_breadcrumb(message=query, category="query", data=data)

if has_span_streaming_enabled(client.options):
additional_attributes = {}
if query is not None:
additional_attributes["db.query.text"] = query

with sentry_sdk.traces.start_span(
name="<unknown SQL query>" if query is None else query,
attributes={
"sentry.origin": span_origin,
"sentry.op": span_op_override_value
if span_op_override_value
else OP.DB,
**additional_attributes,
},
) as span:
yield span
else:
with sentry_sdk.start_span(
op=span_op_override_value if span_op_override_value is not None else OP.DB,
name=query,
origin=span_origin,
) as span:
for k, v in data.items():
span.set_data(k, v)
yield span
additional_attributes = {}
if query is not None:
additional_attributes["db.query.text"] = query

with sentry_sdk.traces.start_span(
name="<unknown SQL query>" if query is None else query,
attributes={
"sentry.origin": span_origin,
"sentry.op": span_op_override_value if span_op_override_value else OP.DB,
**additional_attributes,
},
) as span:
yield span


def add_http_breadcrumb(status_code: "Optional[int]", data: "dict[str, Any]") -> None:
Expand Down Expand Up @@ -332,7 +318,7 @@ def add_source(


def add_query_source(
span: "Union[sentry_sdk.tracing.Span, sentry_sdk.traces.StreamedSpan]",
span: "sentry_sdk.traces.StreamedSpan",
) -> None:
"""
Adds OTel compatible source code information to a database query span
Expand All @@ -341,26 +327,14 @@ def add_query_source(
if not client.is_active():
return

if isinstance(span, Span):
# In the StreamedSpan case, we need to add the extra span information before
# the span finishes, so it's expected that this will be None. In the Span case,
# it should already be finished.
if span.timestamp is None:
return

if span.start_timestamp is None:
return

should_add_query_source = client.options.get("enable_db_query_source", True)
if not should_add_query_source:
return

if isinstance(span, StreamedSpan):
end_timestamp = span.end_timestamp
else:
end_timestamp = span.timestamp

end_timestamp = end_timestamp or datetime.now(timezone.utc)
end_timestamp = span.end_timestamp or datetime.now(timezone.utc)

duration = end_timestamp - span.start_timestamp
threshold = client.options.get("db_query_source_threshold_ms", 0)
Expand Down
6 changes: 4 additions & 2 deletions tests/integrations/django/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.tracing import Span
from sentry_sdk.traces import StreamedSpan
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
Expand Down Expand Up @@ -871,7 +871,9 @@ def get_connection_params(self):
return {}

try:
_set_db_data(Span(), DummyBackend())
_set_db_data(
StreamedSpan(name="name", scope=sentry_sdk.Scope()), DummyBackend()
)
except TypeError:
pytest.fail("A TypeError was raised")

Expand Down
Loading
Loading