diff --git a/server.ts b/server.ts index f93bdc2..ce3f773 100644 --- a/server.ts +++ b/server.ts @@ -741,50 +741,38 @@ async function startServer() { } // Step 2: fetch live monitoring state for all hosts in one call. - // Uses query param to force the collection to return results (some CheckMK versions - // return an empty list without an explicit filter even with full permissions). let hostnameToState: Map; try { - const monQuery = encodeURIComponent(JSON.stringify({ op: '!=', left: 'name', right: '' })); const monRes = await fetch( - `${CHECKMK_API_URL}/domain-types/host/collections/all?query=${monQuery}`, + `${CHECKMK_API_URL}/domain-types/host/collections/all`, { headers } ); if (!monRes.ok) throw new Error(checkmkHttpHint(monRes.status)); const monData = await monRes.json(); + + // Log raw response so we can see the actual structure (first 500 chars). + db.prepare('INSERT INTO logs (id, timestamp, type, message) VALUES (?, ?, ?, ?)') + .run(uid('log'), now, 'system', + `CheckMK monitoring raw response: ${JSON.stringify(monData).substring(0, 500)}`); + hostnameToState = new Map(); - for (const host of monData?.value ?? []) { - const name: string | undefined = host?.id; + // Try multiple possible container keys used by different CheckMK versions. + const candidates: any[] = Array.isArray(monData?.value) + ? monData.value + : Array.isArray(monData?.members) + ? monData.members.map((m: any) => m?.value ?? m) + : []; + for (const host of candidates) { + const name: string | undefined = host?.id ?? host?.extensions?.name; const state: number | undefined = host?.extensions?.state; if (name !== undefined && state !== undefined) hostnameToState.set(name, state); } if (hostnameToState.size === 0 && ipToHostname.size > 0) { - // Monitoring collection empty despite config hosts existing. - // Likely cause: automation user lacks "Use monitoring" permission in CheckMK. - // Falling back: probe one host via /objects/host_config/{name} and log its raw extensions - // so we can identify which field carries the reachability state. db.prepare('INSERT INTO logs (id, timestamp, type, message) VALUES (?, ?, ?, ?)') .run(uid('log'), now, 'system', - 'CheckMK: monitoring collection returned 0 hosts — automation user has no monitoring view access. ' + - 'Fix in CheckMK: Setup → Users → edit automation user → Roles → assign "Administrator" or a role with ' + - '"General Permissions → Use monitoring" and "See all hosts and services" enabled. ' + - 'Alternatively: add the automation user to all relevant Contact Groups.'); - - const firstHostname = [...ipToHostname.values()][0]; - try { - const probeRes = await fetch( - `${CHECKMK_API_URL}/objects/host_config/${encodeURIComponent(firstHostname)}`, - { headers } - ); - if (probeRes.ok) { - const probeData = await probeRes.json(); - const extJson = JSON.stringify(probeData?.extensions ?? {}).substring(0, 400); - db.prepare('INSERT INTO logs (id, timestamp, type, message) VALUES (?, ?, ?, ?)') - .run(uid('log'), now, 'system', - `CheckMK probe extensions for "${firstHostname}": ${extJson}`); - } - } catch { /* probe is best-effort */ } + `CheckMK: parsed 0 monitoring hosts from response (candidates array length: ${candidates.length}). ` + + 'Check the raw response entry above to identify the correct JSON path.'); } } catch (err: any) { const msg = `CheckMK sync failed — could not fetch monitoring states: ${err?.message ?? err}`;