Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sqlserver/changelog.d/20584.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Only submit plan events when we have a plan definition
15 changes: 12 additions & 3 deletions sqlserver/datadog_checks/sqlserver/statements.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,8 @@ def _collect_plans(self, rows, cursor, deadline):
plan_key = row['plan_handle']
if self._seen_plans_ratelimiter.acquire(plan_key):
raw_plan, is_plan_encrypted = self._load_plan(row['plan_handle'], cursor)
obfuscated_plan, collection_errors = None, None
obfuscated_plan = None
collection_errors = []

try:
if raw_plan:
Expand All @@ -639,14 +640,22 @@ def _collect_plans(self, rows, cursor, deadline):
self.log.warning("Failed to obfuscate plan=[%s] | %s", raw_plan, context)
else:
self.log.debug("Failed to obfuscate plan | %s", context)
collection_errors = [{'code': "obfuscate_xml_plan_error", 'message': str(e)}]
collection_errors.append({'code': "obfuscate_xml_plan_error", 'message': str(e)})
self._check.count(
"dd.sqlserver.statements.error",
1,
**self._check.debug_stats_kwargs(tags=["error:obfuscate-xml-plan-{}".format(type(e))]),
)
tags = self._check.tag_manager.get_tags()

if is_plan_encrypted:
collection_errors.append({'code': "plan_encrypted", 'message': "cannot collect encrypted plan"})

# Do not submit plan events if no plan is available and there is no collection error.
# This avoids sending empty plan events when a plan is not available in the cache.
if not raw_plan and not collection_errors:
continue

# for stored procedures, we want to send the plan
# events with the full procedure text, not the text
# for the individual statement encapsulated within the proc
Expand Down Expand Up @@ -677,7 +686,7 @@ def _collect_plans(self, rows, cursor, deadline):
"plan": {
"definition": obfuscated_plan,
"signature": row['query_plan_hash'],
"collection_errors": collection_errors,
"collection_errors": collection_errors if collection_errors else None,
},
"query_signature": query_signature,
"procedure_signature": row.get('procedure_signature', None),
Expand Down
8 changes: 1 addition & 7 deletions sqlserver/tests/test_statements.py
Original file line number Diff line number Diff line change
Expand Up @@ -1001,13 +1001,7 @@ def test_statement_conditional_stored_procedure_with_temp_table(
assert dbm_samples, "should have collected at least one sample"

matched_events = [s for s in dbm_samples if s['dbm_type'] == "plan" and "#Ids" in s['db']['statement']]
assert matched_events, "should have collected plan event"

for event in matched_events:
assert event['db']['plan']['definition'] is None
assert event['sqlserver']['plan_handle'] is not None
assert event['sqlserver']['query_hash'] is not None
assert event['sqlserver']['query_plan_hash'] is not None
assert not matched_events, "should not have collected plan event because there is no plan definition"


@pytest.mark.integration
Expand Down