Skip to content

Commit 7fddf92

Browse files
Fix erikdarlingdata#1048: stop alert engine fabricating 100% host CPU on Linux
The erikdarlingdata#1049 fix corrected every path that reads CPU from the collected table (collector, views, chart reads), but the alert engine doesn't read that table — DatabaseService.NocHealth.GetCpuPercentAsync runs its own live query against sys.dm_os_ring_buffers and was never touched. It computes other_cpu_percent = 100 - SystemIdle - ProcessUtilization, and since SystemIdle is always 0 on SQL Server on Linux, that returns 100 - sqlcpu. AlertHealthResult.TotalCpuPercent then sums to a permanent 100%, so AlertStateService's TotalCpuPercent >= CpuThresholdPercent check fires the host-CPU alert forever — exactly what the reporter still saw after installing the nightly. Fix: apply the same Linux guard used by install/18, RemoteCollectorService.Cpu, and FinOps.Inventory — detect host_platform via sp_executesql behind an OBJECT_ID(N'sys.dm_os_host_info', N'V') check (so SQL 2016 never binds the 2017+ DMV) and return NULL for other_cpu_percent on Linux. The existing TotalCpuPercent getter already falls back to the SQL-only figure when OtherCpuPercent is null, so the alert clears. Windows behavior is unchanged. Dashboard-only change — no schema or installer impact. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 176b931 commit 7fddf92

1 file changed

Lines changed: 31 additions & 11 deletions

File tree

Dashboard/Services/DatabaseService.NocHealth.cs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,22 @@ end_time DESC
252252
OPTION(MAXDOP 1);"
253253
: @"SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
254254
255+
DECLARE @is_linux bit = 0;
256+
257+
/* SystemIdle is always 0 in the SCHEDULER_MONITOR ring buffer on SQL Server
258+
on Linux, so 100 - SystemIdle - ProcessUtilization fabricates a host figure
259+
that pins total CPU at 100% forever (Issue #1048). No DMV exposes true host
260+
CPU on Linux, so report other/host CPU as NULL there and let the alert engine
261+
fall back to the SQL-only figure. sys.dm_os_host_info is 2017+; referenced via
262+
sp_executesql so SQL 2016 (no Linux build) never binds it (@is_linux stays 0). */
263+
IF OBJECT_ID(N'sys.dm_os_host_info', N'V') IS NOT NULL
264+
BEGIN
265+
EXEC sys.sp_executesql
266+
N'SELECT @linux = CASE WHEN hi.host_platform = N''Linux'' THEN 1 ELSE 0 END FROM sys.dm_os_host_info AS hi;',
267+
N'@linux bit OUTPUT',
268+
@linux = @is_linux OUTPUT;
269+
END;
270+
255271
SELECT TOP (1)
256272
sql_cpu_percent =
257273
x.rb.value
@@ -260,17 +276,21 @@ SELECT TOP (1)
260276
'integer'
261277
),
262278
other_cpu_percent =
263-
100
264-
- x.rb.value
265-
(
266-
'(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]',
267-
'integer'
268-
)
269-
- x.rb.value
270-
(
271-
'(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]',
272-
'integer'
273-
)
279+
CASE
280+
WHEN @is_linux = 1
281+
THEN NULL
282+
ELSE 100
283+
- x.rb.value
284+
(
285+
'(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]',
286+
'integer'
287+
)
288+
- x.rb.value
289+
(
290+
'(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]',
291+
'integer'
292+
)
293+
END
274294
FROM
275295
(
276296
SELECT

0 commit comments

Comments
 (0)