3737from sentry_sdk .hub import _should_send_default_pii
3838from sentry_sdk .scope import add_global_event_processor
3939from sentry_sdk .serializer import add_global_repr_processor
40+ from sentry_sdk .tracing import record_sql_query
4041from sentry_sdk .utils import (
4142 capture_internal_exceptions ,
4243 event_from_exception ,
@@ -331,61 +332,49 @@ def format_sql(sql, params):
331332 return sql , rv
332333
333334
334- @contextlib .contextmanager
335- def record_sql (sql , params , cursor = None ):
335+ def record_sql (sql , param_list , cursor = None ):
336336 # type: (Any, Any, Any) -> Generator
337337 hub = Hub .current
338338 if hub .get_integration (DjangoIntegration ) is None :
339339 yield
340340 return
341341
342- real_sql = None
343- real_params = None
342+ formatted_queries = []
344343
345- try :
346- # Prefer our own SQL formatting logic because it's the only one that
347- # has proper value trimming.
348- real_sql , real_params = format_sql (sql , params )
349- if real_sql :
350- real_sql = format_and_strip (real_sql , real_params )
351- except Exception :
352- pass
344+ for params in param_list :
345+ real_sql = None
346+ real_params = None
353347
354- if not real_sql and cursor and hasattr (cursor , "mogrify" ):
355- # If formatting failed and we're using psycopg2, it could be that we're
356- # looking at a query that uses Composed objects. Use psycopg2's mogrify
357- # function to format the query. We lose per-parameter trimming but gain
358- # accuracy in formatting.
359- #
360- # This is intentionally the second choice because we assume Composed
361- # queries are not widely used, while per-parameter trimming is
362- # generally highly desirable.
363348 try :
364- if cursor and hasattr (cursor , "mogrify" ):
365- real_sql = cursor .mogrify (sql , params )
366- if isinstance (real_sql , bytes ):
367- real_sql = real_sql .decode (cursor .connection .encoding )
349+ # Prefer our own SQL formatting logic because it's the only one that
350+ # has proper value trimming.
351+ real_sql , real_params = format_sql (sql , params )
352+ if real_sql :
353+ real_sql = format_and_strip (real_sql , real_params )
368354 except Exception :
369355 pass
370356
371- if real_sql :
372- hub .add_breadcrumb (message = real_sql , category = "query" )
373- with hub .span (op = "db.statement" , description = real_sql ):
374- yield
375- else :
376- yield
357+ if not real_sql and cursor and hasattr (cursor , "mogrify" ):
358+ # If formatting failed and we're using psycopg2, it could be that we're
359+ # looking at a query that uses Composed objects. Use psycopg2's mogrify
360+ # function to format the query. We lose per-parameter trimming but gain
361+ # accuracy in formatting.
362+ #
363+ # This is intentionally the second choice because we assume Composed
364+ # queries are not widely used, while per-parameter trimming is
365+ # generally highly desirable.
366+ try :
367+ if cursor and hasattr (cursor , "mogrify" ):
368+ real_sql = cursor .mogrify (sql , params )
369+ if isinstance (real_sql , bytes ):
370+ real_sql = real_sql .decode (cursor .connection .encoding )
371+ except Exception :
372+ pass
377373
374+ if real_sql :
375+ formatted_queries .append (real_sql )
378376
379- @contextlib .contextmanager
380- def record_many_sql (sql , param_list , cursor ):
381- ctxs = [record_sql (sql , params , cursor ).__enter__ () for params in param_list ]
382-
383- try :
384- yield
385- finally :
386- einfo = sys .exc_info ()
387- for ctx in ctxs :
388- ctx .__exit__ (* einfo )
377+ return record_sql_queries (hub , formatted_queries )
389378
390379
391380def install_sql_hook ():
@@ -404,7 +393,7 @@ def install_sql_hook():
404393 return
405394
406395 def execute (self , sql , params = None ):
407- with record_sql (sql , params , self .cursor ):
396+ with record_sql (sql , [ params ] , self .cursor ):
408397 return real_execute (self , sql , params )
409398
410399 def executemany (self , sql , param_list ):
0 commit comments