UNPKG

@merncloud/nodejs-monitoring

Version:

A comprehensive monitoring service for Node.js applications with built-in health probes and metrics collection

166 lines 6.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MonitoringService = void 0; const SystemMetrics_1 = require("./collectors/SystemMetrics"); const RequestTracker_1 = require("./collectors/RequestTracker"); const BuiltInProbes_1 = require("./probes/BuiltInProbes"); class MonitoringService { constructor(config = {}) { this.customProbes = []; this.probeResults = new Map(); this.metricsHistory = []; this.config = { enableHealthRoute: true, healthRoutePath: "/health", enableMetricsCollection: true, metricsInterval: 30000, enableRequestTracking: true, enableErrorTracking: true, ...config, }; this.systemMetrics = SystemMetrics_1.SystemMetrics.getInstance(); this.requestTracker = RequestTracker_1.RequestTracker.getInstance(); this.startTime = Date.now(); this.initializeBuiltInProbes(); this.startMetricsCollection(); this.startProbeExecution(); } static getInstance(config) { if (!MonitoringService.instance) { MonitoringService.instance = new MonitoringService(config); } return MonitoringService.instance; } initializeBuiltInProbes() { const thresholds = this.config.alertThresholds || {}; this.customProbes.push(BuiltInProbes_1.BuiltInProbes.createMemoryProbe(thresholds.memoryUsage), BuiltInProbes_1.BuiltInProbes.createCpuProbe(thresholds.cpuUsage), BuiltInProbes_1.BuiltInProbes.createUptimeProbe(), BuiltInProbes_1.BuiltInProbes.createDiskSpaceProbe()); if (this.config.customProbes) { this.customProbes.push(...this.config.customProbes); } } startMetricsCollection() { if (!this.config.enableMetricsCollection) return; setInterval(() => { const metrics = this.collectMetrics(); this.metricsHistory.push(metrics); if (this.metricsHistory.length > 100) { this.metricsHistory.shift(); } }, this.config.metricsInterval); } startProbeExecution() { this.customProbes.forEach((probe) => { const interval = probe.interval || 60000; const executeProbe = async () => { try { const result = await probe.check(); this.probeResults.set(probe.name, result); } catch (error) { this.probeResults.set(probe.name, { status: "critical", message: `Probe execution failed: ${error instanceof Error ? error.message : "Unknown error"}`, }); } }; executeProbe(); setInterval(executeProbe, interval); }); } collectMetrics() { const memory = this.systemMetrics.getMemoryMetrics(); const cpu = this.systemMetrics.getCpuMetrics(); const process = this.systemMetrics.getProcessMetrics(); const requestMetrics = this.requestTracker.getMetrics(); return { timestamp: Date.now(), uptime: Math.floor((Date.now() - this.startTime) / 1000), memory, cpu, process, requests: { total: requestMetrics.total, active: requestMetrics.active, averageResponseTime: requestMetrics.averageResponseTime, }, errors: requestMetrics.errors, }; } requestTrackingMiddleware() { if (!this.config.enableRequestTracking) { return (req, res, next) => next(); } return (req, res, next) => { const startTime = Date.now(); const requestId = this.requestTracker.startRequest(); res.on("finish", () => { this.requestTracker.endRequest(requestId, startTime); if (res.statusCode >= 400 && this.config.enableErrorTracking) { this.requestTracker.recordError(); } }); next(); }; } healthCheckHandler() { return (req, res) => { const metrics = this.collectMetrics(); const probes = Object.fromEntries(this.probeResults); const overallStatus = this.getOverallStatus(probes); res.status(overallStatus === "healthy" ? 200 : 503).json({ status: overallStatus, timestamp: metrics.timestamp, uptime: metrics.uptime, metrics, probes, version: process.env.npm_package_version || "1.0.0", }); }; } metricsHistoryHandler() { return (req, res) => { const limit = parseInt(req.query.limit) || 50; const metrics = this.metricsHistory.slice(-limit); res.json({ metrics, count: metrics.length, latest: metrics[metrics.length - 1], }); }; } getOverallStatus(probes) { const statuses = Object.values(probes).map((probe) => probe.status); if (statuses.includes("critical")) return "critical"; if (statuses.includes("warning")) return "warning"; return "healthy"; } addProbe(probe) { this.customProbes.push(probe); const interval = probe.interval || 60000; const executeProbe = async () => { try { const result = await probe.check(); this.probeResults.set(probe.name, result); } catch (error) { this.probeResults.set(probe.name, { status: "critical", message: `Probe execution failed: ${error instanceof Error ? error.message : "Unknown error"}`, }); } }; executeProbe(); setInterval(executeProbe, interval); } getCurrentMetrics() { return this.collectMetrics(); } getProbeResults() { return Object.fromEntries(this.probeResults); } } exports.MonitoringService = MonitoringService; //# sourceMappingURL=MonitoringService.js.map