Files
Admin_dash/monitor.js
Shivam Patel d5ab2db926 Wire up visitor metrics from webserver DB and fix uptime monitoring
- Read visitors from /server_storage/visitors.db (webserver's DB) instead of
  admin dash's own table; geoip lookups at query time for globe markers
- Globe card now shows 24h, 7d, and all-time unique visitor counts
- Uptime monitor: Nextcloud via host.docker.internal for Docker networking,
  Website and Gitea monitored on public domains
- UptimeCard uses real hourly history bars instead of Math.random() mock
- docker-compose: mount /server_storage:ro, add extra_hosts for Linux compat

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 00:50:40 -05:00

81 lines
2.5 KiB
JavaScript

const sqlite3 = require('sqlite3');
const { open } = require('sqlite');
const fetch = require('node-fetch'); // Native fetch in Node 18, but let's be safe or use global fetch
// Node 18 has global fetch, so we don't need node-fetch if running with node 18
const SERVICES = [
{ name: 'Website', url: 'https://www.akkolli.net' },
{ name: 'Gitea', url: 'https://code.akkolli.net' },
{ name: 'Nextcloud', url: 'http://host.docker.internal:6060' },
];
async function monitor() {
console.log('Starting monitoring loop...');
const dbPath = process.env.DB_PATH || './dashboard.db';
const db = await open({
filename: dbPath,
driver: sqlite3.Database
});
// Ensure table exists (in case monitor runs before app)
await db.exec(`
CREATE TABLE IF NOT EXISTS uptime_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
service_name TEXT NOT NULL,
url TEXT NOT NULL,
status TEXT NOT NULL,
latency INTEGER,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);
`);
setInterval(async () => {
console.log('Running checks...');
const now = new Date().toISOString();
for (const service of SERVICES) {
const start = performance.now();
let status = 'down';
let latency = 0;
try {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 5000);
const res = await fetch(service.url, {
method: 'HEAD',
signal: controller.signal
});
clearTimeout(timeout);
status = res.ok ? 'up' : 'down';
const end = performance.now();
latency = Math.round(end - start);
} catch (err) {
status = 'down';
latency = 0;
// console.error(`Failed to reach ${service.name}:`, err.message);
}
try {
await db.run(
`INSERT INTO uptime_logs (service_name, url, status, latency, timestamp) VALUES (?, ?, ?, ?, ?)`,
service.name, service.url, status, latency, now
);
} catch (dbErr) {
console.error('DB Write Error:', dbErr);
}
}
// Prune old logs (keep 7 days)
try {
await db.run(`DELETE FROM uptime_logs WHERE timestamp < datetime('now', '-7 days')`);
} catch (e) { }
}, 60000); // Run every minute
}
monitor();