Skip to content

Commit 43d2b75

Browse files
committed
Better fallback
1 parent cc939a1 commit 43d2b75

File tree

1 file changed

+64
-30
lines changed

1 file changed

+64
-30
lines changed

sentry_sdk/integrations/django/__init__.py

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -762,25 +762,58 @@ def _set_db_data(span, cursor_or_db):
762762
span.set_data(SPANDATA.SERVER_PORT, str(cached_config["port"]))
763763
if cached_config["unix_socket"]:
764764
span.set_data(SPANDATA.SERVER_SOCKET_ADDRESS, cached_config["unix_socket"])
765-
return
765+
return # Success - exit early
766766

767-
# Fallback to using the database connection to get the data.
767+
# Fallback to dynamic database metadata collection.
768768
# This is the edge case where db configuration is not in Django's `DATABASES` setting.
769769
try:
770-
# Some custom backends override `__getattr__`, making it look like `cursor_or_db`
771-
# actually has a `connection` and the `connection` has a `get_dsn_parameters`
772-
# attribute, only to throw an error once you actually want to call it.
773-
# Hence the `inspect` check whether `get_dsn_parameters` is an actual callable
774-
# function.
775-
is_psycopg2 = (
776-
hasattr(cursor_or_db, "connection")
777-
and hasattr(cursor_or_db.connection, "get_dsn_parameters")
778-
and inspect.isroutine(cursor_or_db.connection.get_dsn_parameters)
770+
# Method 1: Try db.get_connection_params() first (NO CONNECTION ACCESS)
771+
logger.debug(
772+
"Cached db connection config retrieval failed for %s. Trying db.get_connection_params().",
773+
db_alias,
779774
)
780-
if is_psycopg2:
781-
connection_params = cursor_or_db.connection.get_dsn_parameters()
782-
else:
783-
try:
775+
try:
776+
connection_params = db.get_connection_params()
777+
778+
db_name = connection_params.get("dbname") or connection_params.get(
779+
"database"
780+
)
781+
if db_name is not None:
782+
span.set_data(SPANDATA.DB_NAME, db_name)
783+
784+
host = connection_params.get("host")
785+
if host is not None:
786+
span.set_data(SPANDATA.SERVER_ADDRESS, host)
787+
788+
port = connection_params.get("port")
789+
if port is not None:
790+
span.set_data(SPANDATA.SERVER_PORT, str(port))
791+
792+
unix_socket = connection_params.get("unix_socket")
793+
if unix_socket is not None:
794+
span.set_data(SPANDATA.SERVER_SOCKET_ADDRESS, unix_socket)
795+
return # Success - exit early to avoid connection access
796+
797+
except (KeyError, ImproperlyConfigured, AttributeError):
798+
# Method 2: Last resort - direct connection access (CONNECTION POOL RISK)
799+
logger.debug(
800+
"db.get_connection_params() failed for %s, trying direct connection access",
801+
db_alias,
802+
)
803+
804+
# Some custom backends override `__getattr__`, making it look like `cursor_or_db`
805+
# actually has a `connection` and the `connection` has a `get_dsn_parameters`
806+
# attribute, only to throw an error once you actually want to call it.
807+
# Hence the `inspect` check whether `get_dsn_parameters` is an actual callable
808+
# function.
809+
is_psycopg2 = (
810+
hasattr(cursor_or_db, "connection")
811+
and hasattr(cursor_or_db.connection, "get_dsn_parameters")
812+
and inspect.isroutine(cursor_or_db.connection.get_dsn_parameters)
813+
)
814+
if is_psycopg2:
815+
connection_params = cursor_or_db.connection.get_dsn_parameters()
816+
else:
784817
# psycopg3, only extract needed params as get_parameters
785818
# can be slow because of the additional logic to filter out default
786819
# values
@@ -793,27 +826,28 @@ def _set_db_data(span, cursor_or_db):
793826
host = cursor_or_db.connection.info.host
794827
if host and not host.startswith("/"):
795828
connection_params["host"] = host
796-
except Exception:
797-
connection_params = db.get_connection_params()
798829

799-
db_name = connection_params.get("dbname") or connection_params.get("database")
800-
if db_name is not None:
801-
span.set_data(SPANDATA.DB_NAME, db_name)
830+
db_name = connection_params.get("dbname") or connection_params.get(
831+
"database"
832+
)
833+
if db_name is not None:
834+
span.set_data(SPANDATA.DB_NAME, db_name)
802835

803-
host = connection_params.get("host")
804-
if host is not None:
805-
span.set_data(SPANDATA.SERVER_ADDRESS, host)
836+
host = connection_params.get("host")
837+
if host is not None:
838+
span.set_data(SPANDATA.SERVER_ADDRESS, host)
806839

807-
port = connection_params.get("port")
808-
if port is not None:
809-
span.set_data(SPANDATA.SERVER_PORT, str(port))
840+
port = connection_params.get("port")
841+
if port is not None:
842+
span.set_data(SPANDATA.SERVER_PORT, str(port))
810843

811-
unix_socket = connection_params.get("unix_socket")
812-
if unix_socket is not None:
813-
span.set_data(SPANDATA.SERVER_SOCKET_ADDRESS, unix_socket)
844+
unix_socket = connection_params.get("unix_socket")
845+
if unix_socket is not None:
846+
span.set_data(SPANDATA.SERVER_SOCKET_ADDRESS, unix_socket)
814847

815-
except (KeyError, ImproperlyConfigured, AttributeError) as e:
848+
except Exception as e:
816849
logger.debug("Failed to get database connection params for %s: %s", db_alias, e)
850+
# Skip database metadata rather than risk further connection issues
817851

818852

819853
def add_template_context_repr_sequence():

0 commit comments

Comments
 (0)