diff --git a/Lite/Services/RemoteCollectorService.Cpu.cs b/Lite/Services/RemoteCollectorService.Cpu.cs index a46c068..fbf3afd 100644 --- a/Lite/Services/RemoteCollectorService.Cpu.cs +++ b/Lite/Services/RemoteCollectorService.Cpu.cs @@ -58,14 +58,12 @@ drs.end_time DESC SELECT TOP (60) sample_time = DATEADD(SECOND, -((@ms_ticks - t.timestamp) / 1000), SYSDATETIME()), - sqlserver_cpu_utilization = t.record.value('(Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'integer'), + sqlserver_cpu_utilization = x.process_utilization, other_process_cpu_utilization = CASE - WHEN (100 - t.record.value('(Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'integer') - - t.record.value('(Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'integer')) < 0 + WHEN (100 - x.system_idle - x.process_utilization) < 0 THEN 0 - ELSE 100 - t.record.value('(Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'integer') - - t.record.value('(Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'integer') + ELSE 100 - x.system_idle - x.process_utilization END FROM ( @@ -75,6 +73,16 @@ record = CONVERT(xml, dorb.record) FROM sys.dm_os_ring_buffers AS dorb WHERE dorb.ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR' ) AS t +CROSS APPLY +( + SELECT + process_utilization = t.record.value('(Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'integer'), + system_idle = t.record.value('(Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'integer') +) AS x +/* Skip ring-buffer records lacking a complete SystemHealth block — their + XML values extract as NULL and would store NULL samples (Issue #989). */ +WHERE x.process_utilization IS NOT NULL +AND x.system_idle IS NOT NULL ORDER BY t.timestamp DESC OPTION(RECOMPILE);"; diff --git a/install/18_collect_cpu_utilization_stats.sql b/install/18_collect_cpu_utilization_stats.sql index 9485750..5563d4a 100644 --- a/install/18_collect_cpu_utilization_stats.sql +++ b/install/18_collect_cpu_utilization_stats.sql @@ -131,16 +131,12 @@ BEGIN @start_time ), sqlserver_cpu_utilization = - t.record.value('(Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'integer'), + x.process_utilization, other_process_cpu_utilization = CASE - WHEN (100 - - t.record.value('(Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'integer') - - t.record.value('(Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'integer')) < 0 + WHEN (100 - x.system_idle - x.process_utilization) < 0 THEN 0 - ELSE 100 - - t.record.value('(Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'integer') - - t.record.value('(Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'integer') + ELSE 100 - x.system_idle - x.process_utilization END FROM ( @@ -151,12 +147,27 @@ BEGIN FROM sys.dm_os_ring_buffers AS dorb WHERE dorb.ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR' ) AS t + CROSS APPLY + ( + SELECT + process_utilization = + t.record.value('(Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'integer'), + system_idle = + t.record.value('(Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'integer') + ) AS x WHERE DATEADD ( SECOND, -((@current_ms_ticks - t.timestamp) / 1000), @start_time ) > ISNULL(@max_sample_time, DATEADD(DAY, -7, @start_time)) + /* + Skip ring-buffer records that lack a complete SystemHealth block — + their XML values extract as NULL and would fail the NOT NULL INSERT, + breaking collection until the bad records age out (Issue #989). + */ + AND x.process_utilization IS NOT NULL + AND x.system_idle IS NOT NULL ORDER BY t.timestamp DESC OPTION(RECOMPILE);