Files
infrastructure-monitoring-d…/backend/server.js
T
Klein 51eb3bf7c8 Implement all vendor integrations, WAN graphs, and FortiGate health panel
- Wire up 26 vendor providers: Atlassian Statuspage API, Status.io, Instatus,
  AWS RSS feeds, Apple/Google JSON feeds, M365 Graph API, and synthetic checks
- Add 11 new providers: AWS, Cloudflare, SmartPass, School Dismissal Manager,
  SherpaDesk, Classkick, ClassDojo, Savvas, Study Island, Promethean, RAZ-Kids
- Rename Local Infrastructure → Internet (TCP check to 8.8.8.8:53)
- Add WAN throughput graph section: dual-link canvas graphs (Crown Castle +
  Comcast) polling FortiGate REST API every 30s with 30-min rolling history
- Add FortiGate health card: uptime, CPU %, memory % from FortiOS API
- Add /api/throughput and /api/fortigate-health endpoints
- Add README with setup instructions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 13:46:13 -05:00

78 lines
2.1 KiB
JavaScript

import "dotenv/config";
import express from "express";
import cors from "cors";
import { providers } from "./providers/index.js";
import { startPolling as startThroughputPolling, getHistory as getThroughputHistory } from "./fortigate-throughput.js";
import { startPolling as startHealthPolling, getHealth as getFgHealth } from "./fortigate-health.js";
const app = express();
const PORT = 3000;
const POLL_INTERVAL = 2 * 60 * 1000; // 2 minutes
const PROVIDER_TIMEOUT = 10 * 1000; // 10 seconds
app.use(cors());
let cachedStatuses = [];
function safeCheck(provider) {
return Promise.race([
provider.checkStatus(),
new Promise((_, reject) =>
setTimeout(() => reject(new Error("Timeout")), PROVIDER_TIMEOUT)
),
]).catch((err) => ({
name: provider.name,
status: "unknown",
message: `Check failed: ${err.message}`,
lastUpdated: new Date().toISOString(),
})).then((result) => ({
url: provider.url ?? null,
...result,
}));
}
async function pollAll() {
const results = await Promise.allSettled(providers.map(safeCheck));
cachedStatuses = results.map((r) =>
r.status === "fulfilled"
? r.value
: {
name: "Unknown",
status: "unknown",
message: "Provider check failed.",
lastUpdated: new Date().toISOString(),
}
);
console.log(
`[${new Date().toISOString()}] Polled ${cachedStatuses.length} providers`
);
}
app.get("/api/status", (_req, res) => {
res.json(cachedStatuses);
});
app.get("/api/throughput", (_req, res) => {
res.json(getThroughputHistory());
});
app.get("/api/fortigate-health", (_req, res) => {
const health = getFgHealth();
if (!health) return res.status(503).json({ error: "Health data not yet available." });
res.json(health);
});
app.get("/api/health", (_req, res) => {
res.json({ ok: true, providers: providers.length });
});
// Poll immediately, then on interval
startThroughputPolling();
startHealthPolling();
await pollAll();
setInterval(pollAll, POLL_INTERVAL);
app.listen(PORT, () => {
console.log(`Backend listening on http://localhost:${PORT}`);
});