Probe every domain every minute, and keep it out of its own traffic numbers
NPM's access log only describes hosts somebody visited; the host most likely to be quietly broken is the one nobody does. Probes carry a User-Agent npm_access_stats.sh drops — unmarked, this monitor would be fifty thousand requests a day in the very logs it reports on.
This commit is contained in:
@@ -102,7 +102,7 @@ require_once dirname(__DIR__) . '/include/auth.php';
|
||||
// panels every stack carries rather than gated to one.
|
||||
const VV_AUTH_ACTION_PANEL = [
|
||||
// GET
|
||||
'npm_proxies' => 'proxies', 'npm_certs' => 'proxies', 'npm_stats' => 'proxies',
|
||||
'npm_proxies' => 'proxies', 'npm_certs' => 'proxies', 'npm_stats' => 'proxies', 'npm_uptime' => 'proxies',
|
||||
'lldap_users' => 'users', 'lldap_groups' => 'users', 'lldap_avatar' => 'users',
|
||||
'authelia_rules' => 'acl',
|
||||
// POST
|
||||
@@ -115,6 +115,16 @@ const VV_AUTH_ACTION_PANEL = [
|
||||
'authelia_save' => 'acl',
|
||||
];
|
||||
|
||||
// Same windowing rule as uptime_probe.php: buckets are keyed by time, so "the last N" is a key
|
||||
// sort rather than an assumption that every period produced a sample.
|
||||
function vv_uptime_window_api(array $buckets, int $n): ?float {
|
||||
if (!$buckets) return null;
|
||||
krsort($buckets);
|
||||
$u = $t = 0;
|
||||
foreach (array_slice($buckets, 0, $n, true) as $b) { $u += $b['u'] ?? 0; $t += $b['t'] ?? 0; }
|
||||
return $t > 0 ? round($u / $t * 100, 2) : null;
|
||||
}
|
||||
|
||||
function vv_auth_action_allowed(string $action): bool {
|
||||
$panel = VV_AUTH_ACTION_PANEL[$action] ?? null;
|
||||
// Unmapped actions are left to the existing "Unknown action" answer rather than being refused
|
||||
@@ -161,6 +171,30 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Per-domain uptime, written by Tools/uptime_probe.sh every minute. Keyed by hostname rather
|
||||
// than proxy id, because that is what was probed.
|
||||
if ($action === 'npm_uptime') {
|
||||
$f = rtrim(defined('DB_DIR') ? DB_DIR : (DATA_DIR . '/db'), '/') . '/uptime.json';
|
||||
$u = is_file($f) ? (json_decode((string) @file_get_contents($f), true) ?: []) : [];
|
||||
$out = [];
|
||||
foreach ($u['domains'] ?? [] as $dom => $r) {
|
||||
// Only what the row draws. The hourly and daily buckets are dozens of entries per
|
||||
// domain and the page shows three percentages and a strip.
|
||||
$out[$dom] = [
|
||||
'state' => $r['state'] ?? null,
|
||||
'samples' => array_slice($r['samples'] ?? [], -60),
|
||||
'h1' => vv_uptime_window_api($r['hours'] ?? [], 1),
|
||||
'h24' => vv_uptime_window_api($r['hours'] ?? [], 24),
|
||||
'd30' => vv_uptime_window_api($r['days'] ?? [], 30),
|
||||
'last_change' => $r['last_change'] ?? null,
|
||||
'last_detail' => $r['last_detail'] ?? null,
|
||||
'last_ms' => $r['last_ms'] ?? null,
|
||||
];
|
||||
}
|
||||
echo json_encode(['ok' => true, 'domains' => $out, 'last_pass' => $u['last_pass'] ?? null]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$result = match ($action) {
|
||||
'npm_proxies' => vv_npm_list_proxies(),
|
||||
'npm_certs' => ['ok' => true, 'certs' => vv_npm_list_certs()],
|
||||
|
||||
Reference in New Issue
Block a user