Skip to content

Commit

Permalink
Take the signature of the top statement on the stack for deadlock pay…
Browse files Browse the repository at this point in the history
…load (#19142)

* relnote

* relnote

* rename the changelog file

* linter
  • Loading branch information
nenadnoveljic authored Nov 27, 2024
1 parent 403cbac commit f59d4a7
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 16 deletions.
1 change: 1 addition & 0 deletions sqlserver/changelog.d/19142.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix poor query signature correlation for deadlocks.
43 changes: 27 additions & 16 deletions sqlserver/datadog_checks/sqlserver/deadlocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
PAYLOAD_XML = "xml"

NO_XE_SESSION_ERROR = f"No XE session `{XE_SESSION_DATADOG}` found"
OBFUSCATION_ERROR = "ERROR: failed to obfuscate"


def agent_check_getter(self):
Expand Down Expand Up @@ -74,7 +75,7 @@ def obfuscate_no_except_wrapper(self, sql_text):
sql_text, self._config.obfuscator_options, replace_null_character=True
)['query']
except Exception as e:
sql_text = "ERROR: failed to obfuscate"
sql_text = OBFUSCATION_ERROR
error_text = "Failed to obfuscate sql text within a deadlock"
if self._config.log_unobfuscated_queries:
error_text += "=[%s]" % sql_text
Expand All @@ -88,24 +89,34 @@ def _obfuscate_xml(self, root):
raise Exception("process-list element not found. The deadlock XML is in an unexpected format.")
query_signatures = []
for process in process_list.findall('process'):
spid = process.get('spid')
if spid is not None:
try:
spid = int(spid)
except ValueError:
self._log.error("spid not an integer. Skipping query signature computation.")
continue
if spid in query_signatures:
continue
else:
self._log.error("spid not found in process element. Skipping query signature computation.")

# Setting `signature` for the first function on the stack
signature = None
for frame in process.findall('.//frame'):
if frame.text is not None and frame.text != "unknown":
frame.text = self.obfuscate_no_except_wrapper(frame.text)
if signature is not None and frame.text != OBFUSCATION_ERROR:
signature = compute_sql_signature(frame.text)

for inputbuf in process.findall('.//inputbuf'):
if inputbuf.text is not None:
inputbuf.text = self.obfuscate_no_except_wrapper(inputbuf.text)
spid = process.get('spid')
if spid is not None:
try:
spid = int(spid)
except ValueError:
self._log.error("spid not an integer. Skipping query signature computation.")
continue
if spid in query_signatures:
continue
query_signatures.append({"spid": spid, "signature": compute_sql_signature(inputbuf.text)})
else:
self._log.error("spid not found in process element. Skipping query signature computation.")
for frame in process.findall('.//frame'):
if frame.text is not None:
frame.text = self.obfuscate_no_except_wrapper(frame.text)
if signature is None and inputbuf.text != OBFUSCATION_ERROR:
signature = compute_sql_signature(inputbuf.text)

query_signatures.append({"spid": spid, "signature": signature})

return query_signatures

def _get_lookback_seconds(self):
Expand Down

0 comments on commit f59d4a7

Please sign in to comment.