Add timed mutes so a temporary problem stops needing a permanent exemption
Every existing exemption lasts until someone remembers to undo it, and nobody does — Healarr has sat in a pressure list since it was uninstalled and seven ignore entries name containers that are gone. A mute states when it ends and then ends, capped by WATCHDOG_MUTE_MAX_HOURS so temporary is enforced rather than intended. Applied where IGNORE_MAP is built, so all five check sites inherit it, and shown with its countdown because an invisible suppression is the thing being fixed.
This commit is contained in:
@@ -84,6 +84,31 @@ function vv_wd_installed_containers(): array {
|
||||
return array_values(array_filter(array_map('trim', $out), fn($n) => $n !== ''));
|
||||
}
|
||||
|
||||
// Active timed mutes, as [name => ['left' => seconds, 'reason' => text]]. Expiry is a read-time
|
||||
// comparison here for the same reason it is in wd_mute_active(): a mute ends when it says it does,
|
||||
// whether or not anything has pruned the file since.
|
||||
//
|
||||
// Surfaced because a suppression nobody can see is the problem this feature exists to fix. An
|
||||
// invisible exemption gets forgotten exactly like a permanent one — the only difference would be
|
||||
// that this one also lies about how long it lasts.
|
||||
function vv_wd_mutes(string $file = ''): array {
|
||||
$path = $file ?: (vv_conf_vars()['WATCHDOG_MUTE_FILE'] ?? STATE_DIR . '/watchdog_mutes.db');
|
||||
$raw = @file_get_contents($path);
|
||||
if ($raw === false) return [];
|
||||
$now = time();
|
||||
$out = [];
|
||||
foreach (explode("\n", $raw) as $line) {
|
||||
$line = trim($line);
|
||||
if ($line === '') continue;
|
||||
$p = explode('|', $line);
|
||||
if (count($p) < 2) continue;
|
||||
$until = (int)$p[1];
|
||||
if ($until <= $now || $p[0] === '') continue;
|
||||
$out[$p[0]] = ['left' => $until - $now, 'reason' => trim($p[2] ?? '')];
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
// How many minutes are supposed to pass between watchdog cycles.
|
||||
//
|
||||
// Parsed from varaverk.cron, which the scheduler regenerates at array start and is the only place
|
||||
@@ -294,6 +319,7 @@ function vv_wd_local_states(string $restartLogPath): array {
|
||||
// The heartbeat, not a strike — see VV_WD_SYS_BOOKKEEPING. stability_watchdog.sh writes it
|
||||
// last in the chain, so a fresh value means a whole cycle completed rather than started.
|
||||
'last_cycle' => (int)($sys['watchdog_cycle'] ?? 0),
|
||||
'mutes' => vv_wd_mutes(),
|
||||
'reboots' => vv_wd_parse_reboot_log($rebootRaw),
|
||||
'restarts' => vv_wd_parse_restart_log($restartRaw),
|
||||
'storage_wd' => vv_wd_parse_storage_state($storRaw) + [
|
||||
|
||||
@@ -514,6 +514,22 @@ function _dockerCard(node, cfg) {
|
||||
}
|
||||
}
|
||||
|
||||
// Shown with the time left, not just the name. A mute whose remaining time is invisible is
|
||||
// indistinguishable from the permanent exemptions it was built to replace — the countdown is
|
||||
// the entire difference, so it is the part that has to be on screen.
|
||||
const mutes = st.mutes || {};
|
||||
const muteNames = Object.keys(mutes);
|
||||
const muteHtml = muteNames.length === 0
|
||||
? '<div style="color:#333;font-size:11px;">none</div>'
|
||||
: `<div class="vv-wd-pill-row">${muteNames.map(n => {
|
||||
const m = mutes[n];
|
||||
const left = m.left >= 3600 ? Math.round(m.left / 3600) + 'h'
|
||||
: m.left >= 60 ? Math.round(m.left / 60) + 'm'
|
||||
: m.left + 's';
|
||||
return `<span class="vv-wd-pill warn" title="${vvEscAttr(m.reason || 'no reason given')}">`
|
||||
+ `${vvEscHtml(n)} · ${left}</span>`;
|
||||
}).join('')}</div>`;
|
||||
|
||||
let skipHtml = '';
|
||||
if (skiplist.length === 0) {
|
||||
skipHtml = '<div style="color:#333;font-size:11px;">empty</div>';
|
||||
@@ -548,6 +564,9 @@ function _dockerCard(node, cfg) {
|
||||
<div class="vv-wd-sec">Skip list</div>
|
||||
${skipHtml}
|
||||
<hr class="vv-wd-sep">
|
||||
<div class="vv-wd-sec">Muted</div>
|
||||
${muteHtml}
|
||||
<hr class="vv-wd-sep">
|
||||
<div class="vv-wd-sec">Restarts (24h)</div>
|
||||
${restartHtml}
|
||||
</div>`;
|
||||
|
||||
Reference in New Issue
Block a user