hono-status-monitor 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +320 -0
- package/dist/dashboard.d.ts +6 -0
- package/dist/dashboard.d.ts.map +1 -0
- package/dist/dashboard.js +454 -0
- package/dist/dashboard.js.map +1 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +85 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware.d.ts +6 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +30 -0
- package/dist/middleware.js.map +1 -0
- package/dist/monitor.d.ts +21 -0
- package/dist/monitor.d.ts.map +1 -0
- package/dist/monitor.js +527 -0
- package/dist/monitor.js.map +1 -0
- package/dist/types.d.ts +209 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// HONO STATUS MONITOR - MIDDLEWARE
|
|
3
|
+
// Request tracking middleware for Hono.js
|
|
4
|
+
// =============================================================================
|
|
5
|
+
/**
|
|
6
|
+
* Create Hono middleware for tracking requests
|
|
7
|
+
*/
|
|
8
|
+
export function createMiddleware(monitor) {
|
|
9
|
+
const statusPath = monitor.config.path;
|
|
10
|
+
return async (c, next) => {
|
|
11
|
+
// Skip tracking for status routes
|
|
12
|
+
if (c.req.path.startsWith(statusPath)) {
|
|
13
|
+
await next();
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const path = c.req.path;
|
|
17
|
+
const method = c.req.method;
|
|
18
|
+
// Track request start
|
|
19
|
+
monitor.trackRequest(path, method);
|
|
20
|
+
const startTime = performance.now();
|
|
21
|
+
// Process request
|
|
22
|
+
await next();
|
|
23
|
+
// Calculate response time
|
|
24
|
+
const endTime = performance.now();
|
|
25
|
+
const duration = endTime - startTime;
|
|
26
|
+
// Track completion with all metrics
|
|
27
|
+
monitor.trackRequestComplete(path, method, duration, c.res.status);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,mCAAmC;AACnC,0CAA0C;AAC1C,gFAAgF;AAIhF;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;IAEvC,OAAO,KAAK,EAAE,CAAM,EAAE,IAAyB,EAAE,EAAE;QAC/C,kCAAkC;QAClC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,EAAE,CAAC;YACb,OAAO;QACX,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;QACxB,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;QAE5B,sBAAsB;QACtB,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAEnC,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAEpC,kBAAkB;QAClB,MAAM,IAAI,EAAE,CAAC;QAEb,0BAA0B;QAC1B,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;QAErC,oCAAoC;QACpC,OAAO,CAAC,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACvE,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Server as HttpServer } from 'http';
|
|
2
|
+
import { Server as SocketServer } from 'socket.io';
|
|
3
|
+
import type { StatusMonitorConfig, DatabaseStats, MetricsSnapshot, ChartData } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Create a status monitor instance
|
|
6
|
+
*/
|
|
7
|
+
export declare function createMonitor(userConfig?: StatusMonitorConfig): {
|
|
8
|
+
config: Required<StatusMonitorConfig>;
|
|
9
|
+
trackRequest: (path: string, method: string) => void;
|
|
10
|
+
trackRequestComplete: (path: string, method: string, durationMs: number, statusCode: number) => void;
|
|
11
|
+
trackRateLimitEvent: (blocked: boolean) => void;
|
|
12
|
+
getMetricsSnapshot: (dbStats?: DatabaseStats) => Promise<MetricsSnapshot>;
|
|
13
|
+
getChartData: () => ChartData;
|
|
14
|
+
start: () => void;
|
|
15
|
+
stop: () => void;
|
|
16
|
+
initSocket: (server: HttpServer) => SocketServer;
|
|
17
|
+
formatUptime: (seconds: number) => string;
|
|
18
|
+
readonly io: SocketServer<import("socket.io").DefaultEventsMap, import("socket.io").DefaultEventsMap, import("socket.io").DefaultEventsMap, any> | null;
|
|
19
|
+
};
|
|
20
|
+
export type Monitor = ReturnType<typeof createMonitor>;
|
|
21
|
+
//# sourceMappingURL=monitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monitor.d.ts","sourceRoot":"","sources":["../src/monitor.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,KAAK,EACR,mBAAmB,EAQnB,aAAa,EACb,eAAe,EACf,SAAS,EACZ,MAAM,YAAY,CAAC;AAsCpB;;GAEG;AACH,wBAAgB,aAAa,CAAC,UAAU,GAAE,mBAAwB;;yBAyYlC,MAAM,UAAU,MAAM,KAAG,IAAI;iCA2B/C,MAAM,UACJ,MAAM,cACF,MAAM,cACN,MAAM,KACnB,IAAI;mCAiD+B,OAAO,KAAG,IAAI;mCAnJR,aAAa,KAAG,OAAO,CAAC,eAAe,CAAC;wBAmD3D,SAAS;iBAwGhB,IAAI;gBAWL,IAAI;yBAWO,UAAU,KAAG,YAAY;4BAuBtB,MAAM,KAAG,MAAM;;EA4BjD;AAED,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC"}
|
package/dist/monitor.js
ADDED
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// HONO STATUS MONITOR - CORE METRICS SERVICE
|
|
3
|
+
// Real-time server metrics collection with WebSocket broadcasting
|
|
4
|
+
// =============================================================================
|
|
5
|
+
import * as os from 'os';
|
|
6
|
+
import { Server as SocketServer } from 'socket.io';
|
|
7
|
+
// Default configuration
|
|
8
|
+
const DEFAULT_CONFIG = {
|
|
9
|
+
path: '/status',
|
|
10
|
+
title: 'Server Status',
|
|
11
|
+
socketPath: '/status/socket.io',
|
|
12
|
+
updateInterval: 1000,
|
|
13
|
+
retentionSeconds: 60,
|
|
14
|
+
maxRecentErrors: 10,
|
|
15
|
+
maxRoutes: 10,
|
|
16
|
+
alerts: {
|
|
17
|
+
cpu: 80,
|
|
18
|
+
memory: 90,
|
|
19
|
+
responseTime: 500,
|
|
20
|
+
errorRate: 5,
|
|
21
|
+
eventLoopLag: 100
|
|
22
|
+
},
|
|
23
|
+
healthCheck: async () => ({ connected: true, latencyMs: 0 }),
|
|
24
|
+
normalizePath: (path) => path
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Default path normalization function
|
|
28
|
+
* Groups similar routes together for analytics
|
|
29
|
+
*/
|
|
30
|
+
function defaultNormalizePath(path) {
|
|
31
|
+
return path
|
|
32
|
+
// Replace UUIDs
|
|
33
|
+
.replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, ':uuid')
|
|
34
|
+
// Replace MongoDB ObjectIds (24 hex characters)
|
|
35
|
+
.replace(/[0-9a-f]{24}/gi, ':id')
|
|
36
|
+
// Replace numeric IDs
|
|
37
|
+
.replace(/\/\d+/g, '/:id')
|
|
38
|
+
// Limit path depth to prevent explosion
|
|
39
|
+
.split('/').slice(0, 4).join('/');
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create a status monitor instance
|
|
43
|
+
*/
|
|
44
|
+
export function createMonitor(userConfig = {}) {
|
|
45
|
+
// Merge configuration
|
|
46
|
+
const config = {
|
|
47
|
+
...DEFAULT_CONFIG,
|
|
48
|
+
...userConfig,
|
|
49
|
+
alerts: { ...DEFAULT_CONFIG.alerts, ...userConfig.alerts },
|
|
50
|
+
normalizePath: userConfig.normalizePath || defaultNormalizePath
|
|
51
|
+
};
|
|
52
|
+
// In-memory metrics storage
|
|
53
|
+
let cpuHistory = [];
|
|
54
|
+
let memoryHistory = [];
|
|
55
|
+
let heapHistory = [];
|
|
56
|
+
let loadAvgHistory = [];
|
|
57
|
+
let responseTimeHistory = [];
|
|
58
|
+
let rpsHistory = [];
|
|
59
|
+
let eventLoopLagHistory = [];
|
|
60
|
+
let errorRateHistory = [];
|
|
61
|
+
// Request tracking
|
|
62
|
+
let requestCount = 0;
|
|
63
|
+
let lastRequestCount = 0;
|
|
64
|
+
let totalResponseTime = 0;
|
|
65
|
+
let responseTimeCount = 0;
|
|
66
|
+
let statusCodes = {};
|
|
67
|
+
let totalRequests = 0;
|
|
68
|
+
let activeConnections = 0;
|
|
69
|
+
// Route tracking
|
|
70
|
+
const routeStats = new Map();
|
|
71
|
+
const recentErrors = [];
|
|
72
|
+
// Response time samples for percentiles
|
|
73
|
+
let responseTimeSamples = [];
|
|
74
|
+
// Rate limit tracking
|
|
75
|
+
let rateLimitBlocked = 0;
|
|
76
|
+
let rateLimitTotal = 0;
|
|
77
|
+
// GC tracking
|
|
78
|
+
let lastHeapUsed = 0;
|
|
79
|
+
let heapGrowthRate = 0;
|
|
80
|
+
// CPU tracking
|
|
81
|
+
let lastCpuInfo = null;
|
|
82
|
+
// Event loop lag tracking
|
|
83
|
+
let lastLoopTime = Date.now();
|
|
84
|
+
// Database latency tracking
|
|
85
|
+
let dbLatency = 0;
|
|
86
|
+
// WebSocket server reference
|
|
87
|
+
let io = null;
|
|
88
|
+
// Metrics collection interval
|
|
89
|
+
let metricsInterval = null;
|
|
90
|
+
/**
|
|
91
|
+
* Calculate CPU usage percentage
|
|
92
|
+
*/
|
|
93
|
+
function calculateCpuUsage() {
|
|
94
|
+
const cpus = os.cpus();
|
|
95
|
+
if (!lastCpuInfo) {
|
|
96
|
+
lastCpuInfo = cpus;
|
|
97
|
+
return 0;
|
|
98
|
+
}
|
|
99
|
+
let totalIdle = 0;
|
|
100
|
+
let totalTick = 0;
|
|
101
|
+
for (let i = 0; i < cpus.length; i++) {
|
|
102
|
+
const cpu = cpus[i];
|
|
103
|
+
const lastCpu = lastCpuInfo[i];
|
|
104
|
+
const idle = cpu.times.idle - lastCpu.times.idle;
|
|
105
|
+
const total = (cpu.times.user - lastCpu.times.user) +
|
|
106
|
+
(cpu.times.nice - lastCpu.times.nice) +
|
|
107
|
+
(cpu.times.sys - lastCpu.times.sys) +
|
|
108
|
+
(cpu.times.idle - lastCpu.times.idle) +
|
|
109
|
+
(cpu.times.irq - lastCpu.times.irq);
|
|
110
|
+
totalIdle += idle;
|
|
111
|
+
totalTick += total;
|
|
112
|
+
}
|
|
113
|
+
lastCpuInfo = cpus;
|
|
114
|
+
if (totalTick === 0)
|
|
115
|
+
return 0;
|
|
116
|
+
return Math.round(((totalTick - totalIdle) / totalTick) * 1000) / 10;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Get memory usage in MB
|
|
120
|
+
*/
|
|
121
|
+
function getMemoryMB() {
|
|
122
|
+
const totalMem = os.totalmem();
|
|
123
|
+
const freeMem = os.freemem();
|
|
124
|
+
const usedMem = totalMem - freeMem;
|
|
125
|
+
return Math.round((usedMem / (1024 * 1024)) * 10) / 10;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get memory usage percentage
|
|
129
|
+
*/
|
|
130
|
+
function getMemoryPercent() {
|
|
131
|
+
const totalMem = os.totalmem();
|
|
132
|
+
const freeMem = os.freemem();
|
|
133
|
+
const usedMem = totalMem - freeMem;
|
|
134
|
+
return Math.round((usedMem / totalMem) * 1000) / 10;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get heap memory usage and track growth
|
|
138
|
+
*/
|
|
139
|
+
function getHeapUsage() {
|
|
140
|
+
const mem = process.memoryUsage();
|
|
141
|
+
const used = Math.round((mem.heapUsed / (1024 * 1024)) * 10) / 10;
|
|
142
|
+
// Track heap growth
|
|
143
|
+
if (lastHeapUsed > 0) {
|
|
144
|
+
heapGrowthRate = used - lastHeapUsed;
|
|
145
|
+
}
|
|
146
|
+
lastHeapUsed = used;
|
|
147
|
+
return {
|
|
148
|
+
used,
|
|
149
|
+
total: Math.round((mem.heapTotal / (1024 * 1024)) * 10) / 10
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Get 1-minute load average
|
|
154
|
+
*/
|
|
155
|
+
function getLoadAverage() {
|
|
156
|
+
const loadAvg = os.loadavg();
|
|
157
|
+
return Math.round(loadAvg[0] * 100) / 100;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Measure event loop lag
|
|
161
|
+
*/
|
|
162
|
+
function measureEventLoopLag() {
|
|
163
|
+
const now = Date.now();
|
|
164
|
+
const expectedInterval = config.updateInterval;
|
|
165
|
+
const actualInterval = now - lastLoopTime;
|
|
166
|
+
lastLoopTime = now;
|
|
167
|
+
const lag = Math.max(0, actualInterval - expectedInterval);
|
|
168
|
+
return Math.round(lag * 10) / 10;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Calculate percentiles from samples
|
|
172
|
+
*/
|
|
173
|
+
function calculatePercentiles() {
|
|
174
|
+
if (responseTimeSamples.length === 0) {
|
|
175
|
+
return { p50: 0, p95: 0, p99: 0, avg: 0 };
|
|
176
|
+
}
|
|
177
|
+
const sorted = [...responseTimeSamples].sort((a, b) => a - b);
|
|
178
|
+
const len = sorted.length;
|
|
179
|
+
const p50Index = Math.floor(len * 0.5);
|
|
180
|
+
const p95Index = Math.floor(len * 0.95);
|
|
181
|
+
const p99Index = Math.floor(len * 0.99);
|
|
182
|
+
const avg = sorted.reduce((a, b) => a + b, 0) / len;
|
|
183
|
+
return {
|
|
184
|
+
p50: Math.round(sorted[p50Index] * 100) / 100,
|
|
185
|
+
p95: Math.round(sorted[p95Index] * 100) / 100,
|
|
186
|
+
p99: Math.round(sorted[Math.min(p99Index, len - 1)] * 100) / 100,
|
|
187
|
+
avg: Math.round(avg * 100) / 100
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get top routes by request count
|
|
192
|
+
*/
|
|
193
|
+
function getTopRoutes() {
|
|
194
|
+
return Array.from(routeStats.values())
|
|
195
|
+
.sort((a, b) => b.count - a.count)
|
|
196
|
+
.slice(0, config.maxRoutes);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Get slowest routes by average response time
|
|
200
|
+
*/
|
|
201
|
+
function getSlowestRoutes() {
|
|
202
|
+
return Array.from(routeStats.values())
|
|
203
|
+
.filter(r => r.count > 0)
|
|
204
|
+
.sort((a, b) => b.avgTime - a.avgTime)
|
|
205
|
+
.slice(0, config.maxRoutes);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Get routes with most errors
|
|
209
|
+
*/
|
|
210
|
+
function getErrorRoutes() {
|
|
211
|
+
return Array.from(routeStats.values())
|
|
212
|
+
.filter(r => r.errors > 0)
|
|
213
|
+
.sort((a, b) => b.errors - a.errors)
|
|
214
|
+
.slice(0, config.maxRoutes);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Calculate current error rate
|
|
218
|
+
*/
|
|
219
|
+
function getErrorRate() {
|
|
220
|
+
const totalErrors = Array.from(routeStats.values()).reduce((sum, r) => sum + r.errors, 0);
|
|
221
|
+
if (totalRequests === 0)
|
|
222
|
+
return 0;
|
|
223
|
+
return Math.round((totalErrors / totalRequests) * 10000) / 100;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Check alert conditions
|
|
227
|
+
*/
|
|
228
|
+
function checkAlerts() {
|
|
229
|
+
const cpu = cpuHistory.length > 0 ? cpuHistory[cpuHistory.length - 1].value : 0;
|
|
230
|
+
const memory = getMemoryPercent();
|
|
231
|
+
const respTime = responseTimeHistory.length > 0 ? responseTimeHistory[responseTimeHistory.length - 1].value : 0;
|
|
232
|
+
const errorRate = getErrorRate();
|
|
233
|
+
const lag = eventLoopLagHistory.length > 0 ? eventLoopLagHistory[eventLoopLagHistory.length - 1].value : 0;
|
|
234
|
+
return {
|
|
235
|
+
cpu: cpu > (config.alerts.cpu ?? 80),
|
|
236
|
+
memory: memory > (config.alerts.memory ?? 90),
|
|
237
|
+
responseTime: respTime > (config.alerts.responseTime ?? 500),
|
|
238
|
+
errorRate: errorRate > (config.alerts.errorRate ?? 5),
|
|
239
|
+
eventLoopLag: lag > (config.alerts.eventLoopLag ?? 100)
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Get database stats using custom health check
|
|
244
|
+
*/
|
|
245
|
+
async function getDatabaseStats() {
|
|
246
|
+
try {
|
|
247
|
+
const start = performance.now();
|
|
248
|
+
const result = await config.healthCheck();
|
|
249
|
+
dbLatency = Math.round((performance.now() - start) * 100) / 100;
|
|
250
|
+
return {
|
|
251
|
+
connected: result.connected,
|
|
252
|
+
poolSize: 10,
|
|
253
|
+
availableConnections: result.connected ? 10 : 0,
|
|
254
|
+
waitQueueSize: 0,
|
|
255
|
+
latencyMs: result.latencyMs || dbLatency,
|
|
256
|
+
name: result.name
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return {
|
|
261
|
+
connected: false,
|
|
262
|
+
poolSize: 0,
|
|
263
|
+
availableConnections: 0,
|
|
264
|
+
waitQueueSize: 0,
|
|
265
|
+
latencyMs: 0
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Add a data point to history
|
|
271
|
+
*/
|
|
272
|
+
function addToHistory(history, value) {
|
|
273
|
+
const now = Date.now();
|
|
274
|
+
history.push({ timestamp: now, value });
|
|
275
|
+
const cutoff = now - (config.retentionSeconds * 1000);
|
|
276
|
+
while (history.length > 0 && history[0].timestamp < cutoff) {
|
|
277
|
+
history.shift();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Update metrics and broadcast via WebSocket
|
|
282
|
+
*/
|
|
283
|
+
async function updateMetrics() {
|
|
284
|
+
const heap = getHeapUsage();
|
|
285
|
+
const eventLoopLag = measureEventLoopLag();
|
|
286
|
+
const errorRate = getErrorRate();
|
|
287
|
+
// System metrics
|
|
288
|
+
addToHistory(cpuHistory, calculateCpuUsage());
|
|
289
|
+
addToHistory(memoryHistory, getMemoryMB());
|
|
290
|
+
addToHistory(heapHistory, heap.used);
|
|
291
|
+
addToHistory(loadAvgHistory, getLoadAverage());
|
|
292
|
+
addToHistory(eventLoopLagHistory, eventLoopLag);
|
|
293
|
+
addToHistory(errorRateHistory, errorRate);
|
|
294
|
+
// Request metrics
|
|
295
|
+
const currentRps = requestCount - lastRequestCount;
|
|
296
|
+
lastRequestCount = requestCount;
|
|
297
|
+
addToHistory(rpsHistory, currentRps);
|
|
298
|
+
// Average response time
|
|
299
|
+
const avgResponseTime = responseTimeCount > 0
|
|
300
|
+
? Math.round((totalResponseTime / responseTimeCount) * 100) / 100
|
|
301
|
+
: 0;
|
|
302
|
+
addToHistory(responseTimeHistory, avgResponseTime);
|
|
303
|
+
// Reset response time tracking
|
|
304
|
+
totalResponseTime = 0;
|
|
305
|
+
responseTimeCount = 0;
|
|
306
|
+
// Trim response time samples (keep last 1000)
|
|
307
|
+
if (responseTimeSamples.length > 1000) {
|
|
308
|
+
responseTimeSamples = responseTimeSamples.slice(-500);
|
|
309
|
+
}
|
|
310
|
+
// Broadcast to connected clients
|
|
311
|
+
if (io) {
|
|
312
|
+
const dbStats = await getDatabaseStats();
|
|
313
|
+
io.emit('metrics', {
|
|
314
|
+
snapshot: await getMetricsSnapshot(dbStats),
|
|
315
|
+
charts: getChartData()
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Get current metrics snapshot
|
|
321
|
+
*/
|
|
322
|
+
async function getMetricsSnapshot(dbStats) {
|
|
323
|
+
const heap = getHeapUsage();
|
|
324
|
+
const db = dbStats || await getDatabaseStats();
|
|
325
|
+
return {
|
|
326
|
+
timestamp: Date.now(),
|
|
327
|
+
cpu: cpuHistory.length > 0 ? cpuHistory[cpuHistory.length - 1].value : 0,
|
|
328
|
+
memoryMB: getMemoryMB(),
|
|
329
|
+
memoryPercent: getMemoryPercent(),
|
|
330
|
+
heapUsedMB: heap.used,
|
|
331
|
+
heapTotalMB: heap.total,
|
|
332
|
+
loadAvg: getLoadAverage(),
|
|
333
|
+
uptime: Math.round(os.uptime()),
|
|
334
|
+
processUptime: Math.round(process.uptime()),
|
|
335
|
+
responseTime: responseTimeHistory.length > 0
|
|
336
|
+
? responseTimeHistory[responseTimeHistory.length - 1].value
|
|
337
|
+
: 0,
|
|
338
|
+
rps: rpsHistory.length > 0
|
|
339
|
+
? rpsHistory[rpsHistory.length - 1].value
|
|
340
|
+
: 0,
|
|
341
|
+
statusCodes: { ...statusCodes },
|
|
342
|
+
totalRequests,
|
|
343
|
+
activeConnections,
|
|
344
|
+
eventLoopLag: eventLoopLagHistory.length > 0
|
|
345
|
+
? eventLoopLagHistory[eventLoopLagHistory.length - 1].value
|
|
346
|
+
: 0,
|
|
347
|
+
hostname: os.hostname(),
|
|
348
|
+
platform: `${os.type()} ${os.release()}`,
|
|
349
|
+
nodeVersion: process.version,
|
|
350
|
+
pid: process.pid,
|
|
351
|
+
cpuCount: os.cpus().length,
|
|
352
|
+
percentiles: calculatePercentiles(),
|
|
353
|
+
topRoutes: getTopRoutes(),
|
|
354
|
+
slowestRoutes: getSlowestRoutes(),
|
|
355
|
+
errorRoutes: getErrorRoutes(),
|
|
356
|
+
recentErrors: [...recentErrors],
|
|
357
|
+
alerts: checkAlerts(),
|
|
358
|
+
gc: {
|
|
359
|
+
collections: 0,
|
|
360
|
+
pauseTimeMs: 0,
|
|
361
|
+
heapGrowthRate: Math.round(heapGrowthRate * 100) / 100
|
|
362
|
+
},
|
|
363
|
+
database: db,
|
|
364
|
+
rateLimitStats: { blocked: rateLimitBlocked, total: rateLimitTotal },
|
|
365
|
+
errorRate: getErrorRate()
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Get chart data
|
|
370
|
+
*/
|
|
371
|
+
function getChartData() {
|
|
372
|
+
return {
|
|
373
|
+
cpu: [...cpuHistory],
|
|
374
|
+
memory: [...memoryHistory],
|
|
375
|
+
heap: [...heapHistory],
|
|
376
|
+
loadAvg: [...loadAvgHistory],
|
|
377
|
+
responseTime: [...responseTimeHistory],
|
|
378
|
+
rps: [...rpsHistory],
|
|
379
|
+
eventLoopLag: [...eventLoopLagHistory],
|
|
380
|
+
errorRate: [...errorRateHistory]
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Track a request start
|
|
385
|
+
*/
|
|
386
|
+
function trackRequest(path, method) {
|
|
387
|
+
requestCount++;
|
|
388
|
+
totalRequests++;
|
|
389
|
+
activeConnections++;
|
|
390
|
+
const normalizedPath = config.normalizePath(path);
|
|
391
|
+
const key = `${method}:${normalizedPath}`;
|
|
392
|
+
if (!routeStats.has(key)) {
|
|
393
|
+
routeStats.set(key, {
|
|
394
|
+
path: normalizedPath,
|
|
395
|
+
method,
|
|
396
|
+
count: 0,
|
|
397
|
+
totalTime: 0,
|
|
398
|
+
avgTime: 0,
|
|
399
|
+
minTime: Infinity,
|
|
400
|
+
maxTime: 0,
|
|
401
|
+
errors: 0,
|
|
402
|
+
lastAccess: Date.now()
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Track request completion
|
|
408
|
+
*/
|
|
409
|
+
function trackRequestComplete(path, method, durationMs, statusCode) {
|
|
410
|
+
activeConnections = Math.max(0, activeConnections - 1);
|
|
411
|
+
// Track response time
|
|
412
|
+
totalResponseTime += durationMs;
|
|
413
|
+
responseTimeCount++;
|
|
414
|
+
responseTimeSamples.push(durationMs);
|
|
415
|
+
// Track status code
|
|
416
|
+
const codeStr = statusCode.toString();
|
|
417
|
+
statusCodes[codeStr] = (statusCodes[codeStr] || 0) + 1;
|
|
418
|
+
// Update route stats
|
|
419
|
+
const normalizedPath = config.normalizePath(path);
|
|
420
|
+
const key = `${method}:${normalizedPath}`;
|
|
421
|
+
const stats = routeStats.get(key);
|
|
422
|
+
if (stats) {
|
|
423
|
+
stats.count++;
|
|
424
|
+
stats.totalTime += durationMs;
|
|
425
|
+
stats.avgTime = stats.totalTime / stats.count;
|
|
426
|
+
stats.minTime = Math.min(stats.minTime, durationMs);
|
|
427
|
+
stats.maxTime = Math.max(stats.maxTime, durationMs);
|
|
428
|
+
stats.lastAccess = Date.now();
|
|
429
|
+
// Track errors
|
|
430
|
+
if (statusCode >= 400) {
|
|
431
|
+
stats.errors++;
|
|
432
|
+
// Add to recent errors
|
|
433
|
+
recentErrors.unshift({
|
|
434
|
+
timestamp: Date.now(),
|
|
435
|
+
path: normalizedPath,
|
|
436
|
+
method,
|
|
437
|
+
status: statusCode,
|
|
438
|
+
message: `${method} ${normalizedPath} returned ${statusCode}`
|
|
439
|
+
});
|
|
440
|
+
// Keep only recent errors
|
|
441
|
+
while (recentErrors.length > config.maxRecentErrors) {
|
|
442
|
+
recentErrors.pop();
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Track rate limit
|
|
449
|
+
*/
|
|
450
|
+
function trackRateLimitEvent(blocked) {
|
|
451
|
+
rateLimitTotal++;
|
|
452
|
+
if (blocked)
|
|
453
|
+
rateLimitBlocked++;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Start metrics collection
|
|
457
|
+
*/
|
|
458
|
+
function start() {
|
|
459
|
+
if (!metricsInterval) {
|
|
460
|
+
lastLoopTime = Date.now();
|
|
461
|
+
metricsInterval = setInterval(updateMetrics, config.updateInterval);
|
|
462
|
+
console.log('📊 Status monitor started');
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Stop metrics collection
|
|
467
|
+
*/
|
|
468
|
+
function stop() {
|
|
469
|
+
if (metricsInterval) {
|
|
470
|
+
clearInterval(metricsInterval);
|
|
471
|
+
metricsInterval = null;
|
|
472
|
+
console.log('📊 Status monitor stopped');
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Initialize Socket.io server
|
|
477
|
+
*/
|
|
478
|
+
function initSocket(server) {
|
|
479
|
+
io = new SocketServer(server, {
|
|
480
|
+
path: config.socketPath,
|
|
481
|
+
cors: {
|
|
482
|
+
origin: '*',
|
|
483
|
+
methods: ['GET', 'POST']
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
io.on('connection', (socket) => {
|
|
487
|
+
console.log('📊 Status monitor client connected');
|
|
488
|
+
socket.on('disconnect', () => {
|
|
489
|
+
console.log('📊 Status monitor client disconnected');
|
|
490
|
+
});
|
|
491
|
+
});
|
|
492
|
+
console.log('📊 Status monitor WebSocket initialized');
|
|
493
|
+
return io;
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Format uptime
|
|
497
|
+
*/
|
|
498
|
+
function formatUptime(seconds) {
|
|
499
|
+
const days = Math.floor(seconds / 86400);
|
|
500
|
+
const hours = Math.floor((seconds % 86400) / 3600);
|
|
501
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
502
|
+
const secs = Math.floor(seconds % 60);
|
|
503
|
+
const parts = [];
|
|
504
|
+
if (days > 0)
|
|
505
|
+
parts.push(`${days}d`);
|
|
506
|
+
if (hours > 0)
|
|
507
|
+
parts.push(`${hours}h`);
|
|
508
|
+
if (minutes > 0)
|
|
509
|
+
parts.push(`${minutes}m`);
|
|
510
|
+
parts.push(`${secs}s`);
|
|
511
|
+
return parts.join(' ');
|
|
512
|
+
}
|
|
513
|
+
return {
|
|
514
|
+
config,
|
|
515
|
+
trackRequest,
|
|
516
|
+
trackRequestComplete,
|
|
517
|
+
trackRateLimitEvent,
|
|
518
|
+
getMetricsSnapshot,
|
|
519
|
+
getChartData,
|
|
520
|
+
start,
|
|
521
|
+
stop,
|
|
522
|
+
initSocket,
|
|
523
|
+
formatUptime,
|
|
524
|
+
get io() { return io; }
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
//# sourceMappingURL=monitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monitor.js","sourceRoot":"","sources":["../src/monitor.ts"],"names":[],"mappings":"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"}
|