fix: revert ineffective Uptime-Kuma paused fix; harden Unraid CPU divisor

The Uptime-Kuma status-page API (toPublicJSON) does not emit a status
field on monitor objects, so the added status schema field and paused
early-return were dead code and did not resolve #6002. Paused monitors
stop producing heartbeats and the two consumed endpoints expose no
paused signal, so revert the change.

Unraid CPU: divide by cpus.length (the array actually being averaged)
instead of info.cpu.threads, which is more robust if the two ever
disagree, while keeping the SMT over-reporting fix.
This commit is contained in:
Thomas Camlong committed 2026-08-03 17:41:24 +02:00
1 parent 751dd751e0
commit b2a4dcad1c
3 files changed
+5 -21

No files matched your search

@@ -37,11 +37,11 @@ export class UnraidIntegration extends Integration implements ISystemHealthMonit
const systemInfo = await this.getSystemInformationAsync();
const cpuUtilization = systemInfo.metrics.cpu.cpus.reduce((acc, val) => acc + val.percentTotal, 0);
const cpuCount = systemInfo.info.cpu.threads;
const cpuCount = systemInfo.metrics.cpu.cpus.length;
// We use the thread count (not physical cores) because each logical CPU entry in cpus[]
// represents a thread. Dividing by cores would over-report utilization on SMT systems.
// Guard against zero or negative thread counts to avoid Infinity/NaN.
// Each entry in cpus[] is one logical CPU (thread). Dividing the summed per-thread
// utilization by the thread count (not physical cores) gives the correct average and
// avoids over-reporting on SMT systems. Guard against zero to avoid Infinity/NaN.
const cpuUtilizationNormalized = cpuCount > 0 ? cpuUtilization / cpuCount : 0;
const totalMemory = systemInfo.info.memory.layout.reduce((acc, layout) => layout.size + acc, 0);
@@ -62,24 +62,9 @@ export class UptimeKumaIntegration extends Integration {
}
private mapMonitor(
monitor: { id: number; name: string; status?: number },
monitor: { id: number; name: string },
heartbeat: { heartbeatList: Record<string, { status: number }[]>; uptimeList: Record<string, number> },
): UptimeKumaMonitor {
// If the status page reports a monitor status directly, prefer it over heartbeat inference.
// Uptime-Kuma status page returns status=2 for paused monitors, and once paused,
// heartbeats stop arriving so the latest heartbeat may still show "up" from before pausing.
if (monitor.status !== undefined) {
const statusFromPage = uptimeKumaHeartbeatCategoryMap[monitor.status];
if (statusFromPage === "paused") {
return {
id: monitor.id,
name: monitor.name,
status: "paused",
uptimePercent24h: null,
};
}
}
const heartbeats = heartbeat.heartbeatList[String(monitor.id)] ?? [];
const latestHeartbeat = heartbeats.at(-1);
const uptimeKey = `${monitor.id}_24`;
@@ -19,7 +19,6 @@ export const uptimeKumaHeartbeatCategoryMap: Record<number, UptimeKumaMonitorCat
export const uptimeKumaStatusPageMonitorSchema = z.object({
id: z.number().int(),
name: z.string(),
status: z.number().int().optional(),
});
export const uptimeKumaStatusPageGroupSchema = z.object({