@@ -190,6 +190,7 @@ def rpc_completed_expected_values():
190
190
'client_hostname' : 'EC2AMAZ-ML3E0PH' ,
191
191
'client_app_name' : 'SQLAgent - Job Manager' ,
192
192
'username' : 'NT AUTHORITY\\ NETWORK SERVICE' ,
193
+ 'object_name' : 'sp_executesql' ,
193
194
}
194
195
195
196
@@ -208,6 +209,8 @@ def error_expected_values():
208
209
'client_app_name' : 'go-mssqldb' ,
209
210
'username' : 'shopper_4' ,
210
211
'message' : "'REPEAT' is not a recognized built-in function name." ,
212
+ 'activity_id' : 'F961B15C-752A-487E-AC4F-F2A9BAB11DB7-1' ,
213
+ 'activity_id_xfer' : 'AFCCDE6F-EACD-47F3-9B62-CC02D517191B-0' ,
211
214
}
212
215
213
216
@@ -253,6 +256,8 @@ def attention_expected_values():
253
256
'client_hostname' : 'COMP-MX2YQD7P2P' ,
254
257
'client_app_name' : 'azdata' ,
255
258
'username' : 'datadog' ,
259
+ 'activity_id' : 'F961B15C-752A-487E-AC4F-F2A9BAB11DB7-1' ,
260
+ 'activity_id_xfer' : 'AFCCDE6F-EACD-47F3-9B62-CC02D517191B-0' ,
256
261
}
257
262
258
263
@@ -621,6 +626,8 @@ def test_process_events_rpc_completed(
621
626
assert 'sp_executesql' in event ['statement' ]
622
627
assert 'sql_text' in event
623
628
assert 'EXECUTE [msdb].[dbo].[sp_agent_log_job_history]' in event ['sql_text' ]
629
+ assert 'object_name' in event
630
+ assert event ['object_name' ] == 'sp_executesql'
624
631
625
632
def test_process_events_error_reported (self , error_events_handler , sample_error_event_xml , error_expected_values ):
626
633
"""Test processing of error reported events"""
@@ -824,6 +831,34 @@ def test_normalize_error_event(self, error_events_handler):
824
831
assert 'duration_ms' not in normalized
825
832
assert 'query_start' not in normalized
826
833
834
+ def test_normalize_attention_event (self , error_events_handler ):
835
+ """Test attention event normalization"""
836
+ # Test attention event with fields
837
+ event = {
838
+ 'event_name' : 'attention' ,
839
+ 'timestamp' : '2023-01-01T12:00:00.123Z' ,
840
+ 'duration_ms' : 328.677 ,
841
+ 'session_id' : 123 ,
842
+ 'request_id' : 456 ,
843
+ 'database_name' : 'TestDB' ,
844
+ 'sql_text' : 'SELECT * FROM Customers WHERE CustomerId = 123' ,
845
+ }
846
+
847
+ normalized = error_events_handler ._normalize_event_impl (event )
848
+
849
+ # Verify normalized fields
850
+ assert normalized ['xe_type' ] == 'attention'
851
+ assert normalized ['event_fire_timestamp' ] == '2023-01-01T12:00:00.123Z'
852
+ assert normalized ['session_id' ] == 123
853
+ assert normalized ['request_id' ] == 456
854
+ assert normalized ['database_name' ] == 'TestDB'
855
+ assert normalized ['sql_text' ] == 'SELECT * FROM Customers WHERE CustomerId = 123'
856
+
857
+ # Verify duration_ms and query_start are preserved for attention events
858
+ assert 'duration_ms' in normalized
859
+ assert normalized ['duration_ms' ] == 328.677
860
+ assert 'query_start' in normalized # Query start should be calculated from timestamp and duration
861
+
827
862
@patch ('datadog_checks.sqlserver.xe_collection.base.datadog_agent' )
828
863
def test_create_event_payload (self , mock_agent , query_completion_handler ):
829
864
"""Test creation of event payload"""
@@ -926,6 +961,62 @@ def test_create_rqt_event(self, mock_agent, query_completion_handler):
926
961
assert rqt_event ['sqlserver' ]['query_start' ] == '2023-01-01T11:59:50.123Z'
927
962
assert rqt_event ['sqlserver' ]['primary_sql_field' ] == 'batch_text'
928
963
964
+ @patch ('datadog_checks.sqlserver.xe_collection.base.datadog_agent' )
965
+ def test_create_rqt_event_attention (self , mock_agent , error_events_handler ):
966
+ """Test creation of Raw Query Text event for attention event"""
967
+ mock_agent .get_version .return_value = '7.30.0'
968
+
969
+ # Create attention event with SQL fields - from the error_events_handler
970
+ event = {
971
+ 'event_name' : 'attention' ,
972
+ 'timestamp' : '2023-01-01T12:00:00.123Z' ,
973
+ 'duration_ms' : 328.677 ,
974
+ 'session_id' : 123 ,
975
+ 'database_name' : 'TestDB' ,
976
+ 'sql_text' : 'SELECT * FROM Customers WHERE CustomerId = ?' ,
977
+ 'query_signature' : 'abc123' ,
978
+ 'primary_sql_field' : 'sql_text' ,
979
+ 'dd_tables' : ['Customers' ],
980
+ 'dd_commands' : ['SELECT' ],
981
+ }
982
+
983
+ # Create raw SQL fields
984
+ raw_sql_fields = {
985
+ 'sql_text' : 'SELECT * FROM Customers WHERE CustomerId = 123' ,
986
+ 'raw_query_signature' : 'def456' ,
987
+ }
988
+
989
+ # Query details with formatted timestamps
990
+ query_details = {
991
+ 'event_fire_timestamp' : '2023-01-01T12:00:00.123Z' ,
992
+ 'query_start' : '2023-01-01T11:59:59.795Z' , # 328.677ms before timestamp
993
+ 'duration_ms' : 328.677 ,
994
+ }
995
+
996
+ # Create RQT event
997
+ rqt_event = error_events_handler ._create_rqt_event (event , raw_sql_fields , query_details )
998
+
999
+ # Validate common payload fields
1000
+ validate_common_payload_fields (rqt_event , expected_source = 'datadog_query_errors' , expected_type = 'rqt' )
1001
+
1002
+ # Verify DB fields
1003
+ assert rqt_event ['db' ]['instance' ] == 'TestDB'
1004
+ assert rqt_event ['db' ]['query_signature' ] == 'abc123'
1005
+ assert rqt_event ['db' ]['raw_query_signature' ] == 'def456'
1006
+ assert rqt_event ['db' ]['statement' ] == 'SELECT * FROM Customers WHERE CustomerId = 123'
1007
+
1008
+ # Verify sqlserver fields
1009
+ assert rqt_event ['sqlserver' ]['session_id' ] == 123
1010
+ assert rqt_event ['sqlserver' ]['xe_type' ] == 'attention'
1011
+ assert rqt_event ['sqlserver' ]['event_fire_timestamp' ] == '2023-01-01T12:00:00.123Z'
1012
+
1013
+ # Key check: verify that duration_ms and query_start are present for attention events
1014
+ # even though they come from the error_events_handler
1015
+ assert 'duration_ms' in rqt_event ['sqlserver' ]
1016
+ assert rqt_event ['sqlserver' ]['duration_ms' ] == 328.677
1017
+ assert 'query_start' in rqt_event ['sqlserver' ]
1018
+ assert rqt_event ['sqlserver' ]['query_start' ] == '2023-01-01T11:59:59.795Z'
1019
+
929
1020
def test_create_rqt_event_disabled (self , mock_check , mock_config ):
930
1021
"""Test RQT event creation when disabled"""
931
1022
# Disable raw query collection
@@ -972,6 +1063,63 @@ def test_create_rqt_event_missing_signature(self, query_completion_handler):
972
1063
# Should return None when missing signature
973
1064
assert query_completion_handler ._create_rqt_event (event , raw_sql_fields , query_details ) is None
974
1065
1066
+ @patch ('datadog_checks.sqlserver.xe_collection.base.datadog_agent' )
1067
+ def test_create_rqt_event_error_reported (self , mock_agent , error_events_handler ):
1068
+ """Test creation of Raw Query Text event for error_reported event"""
1069
+ mock_agent .get_version .return_value = '7.30.0'
1070
+
1071
+ # Create error_reported event with SQL fields
1072
+ event = {
1073
+ 'event_name' : 'error_reported' ,
1074
+ 'timestamp' : '2023-01-01T12:00:00.123Z' ,
1075
+ 'error_number' : 8134 ,
1076
+ 'severity' : 15 ,
1077
+ 'session_id' : 123 ,
1078
+ 'database_name' : 'TestDB' ,
1079
+ 'sql_text' : 'SELECT 1/0' ,
1080
+ 'message' : 'Division by zero error' ,
1081
+ 'query_signature' : 'abc123' ,
1082
+ 'primary_sql_field' : 'sql_text' ,
1083
+ }
1084
+
1085
+ # Create raw SQL fields
1086
+ raw_sql_fields = {
1087
+ 'sql_text' : 'SELECT 1/0' ,
1088
+ 'raw_query_signature' : 'def456' ,
1089
+ }
1090
+
1091
+ # Query details would not have duration_ms or query_start for error_reported events
1092
+ query_details = {
1093
+ 'event_fire_timestamp' : '2023-01-01T12:00:00.123Z' ,
1094
+ }
1095
+
1096
+ # Create RQT event
1097
+ rqt_event = error_events_handler ._create_rqt_event (event , raw_sql_fields , query_details )
1098
+
1099
+ # Validate common payload fields
1100
+ validate_common_payload_fields (rqt_event , expected_source = 'datadog_query_errors' , expected_type = 'rqt' )
1101
+
1102
+ # Verify DB fields
1103
+ assert rqt_event ['db' ]['instance' ] == 'TestDB'
1104
+ assert rqt_event ['db' ]['query_signature' ] == 'abc123'
1105
+ assert rqt_event ['db' ]['raw_query_signature' ] == 'def456'
1106
+ assert rqt_event ['db' ]['statement' ] == 'SELECT 1/0'
1107
+
1108
+ # Verify sqlserver fields
1109
+ assert rqt_event ['sqlserver' ]['session_id' ] == 123
1110
+ assert rqt_event ['sqlserver' ]['xe_type' ] == 'error_reported'
1111
+ assert rqt_event ['sqlserver' ]['event_fire_timestamp' ] == '2023-01-01T12:00:00.123Z'
1112
+
1113
+ # Key check: verify that error_number and message are included for error_reported events
1114
+ assert 'error_number' in rqt_event ['sqlserver' ]
1115
+ assert rqt_event ['sqlserver' ]['error_number' ] == 8134
1116
+ assert 'message' in rqt_event ['sqlserver' ]
1117
+ assert rqt_event ['sqlserver' ]['message' ] == 'Division by zero error'
1118
+
1119
+ # Verify that duration_ms and query_start are NOT present for error_reported events
1120
+ assert 'duration_ms' not in rqt_event ['sqlserver' ]
1121
+ assert 'query_start' not in rqt_event ['sqlserver' ]
1122
+
975
1123
976
1124
@pytest .mark .integration
977
1125
@pytest .mark .usefixtures ('dd_environment' )
0 commit comments