From 81544c8a3975224420be1dd0204ad3bb935f2a93 Mon Sep 17 00:00:00 2001 From: MayMeow <3164256+MayMeow@users.noreply.github.com> Date: Sun, 9 Nov 2025 17:57:20 +0100 Subject: [PATCH] Fix Group monitors to send notification after reaching maximum retires count (#6286) Co-authored-by: Frank Elsinga --- server/monitor-types/group.js | 82 ++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/server/monitor-types/group.js b/server/monitor-types/group.js index 28d0443d4..8372b4f17 100644 --- a/server/monitor-types/group.js +++ b/server/monitor-types/group.js @@ -11,35 +11,67 @@ class GroupMonitorType extends MonitorType { async check(monitor, heartbeat, _server) { const children = await Monitor.getChildren(monitor.id); - if (children.length > 0) { - heartbeat.status = UP; - heartbeat.msg = "All children up and running"; - for (const child of children) { - if (!child.active) { - // Ignore inactive childs - continue; - } - const lastBeat = await Monitor.getPreviousHeartbeat(child.id); - - // Only change state if the monitor is in worse conditions then the ones before - // lastBeat.status could be null - if (!lastBeat) { - heartbeat.status = PENDING; - } else if (heartbeat.status === UP && (lastBeat.status === PENDING || lastBeat.status === DOWN)) { - heartbeat.status = lastBeat.status; - } else if (heartbeat.status === PENDING && lastBeat.status === DOWN) { - heartbeat.status = lastBeat.status; - } - } - - if (heartbeat.status !== UP) { - heartbeat.msg = "Child inaccessible"; - } - } else { + if (children.length === 0) { // Set status pending if group is empty heartbeat.status = PENDING; heartbeat.msg = "Group empty"; + return; } + + let worstStatus = UP; + const downChildren = []; + const pendingChildren = []; + + for (const child of children) { + if (!child.active) { + // Ignore inactive (=paused) children + continue; + } + + const label = child.name || `#${child.id}`; + const lastBeat = await Monitor.getPreviousHeartbeat(child.id); + + if (!lastBeat) { + if (worstStatus === UP) { + worstStatus = PENDING; + } + pendingChildren.push(label); + continue; + } + + if (lastBeat.status === DOWN) { + worstStatus = DOWN; + downChildren.push(label); + } else if (lastBeat.status === PENDING) { + if (worstStatus !== DOWN) { + worstStatus = PENDING; + } + pendingChildren.push(label); + } + } + + if (worstStatus === UP) { + heartbeat.status = UP; + heartbeat.msg = "All children up and running"; + return; + } + + if (worstStatus === PENDING) { + heartbeat.status = PENDING; + heartbeat.msg = `Pending child monitors: ${pendingChildren.join(", ")}`; + return; + } + + heartbeat.status = DOWN; + + let message = `Child monitors down: ${downChildren.join(", ")}`; + + if (pendingChildren.length > 0) { + message += `; pending: ${pendingChildren.join(", ")}`; + } + + // Throw to leverage the generic retry handling and notification flow + throw new Error(message); } }