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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Vinit Kumar Goel
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# hono-status-monitor
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/hono-status-monitor)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
Real-time server monitoring dashboard for **Hono.js** applications with WebSocket updates. Express-status-monitor style metrics powered by Socket.io.
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
## ✨ Features
|
|
11
|
+
|
|
12
|
+
| Feature | Description |
|
|
13
|
+
|---------|-------------|
|
|
14
|
+
| **7 Real-Time Metrics** | CPU, Memory, Heap, Load Average, Response Time, RPS, Event Loop Lag |
|
|
15
|
+
| **Response Percentiles** | P50, P95, P99 latency tracking for accurate performance insights |
|
|
16
|
+
| **Route Analytics** | Top routes by traffic, slowest routes, routes with most errors |
|
|
17
|
+
| **Error Tracking** | Recent errors with timestamps, paths, and status codes |
|
|
18
|
+
| **Visual Alerts** | Automatic warnings when CPU >80%, Memory >90%, Response >500ms |
|
|
19
|
+
| **Dark Mode** | Toggle with localStorage persistence |
|
|
20
|
+
| **WebSocket Updates** | Real-time updates via Socket.io (1 second interval) |
|
|
21
|
+
| **Pluggable Health Checks** | Optional database/service health monitoring |
|
|
22
|
+
| **Configurable** | Custom thresholds, paths, titles, and more |
|
|
23
|
+
|
|
24
|
+
## 📦 Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install hono-status-monitor
|
|
28
|
+
# or
|
|
29
|
+
yarn add hono-status-monitor
|
|
30
|
+
# or
|
|
31
|
+
pnpm add hono-status-monitor
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 🚀 Quick Start
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { Hono } from 'hono';
|
|
38
|
+
import { serve } from '@hono/node-server';
|
|
39
|
+
import { statusMonitor } from 'hono-status-monitor';
|
|
40
|
+
|
|
41
|
+
const app = new Hono();
|
|
42
|
+
|
|
43
|
+
// Create status monitor
|
|
44
|
+
const monitor = statusMonitor();
|
|
45
|
+
|
|
46
|
+
// Add middleware to track ALL requests (must be first!)
|
|
47
|
+
app.use('*', monitor.middleware);
|
|
48
|
+
|
|
49
|
+
// Mount status dashboard at /status
|
|
50
|
+
app.route('/status', monitor.routes);
|
|
51
|
+
|
|
52
|
+
// Your routes
|
|
53
|
+
app.get('/', (c) => c.text('Hello World!'));
|
|
54
|
+
|
|
55
|
+
// Start server
|
|
56
|
+
const server = serve({ fetch: app.fetch, port: 3000 });
|
|
57
|
+
|
|
58
|
+
// Initialize WebSocket for real-time updates
|
|
59
|
+
monitor.initSocket(server);
|
|
60
|
+
|
|
61
|
+
console.log('📊 Status monitor: http://localhost:3000/status');
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## ⚙️ Configuration
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
const monitor = statusMonitor({
|
|
68
|
+
// Dashboard path (default: '/status')
|
|
69
|
+
path: '/status',
|
|
70
|
+
|
|
71
|
+
// Dashboard title (default: 'Server Status')
|
|
72
|
+
title: 'My App Status',
|
|
73
|
+
|
|
74
|
+
// Socket.io path (default: '/status/socket.io')
|
|
75
|
+
socketPath: '/status/socket.io',
|
|
76
|
+
|
|
77
|
+
// Metrics update interval in ms (default: 1000)
|
|
78
|
+
updateInterval: 1000,
|
|
79
|
+
|
|
80
|
+
// History retention in seconds (default: 60)
|
|
81
|
+
retentionSeconds: 60,
|
|
82
|
+
|
|
83
|
+
// Max recent errors to store (default: 10)
|
|
84
|
+
maxRecentErrors: 10,
|
|
85
|
+
|
|
86
|
+
// Max routes to show in analytics (default: 10)
|
|
87
|
+
maxRoutes: 10,
|
|
88
|
+
|
|
89
|
+
// Alert thresholds
|
|
90
|
+
alerts: {
|
|
91
|
+
cpu: 80, // CPU percentage
|
|
92
|
+
memory: 90, // Memory percentage
|
|
93
|
+
responseTime: 500, // Response time in ms
|
|
94
|
+
errorRate: 5, // Error rate percentage
|
|
95
|
+
eventLoopLag: 100 // Event loop lag in ms
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
// Custom database health check (optional)
|
|
99
|
+
healthCheck: async () => {
|
|
100
|
+
const start = performance.now();
|
|
101
|
+
await mongoose.connection.db?.admin().ping();
|
|
102
|
+
return {
|
|
103
|
+
connected: mongoose.connection.readyState === 1,
|
|
104
|
+
latencyMs: performance.now() - start,
|
|
105
|
+
name: 'MongoDB'
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
// Custom path normalization (optional)
|
|
110
|
+
normalizePath: (path) => {
|
|
111
|
+
return path
|
|
112
|
+
.replace(/\/users\/\d+/g, '/users/:id')
|
|
113
|
+
.replace(/\/posts\/[a-f0-9]{24}/g, '/posts/:id');
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## 📊 Dashboard Sections
|
|
119
|
+
|
|
120
|
+
### Header
|
|
121
|
+
- Server hostname
|
|
122
|
+
- Connection status (Live/Offline)
|
|
123
|
+
- Dark mode toggle
|
|
124
|
+
|
|
125
|
+
### Stats Bar
|
|
126
|
+
- Uptime
|
|
127
|
+
- Total requests
|
|
128
|
+
- Active connections
|
|
129
|
+
- Error rate
|
|
130
|
+
|
|
131
|
+
### Response Percentiles
|
|
132
|
+
- Average response time
|
|
133
|
+
- P50 (median)
|
|
134
|
+
- P95
|
|
135
|
+
- P99
|
|
136
|
+
|
|
137
|
+
### Real-Time Charts
|
|
138
|
+
- CPU usage
|
|
139
|
+
- Memory usage (MB)
|
|
140
|
+
- Heap usage (MB)
|
|
141
|
+
- Load average
|
|
142
|
+
- Response time (ms)
|
|
143
|
+
- Requests per second
|
|
144
|
+
- Event loop lag (ms)
|
|
145
|
+
|
|
146
|
+
### Route Analytics
|
|
147
|
+
- 🔥 Top Routes (by request count)
|
|
148
|
+
- 🐢 Slowest Routes (by avg response time)
|
|
149
|
+
|
|
150
|
+
### HTTP Status Codes
|
|
151
|
+
- 2xx success count
|
|
152
|
+
- 3xx redirect count
|
|
153
|
+
- 4xx client error count
|
|
154
|
+
- 5xx server error count
|
|
155
|
+
- Rate limited count
|
|
156
|
+
|
|
157
|
+
### Recent Errors
|
|
158
|
+
- Last 10 errors with timestamp, path, and status code
|
|
159
|
+
|
|
160
|
+
### Health Checks
|
|
161
|
+
- Database connection status and latency
|
|
162
|
+
- Heap total and growth rate
|
|
163
|
+
|
|
164
|
+
### Process Info
|
|
165
|
+
- Node.js version
|
|
166
|
+
- Platform
|
|
167
|
+
- PID
|
|
168
|
+
- CPU count
|
|
169
|
+
|
|
170
|
+
## 🔌 API Endpoints
|
|
171
|
+
|
|
172
|
+
| Endpoint | Description |
|
|
173
|
+
|----------|-------------|
|
|
174
|
+
| `GET /status` | Dashboard HTML page |
|
|
175
|
+
| `GET /status/api/metrics` | JSON API with full metrics snapshot |
|
|
176
|
+
|
|
177
|
+
### JSON API Response
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"snapshot": {
|
|
182
|
+
"timestamp": 1704067200000,
|
|
183
|
+
"cpu": 12.5,
|
|
184
|
+
"memoryMB": 256.4,
|
|
185
|
+
"memoryPercent": 15.8,
|
|
186
|
+
"heapUsedMB": 48.2,
|
|
187
|
+
"heapTotalMB": 64.0,
|
|
188
|
+
"loadAvg": 1.25,
|
|
189
|
+
"uptime": 86400,
|
|
190
|
+
"processUptime": 3600,
|
|
191
|
+
"responseTime": 15.4,
|
|
192
|
+
"rps": 125,
|
|
193
|
+
"totalRequests": 450000,
|
|
194
|
+
"activeConnections": 42,
|
|
195
|
+
"eventLoopLag": 2.1,
|
|
196
|
+
"percentiles": {
|
|
197
|
+
"avg": 15.4,
|
|
198
|
+
"p50": 12.0,
|
|
199
|
+
"p95": 45.0,
|
|
200
|
+
"p99": 120.0
|
|
201
|
+
},
|
|
202
|
+
"topRoutes": [...],
|
|
203
|
+
"slowestRoutes": [...],
|
|
204
|
+
"recentErrors": [...],
|
|
205
|
+
"alerts": {
|
|
206
|
+
"cpu": false,
|
|
207
|
+
"memory": false,
|
|
208
|
+
"responseTime": false,
|
|
209
|
+
"errorRate": false,
|
|
210
|
+
"eventLoopLag": false
|
|
211
|
+
},
|
|
212
|
+
"database": {
|
|
213
|
+
"connected": true,
|
|
214
|
+
"latencyMs": 1.2
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
"charts": {
|
|
218
|
+
"cpu": [{ "timestamp": 1704067200000, "value": 12.5 }, ...],
|
|
219
|
+
"memory": [...],
|
|
220
|
+
"heap": [...],
|
|
221
|
+
"loadAvg": [...],
|
|
222
|
+
"responseTime": [...],
|
|
223
|
+
"rps": [...],
|
|
224
|
+
"eventLoopLag": [...],
|
|
225
|
+
"errorRate": [...]
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## 🎛️ Advanced Usage
|
|
231
|
+
|
|
232
|
+
### Rate Limit Tracking
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
// In your rate limiter middleware
|
|
236
|
+
import { monitor } from './your-app';
|
|
237
|
+
|
|
238
|
+
if (isRateLimited) {
|
|
239
|
+
monitor.trackRateLimit(true); // Track blocked request
|
|
240
|
+
return c.text('Too many requests', 429);
|
|
241
|
+
}
|
|
242
|
+
monitor.trackRateLimit(false); // Track allowed request
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Custom Path Normalization
|
|
246
|
+
|
|
247
|
+
Group similar routes for meaningful analytics:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
const monitor = statusMonitor({
|
|
251
|
+
normalizePath: (path) => {
|
|
252
|
+
return path
|
|
253
|
+
// Replace user IDs
|
|
254
|
+
.replace(/\/users\/\d+/g, '/users/:id')
|
|
255
|
+
// Replace MongoDB ObjectIds
|
|
256
|
+
.replace(/\/[a-f0-9]{24}/g, '/:id')
|
|
257
|
+
// Replace UUIDs
|
|
258
|
+
.replace(/\/[0-9a-f-]{36}/g, '/:uuid');
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Multiple Health Checks
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
const monitor = statusMonitor({
|
|
267
|
+
healthCheck: async () => {
|
|
268
|
+
const dbStart = performance.now();
|
|
269
|
+
const dbConnected = mongoose.connection.readyState === 1;
|
|
270
|
+
|
|
271
|
+
if (dbConnected) {
|
|
272
|
+
await mongoose.connection.db?.admin().ping();
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return {
|
|
276
|
+
connected: dbConnected,
|
|
277
|
+
latencyMs: performance.now() - dbStart,
|
|
278
|
+
name: 'MongoDB'
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## 🛡️ Security Considerations
|
|
285
|
+
|
|
286
|
+
The status dashboard exposes server metrics. Consider:
|
|
287
|
+
|
|
288
|
+
1. **Authentication**: Add middleware to protect the `/status` route
|
|
289
|
+
2. **Rate Limiting**: Limit access to the dashboard
|
|
290
|
+
3. **Internal Only**: Only expose on internal networks
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
import { basicAuth } from 'hono/basic-auth';
|
|
294
|
+
|
|
295
|
+
// Protect status routes
|
|
296
|
+
app.use('/status/*', basicAuth({
|
|
297
|
+
username: 'admin',
|
|
298
|
+
password: process.env.STATUS_PASSWORD!
|
|
299
|
+
}));
|
|
300
|
+
|
|
301
|
+
app.route('/status', monitor.routes);
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## 📋 Requirements
|
|
305
|
+
|
|
306
|
+
- Node.js >= 18.0.0
|
|
307
|
+
- Hono.js >= 4.0.0
|
|
308
|
+
- @hono/node-server >= 1.0.0
|
|
309
|
+
|
|
310
|
+
## 🤝 Contributing
|
|
311
|
+
|
|
312
|
+
Contributions welcome! Please read the [contributing guidelines](CONTRIBUTING.md) first.
|
|
313
|
+
|
|
314
|
+
## 📄 License
|
|
315
|
+
|
|
316
|
+
MIT © [Vinit Kumar Goel](https://github.com/vinitkumargoel)
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
Made with ❤️ for the Hono.js community
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,cAAc,GAAG,MAAM,CA6bjG"}
|