Files
skywatch/server/monitorService.js
T

117 lines
3.1 KiB
JavaScript

const axios = require('axios');
const db = require('./database');
class MonitorService {
async checkResource(resource) {
const startTime = Date.now();
let result = {
resource_id: resource.id,
status: 'down',
response_time: null,
status_code: null,
error_message: null,
};
try {
const response = await axios.get(resource.url, {
timeout: resource.timeout,
validateStatus: () => true, // Don't throw on any status
});
const responseTime = Date.now() - startTime;
const isUp = response.status >= 200 && response.status < 400;
result = {
...result,
status: isUp ? 'up' : 'down',
response_time: responseTime,
status_code: response.status,
error_message: isUp ? null : `HTTP ${response.status}`,
};
} catch (error) {
result.error_message = error.message;
result.response_time = Date.now() - startTime;
}
return result;
}
saveCheck(check) {
const stmt = db.prepare(`
INSERT INTO checks (resource_id, status, response_time, status_code, error_message)
VALUES (?, ?, ?, ?, ?)
`);
stmt.run(
check.resource_id,
check.status,
check.response_time,
check.status_code,
check.error_message
);
}
getLastCheck(resourceId) {
return db.prepare(`
SELECT * FROM checks
WHERE resource_id = ?
ORDER BY checked_at DESC
LIMIT 1
`).get(resourceId);
}
handleIncident(resourceId, isDown) {
const activeIncident = db.prepare(`
SELECT * FROM incidents
WHERE resource_id = ? AND resolved_at IS NULL
`).get(resourceId);
if (isDown && !activeIncident) {
// Start new incident
db.prepare(`
INSERT INTO incidents (resource_id) VALUES (?)
`).run(resourceId);
return { type: 'started', incident: true };
} else if (!isDown && activeIncident) {
// Resolve incident
db.prepare(`
UPDATE incidents
SET resolved_at = CURRENT_TIMESTAMP
WHERE id = ?
`).run(activeIncident.id);
return { type: 'resolved', incident: activeIncident };
}
return { type: 'none' };
}
getResourceStats(resourceId, hours = 24) {
const checks = db.prepare(`
SELECT * FROM checks
WHERE resource_id = ?
AND checked_at >= datetime('now', '-' || ? || ' hours')
ORDER BY checked_at ASC
`).all(resourceId, hours);
const upChecks = checks.filter(c => c.status === 'up');
const totalChecks = checks.length;
const uptime = totalChecks > 0 ? (upChecks.length / totalChecks) * 100 : 0;
const responseTimes = checks
.filter(c => c.response_time !== null)
.map(c => c.response_time);
const avgResponseTime = responseTimes.length > 0
? responseTimes.reduce((a, b) => a + b, 0) / responseTimes.length
: 0;
return {
uptime: uptime.toFixed(2),
avgResponseTime: avgResponseTime.toFixed(0),
totalChecks,
checks: checks.slice(-50), // Last 50 checks
};
}
}
module.exports = new MonitorService();