Say what Varaverk itself is using on the System card
The card described the machine and said nothing about the thing whose dashboard it is. Cache size matters most: VV_CACHE_ROOT is under /tmp, which on Unraid is RAM, so it is shown against the rootfs percentage it counts against. Jobs are locks with a live process — four lock files were sitting there and one job was actually running.
This commit is contained in:
@@ -112,6 +112,7 @@ if (vv_ai_ui_on()) {
|
|||||||
|
|
||||||
$monitor = [
|
$monitor = [
|
||||||
'system' => vv_system_info(),
|
'system' => vv_system_info(),
|
||||||
|
'varaverk' => vv_varaverk_state(),
|
||||||
'fallback' => vv_fallback_state(),
|
'fallback' => vv_fallback_state(),
|
||||||
'fallback_active' => vv_fallback_active(),
|
'fallback_active' => vv_fallback_active(),
|
||||||
'partner' => vv_partner_state(),
|
'partner' => vv_partner_state(),
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ if (vv_ai_ui_on()) {
|
|||||||
|
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'system' => vv_system_info(),
|
'system' => vv_system_info(),
|
||||||
|
'varaverk' => vv_varaverk_state(),
|
||||||
'fallback' => vv_fallback_state(),
|
'fallback' => vv_fallback_state(),
|
||||||
'fallback_active' => vv_fallback_active(),
|
'fallback_active' => vv_fallback_active(),
|
||||||
'partner' => vv_partner_state(),
|
'partner' => vv_partner_state(),
|
||||||
|
|||||||
@@ -329,6 +329,76 @@ function vv_watchdog_summary(): array {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// What Varaverk itself is occupying and doing, as opposed to what the machine is.
|
||||||
|
//
|
||||||
|
// The System card described the host — model, uptime, load — and said nothing about the thing
|
||||||
|
// whose dashboard it is. These are the figures that are Varaverk's own and that nothing else on
|
||||||
|
// the page reports.
|
||||||
|
//
|
||||||
|
// The cache size is the one worth watching. VV_CACHE_ROOT is /tmp/varaverk, and on Unraid /tmp is
|
||||||
|
// on rootfs, which is RAM — so this directory is memory, not disk, and the arr payload cache is
|
||||||
|
// most of it. master.conf says never to move these onto flash, which makes the size the thing to
|
||||||
|
// keep an eye on instead. Reported next to the rootfs percentage it consumes, because 187 MB
|
||||||
|
// means nothing without the ceiling it counts against.
|
||||||
|
//
|
||||||
|
// du rather than a recursive PHP walk: both roots are small and page-cached, measured at 3ms
|
||||||
|
// each, and this is assembled once a minute by the cache writer rather than per page load.
|
||||||
|
function vv_varaverk_state(): array {
|
||||||
|
$du = function (string $path): ?int {
|
||||||
|
if (!is_dir($path)) return null;
|
||||||
|
$out = shell_exec('du -sb ' . escapeshellarg($path) . ' 2>/dev/null');
|
||||||
|
return preg_match('/^(\d+)/', (string)$out, $m) ? (int)$m[1] : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Locks whose process is still alive. A lock file alone does not mean a job is running —
|
||||||
|
// acquire_lock() clears one whose pid is gone, and three were sitting in LOCK_DIR from jobs
|
||||||
|
// that finished days ago. Counting files would have reported four jobs running and one
|
||||||
|
// actually was.
|
||||||
|
$running = [];
|
||||||
|
$stale = 0;
|
||||||
|
foreach ((array)@glob('/tmp/unraid_locks/*.lock') as $lock) {
|
||||||
|
$content = trim((string)@file_get_contents($lock));
|
||||||
|
if ($content === '') { $stale++; continue; }
|
||||||
|
[$pid, $name] = array_pad(explode(':', $content, 2), 2, '');
|
||||||
|
$pid = (int)$pid;
|
||||||
|
if ($pid > 1 && @posix_kill($pid, 0)) {
|
||||||
|
$running[] = $name !== '' ? $name : basename($lock, '.lock');
|
||||||
|
} else {
|
||||||
|
$stale++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort($running);
|
||||||
|
|
||||||
|
// Newest partner conf in the RAM cache. conf_sync fills it; an age climbing past its schedule
|
||||||
|
// means the mesh has stopped talking, which nothing else on this page would show.
|
||||||
|
$confAge = null;
|
||||||
|
foreach ((array)@glob(VV_CONF_RAM_CACHE_DIR . '/host*.conf') as $c) {
|
||||||
|
$m = @filemtime($c);
|
||||||
|
if ($m && ($confAge === null || (time() - $m) < $confAge)) $confAge = time() - $m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage mode as a fact about where this install actually is, not as the conf toggle's word
|
||||||
|
// for it — the toggle is what someone intended and the path is what happened.
|
||||||
|
//
|
||||||
|
// "internal", not "flash". /boot is the internal mode in Varaverk's own vocabulary and on this
|
||||||
|
// hardware it is a mirrored NVMe pool, not a USB stick; calling it flash on the dashboard
|
||||||
|
// would invite a write-wear worry that does not apply here.
|
||||||
|
$internal = str_starts_with(SCRIPTS_DIR, '/boot');
|
||||||
|
|
||||||
|
return [
|
||||||
|
'cache_root' => VV_CACHE_ROOT,
|
||||||
|
'cache_bytes' => $du(VV_CACHE_ROOT),
|
||||||
|
'data_bytes' => $du(DATA_DIR),
|
||||||
|
'scripts_dir' => SCRIPTS_DIR,
|
||||||
|
'storage' => $internal ? 'internal' : 'appdata',
|
||||||
|
'commit' => trim((string)shell_exec(
|
||||||
|
'git -C ' . escapeshellarg(SCRIPTS_DIR) . ' rev-parse --short HEAD 2>/dev/null')),
|
||||||
|
'jobs_running' => $running,
|
||||||
|
'locks_stale' => $stale,
|
||||||
|
'conf_age_sec' => $confAge,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
function vv_scripts_status(): array {
|
function vv_scripts_status(): array {
|
||||||
$logDir = LOG_DIR;
|
$logDir = LOG_DIR;
|
||||||
$statFiles = array_merge(
|
$statFiles = array_merge(
|
||||||
|
|||||||
@@ -949,6 +949,55 @@ function vvPollMonitor(live) {
|
|||||||
: '—';
|
: '—';
|
||||||
const _coreMeta = _threadInfo ? ` <span style="color:#444;">(${_threadInfo})</span>` : '';
|
const _coreMeta = _threadInfo ? ` <span style="color:#444;">(${_threadInfo})</span>` : '';
|
||||||
|
|
||||||
|
// ── Varaverk's own footprint ────────────────────────────────────────────
|
||||||
|
// The rows above describe the machine. These describe the thing whose dashboard this is,
|
||||||
|
// and nothing else on the page reports them.
|
||||||
|
const vv = d.varaverk ?? {};
|
||||||
|
const _rootPct = d.watchdog?.stability?.rootfs_pct ?? null;
|
||||||
|
|
||||||
|
// The cache is RAM, not disk: VV_CACHE_ROOT is /tmp/varaverk and /tmp lives on rootfs, which
|
||||||
|
// on Unraid is a memory filesystem. Shown against the rootfs percentage because a size with
|
||||||
|
// no ceiling beside it is a number nobody can act on.
|
||||||
|
// Local formatters. vvFmt() is a GB formatter — feeding it megabytes prints "186 GB" — and
|
||||||
|
// vvRelTime() takes a timestamp where these carry an age in seconds. Both would have been
|
||||||
|
// silently wrong rather than broken.
|
||||||
|
const _vvSize = b => b == null ? '—'
|
||||||
|
: b >= 1073741824 ? (b / 1073741824).toFixed(1) + ' GB' : Math.round(b / 1048576) + ' MB';
|
||||||
|
const _vvAge = s => s == null ? '—'
|
||||||
|
: s < 90 ? s + 's' : s < 5400 ? Math.round(s / 60) + 'm'
|
||||||
|
: s < 172800 ? Math.round(s / 3600) + 'h' : Math.round(s / 86400) + 'd';
|
||||||
|
|
||||||
|
const _cacheColor = _rootPct == null ? '#888'
|
||||||
|
: _rootPct >= 90 ? '#f44336' : _rootPct >= 75 ? '#ff9800' : '#888';
|
||||||
|
// The suffix belongs to a real figure. "— in RAM" reads as a measurement that came back
|
||||||
|
// empty rather than one that was never taken.
|
||||||
|
const _cacheStr = vv.cache_bytes == null
|
||||||
|
? `<span style="color:#555;">not measured</span>`
|
||||||
|
: `${_vvSize(vv.cache_bytes)}<span style="color:#444;"> in RAM`
|
||||||
|
+ (_rootPct != null ? ` · rootfs ${_rootPct}%` : '') + `</span>`;
|
||||||
|
|
||||||
|
const _dataStr = vv.data_bytes == null
|
||||||
|
? `<span style="color:#555;">not measured</span>`
|
||||||
|
: `${_vvSize(vv.data_bytes)}<span style="color:#444;"> on ${vvEscHtml(vv.storage || '?')}</span>`;
|
||||||
|
|
||||||
|
// Jobs actually running — locks whose process is alive. A stale lock is not a running job
|
||||||
|
// and acquire_lock() clears it on the next run, so it is reported as an aside rather than
|
||||||
|
// as a fault.
|
||||||
|
const _jobs = vv.jobs_running ?? [];
|
||||||
|
const _jobStr = _jobs.length === 0
|
||||||
|
? `<span style="color:#555;">idle</span>`
|
||||||
|
: `<span style="color:#4caf50;">${_jobs.length} running</span>`
|
||||||
|
+ `<span style="color:#444;"> · ${vvEscHtml(_jobs.slice(0, 2).join(', '))}`
|
||||||
|
+ (_jobs.length > 2 ? ` +${_jobs.length - 2}` : '') + `</span>`;
|
||||||
|
const _staleStr = (vv.locks_stale ?? 0) > 0
|
||||||
|
? `<span style="color:#3a3a3a;"> · ${vv.locks_stale} stale lock${vv.locks_stale !== 1 ? 's' : ''}</span>` : '';
|
||||||
|
|
||||||
|
// Conf sync freshness. An age climbing past its schedule means the mesh has stopped talking,
|
||||||
|
// which no other row on this page would show.
|
||||||
|
const _confAge = vv.conf_age_sec;
|
||||||
|
const _confStr = _confAge == null ? `<span style="color:#555;">none cached</span>`
|
||||||
|
: `<span style="color:${_confAge > 172800 ? '#ff9800' : '#888'};">${_vvAge(_confAge)} ago</span>`;
|
||||||
|
|
||||||
document.getElementById('vv-system-body').innerHTML =
|
document.getElementById('vv-system-body').innerHTML =
|
||||||
`<div style="display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:8px;">
|
`<div style="display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:8px;">
|
||||||
<div style="min-width:0;">
|
<div style="min-width:0;">
|
||||||
@@ -988,6 +1037,18 @@ function vvPollMonitor(live) {
|
|||||||
<span style="color:#444;">Load</span> <span style="color:${_loadColor};">${_loadStr}</span>
|
<span style="color:#444;">Load</span> <span style="color:${_loadColor};">${_loadStr}</span>
|
||||||
<span style="color:#444;">Running</span> <span style="color:#888;">${_runningCtrs} ctr${_runningCtrs !== 1 ? 's' : ''}${_runningVMs > 0 ? ` · ${_runningVMs} VM` : ''}</span>
|
<span style="color:#444;">Running</span> <span style="color:#888;">${_runningCtrs} ctr${_runningCtrs !== 1 ? 's' : ''}${_runningVMs > 0 ? ` · ${_runningVMs} VM` : ''}</span>
|
||||||
<span style="color:#444;">Version</span> <span style="color:#3a3a3a;">${ver}</span>
|
<span style="color:#444;">Version</span> <span style="color:#3a3a3a;">${ver}</span>
|
||||||
|
</div>
|
||||||
|
<!-- Varaverk's own figures, ruled off from the host's. Same grid so the labels line up,
|
||||||
|
separate block so it reads as a different subject rather than more of the same. -->
|
||||||
|
<div style="border-top:1px solid #1e1e1e;margin-top:8px;padding-top:7px;">
|
||||||
|
<div style="font-size:9px;color:#333;text-transform:uppercase;letter-spacing:.07em;margin-bottom:5px;">Varaverk</div>
|
||||||
|
<div style="display:grid;grid-template-columns:auto 1fr;gap:3px 8px;font-size:11px;">
|
||||||
|
<span style="color:#444;">Cache</span> <span style="color:${_cacheColor};">${_cacheStr}</span>
|
||||||
|
<span style="color:#444;">Data</span> <span style="color:#888;">${_dataStr}</span>
|
||||||
|
<span style="color:#444;">Jobs</span> <span>${_jobStr}${_staleStr}</span>
|
||||||
|
<span style="color:#444;">Conf</span> <span>${_confStr}</span>
|
||||||
|
<span style="color:#444;">Build</span> <span style="color:#3a3a3a;font-family:monospace;">${vvEscHtml(vv.commit || '—')}</span>
|
||||||
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
// ── Partner ──────────────────────────────────────────────────────────────
|
// ── Partner ──────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user