pms_md 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.
Files changed (55) hide show
  1. package/README.md +93 -0
  2. package/node-monitor/ARCHITECTURE.md +341 -0
  3. package/node-monitor/CHANGELOG.md +105 -0
  4. package/node-monitor/CONTRIBUTING.md +96 -0
  5. package/node-monitor/DESIGN_IMPROVEMENTS.md +286 -0
  6. package/node-monitor/FILTER_BUTTONS_FIX.md +303 -0
  7. package/node-monitor/GETTING_STARTED.md +416 -0
  8. package/node-monitor/INSTALLATION.md +470 -0
  9. package/node-monitor/LICENSE +22 -0
  10. package/node-monitor/PUBLISHING_GUIDE.md +331 -0
  11. package/node-monitor/QUICK_REFERENCE.md +252 -0
  12. package/node-monitor/README.md +458 -0
  13. package/node-monitor/READY_TO_PUBLISH.md +272 -0
  14. package/node-monitor/SETUP_GUIDE.md +479 -0
  15. package/node-monitor/examples/EMAIL_SETUP_GUIDE.md +282 -0
  16. package/node-monitor/examples/ERROR_LOGGING_GUIDE.md +405 -0
  17. package/node-monitor/examples/GET_APP_PASSWORD.md +145 -0
  18. package/node-monitor/examples/LOG_FILES_REFERENCE.md +336 -0
  19. package/node-monitor/examples/QUICK_START_EMAIL.md +126 -0
  20. package/node-monitor/examples/express-app.js +499 -0
  21. package/node-monitor/examples/package-lock.json +1295 -0
  22. package/node-monitor/examples/package.json +18 -0
  23. package/node-monitor/examples/public/css/style.css +718 -0
  24. package/node-monitor/examples/public/js/dashboard.js +207 -0
  25. package/node-monitor/examples/public/js/health.js +114 -0
  26. package/node-monitor/examples/public/js/main.js +89 -0
  27. package/node-monitor/examples/public/js/metrics.js +225 -0
  28. package/node-monitor/examples/public/js/theme.js +138 -0
  29. package/node-monitor/examples/views/dashboard.ejs +20 -0
  30. package/node-monitor/examples/views/error-logs.ejs +1129 -0
  31. package/node-monitor/examples/views/health.ejs +21 -0
  32. package/node-monitor/examples/views/home.ejs +341 -0
  33. package/node-monitor/examples/views/layout.ejs +50 -0
  34. package/node-monitor/examples/views/metrics.ejs +16 -0
  35. package/node-monitor/examples/views/partials/footer.ejs +16 -0
  36. package/node-monitor/examples/views/partials/header.ejs +35 -0
  37. package/node-monitor/examples/views/partials/nav.ejs +23 -0
  38. package/node-monitor/examples/views/status.ejs +390 -0
  39. package/node-monitor/package-lock.json +4300 -0
  40. package/node-monitor/package.json +76 -0
  41. package/node-monitor/pre-publish-check.js +200 -0
  42. package/node-monitor/src/config/monitoringConfig.js +255 -0
  43. package/node-monitor/src/index.js +300 -0
  44. package/node-monitor/src/logger/errorLogger.js +297 -0
  45. package/node-monitor/src/monitors/apiErrorMonitor.js +156 -0
  46. package/node-monitor/src/monitors/dbConnectionMonitor.js +389 -0
  47. package/node-monitor/src/monitors/serverHealthMonitor.js +320 -0
  48. package/node-monitor/src/monitors/systemResourceMonitor.js +357 -0
  49. package/node-monitor/src/notifiers/emailNotifier.js +248 -0
  50. package/node-monitor/src/notifiers/notificationManager.js +96 -0
  51. package/node-monitor/src/notifiers/slackNotifier.js +209 -0
  52. package/node-monitor/src/views/dashboard.html +530 -0
  53. package/node-monitor/src/views/health.html +399 -0
  54. package/node-monitor/src/views/metrics.html +406 -0
  55. package/package.json +22 -0
@@ -0,0 +1,499 @@
1
+ /**
2
+ * Example Express Application with Node Monitor
3
+ * Demonstrates how to integrate the monitoring package
4
+ */
5
+
6
+ // Load environment variables
7
+ require('dotenv').config();
8
+
9
+ const express = require('express');
10
+ const path = require('path');
11
+ const NodeMonitor = require('../src/index');
12
+
13
+ // Initialize the monitor with custom configuration
14
+ const monitor = new NodeMonitor({
15
+ app: {
16
+ name: 'Example Express App',
17
+ version: '1.0.0',
18
+ environment: process.env.NODE_ENV || 'development'
19
+ },
20
+
21
+ intervals: {
22
+ health: 30000, // Check health every 30 seconds
23
+ system: 60000, // Check system resources every minute
24
+ database: 60000 // Check database every minute
25
+ },
26
+
27
+ thresholds: {
28
+ cpu: 75, // Alert if CPU > 75%
29
+ memory: 85, // Alert if memory > 85%
30
+ errorRate: 10, // Alert if > 10 errors per minute
31
+ responseTime: 3000, // Alert if response time > 3 seconds
32
+ consecutiveFailures: 2
33
+ },
34
+
35
+ notifications: {
36
+ enabled: true,
37
+ cooldown: 180000, // 3 minutes between alerts
38
+
39
+ email: {
40
+ enabled: true,
41
+ host: 'smtp.gmail.com',
42
+ port: 587,
43
+ secure: false,
44
+ auth: {
45
+ user: 'manish.proses@gmail.com',
46
+ pass: process.env.EMAIL_APP_PASSWORD || 'your-app-password-here'
47
+ },
48
+ from: 'manish.proses@gmail.com',
49
+ recipients: ['manish.proses@gmail.com']
50
+ },
51
+
52
+ slack: {
53
+ enabled: false, // Set to true and configure to enable
54
+ // webhook: 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL',
55
+ // channel: '#monitoring'
56
+ }
57
+ },
58
+
59
+ logging: {
60
+ enabled: true,
61
+ level: 'info',
62
+ directory: './logs',
63
+ console: true
64
+ }
65
+ });
66
+
67
+ // Create Express app
68
+ const app = express();
69
+ const PORT = process.env.PORT || 3001;
70
+
71
+ // ============================================
72
+ // SETUP VIEW ENGINE (EJS)
73
+ // ============================================
74
+ app.set('view engine', 'ejs');
75
+ app.set('views', path.join(__dirname, 'views'));
76
+
77
+ // Serve static files (CSS, JS, images)
78
+ app.use(express.static(path.join(__dirname, 'public')));
79
+
80
+ // Middleware
81
+ app.use(express.json());
82
+ app.use(express.urlencoded({ extended: true }));
83
+
84
+ // Add request logger (optional - logs slow requests)
85
+ app.use(monitor.requestLogger());
86
+
87
+ // ============================================
88
+ // MONITORING ENDPOINTS
89
+ // ============================================
90
+
91
+ // Health check endpoint (HTML or JSON)
92
+ app.get('/health', (req, res) => {
93
+ const acceptsJson = req.headers.accept && req.headers.accept.includes('application/json');
94
+ const isApiRequest = req.query.format === 'json' || acceptsJson;
95
+
96
+ if (!isApiRequest) {
97
+ // Default to HTML for browser requests
98
+ return res.render('health', {
99
+ title: 'Health Check',
100
+ headerIcon: 'šŸ’š',
101
+ headerTitle: 'Health Check',
102
+ subtitle: 'System health status and monitoring',
103
+ currentPage: 'health',
104
+ includeCharts: false,
105
+ pageScript: 'health.js'
106
+ });
107
+ }
108
+
109
+ // Return JSON for API requests
110
+ monitor.healthCheckEndpoint()(req, res);
111
+ });
112
+
113
+ // Basic health info
114
+ app.get('/health/info', monitor.healthInfoEndpoint());
115
+
116
+ // Monitoring dashboard (HTML or JSON)
117
+ app.get('/monitor/dashboard', (req, res) => {
118
+ const acceptsJson = req.headers.accept && req.headers.accept.includes('application/json');
119
+ const isApiRequest = req.query.format === 'json' || acceptsJson;
120
+
121
+ if (!isApiRequest) {
122
+ // Default to HTML for browser requests
123
+ return res.render('dashboard', {
124
+ title: 'Dashboard',
125
+ headerIcon: 'šŸ“Š',
126
+ headerTitle: 'Monitoring Dashboard',
127
+ subtitle: 'Real-time application monitoring and analytics',
128
+ currentPage: 'dashboard',
129
+ includeCharts: false,
130
+ pageScript: 'dashboard.js'
131
+ });
132
+ }
133
+
134
+ // Return JSON for API requests
135
+ monitor.dashboardEndpoint()(req, res);
136
+ });
137
+
138
+ // Get current monitoring status
139
+ // Get status (HTML or JSON)
140
+ app.get('/monitor/status', (req, res) => {
141
+ const acceptsJson = req.headers.accept && req.headers.accept.includes('application/json');
142
+ const isApiRequest = req.query.format === 'json' || acceptsJson;
143
+
144
+ if (!isApiRequest) {
145
+ // Default to HTML for browser requests
146
+ return res.render('status', {
147
+ title: 'API Status',
148
+ headerIcon: 'šŸ“‹',
149
+ headerTitle: 'API Status',
150
+ subtitle: 'Real-time application status and metrics',
151
+ currentPage: 'status'
152
+ });
153
+ }
154
+
155
+ // Return JSON for API requests
156
+ res.json(monitor.getStatus());
157
+ });
158
+
159
+ // Get system information
160
+ app.get('/monitor/system', (req, res) => {
161
+ res.json(monitor.getSystemInfo());
162
+ });
163
+
164
+ // Get metrics history (HTML or JSON)
165
+ app.get('/monitor/metrics', (req, res) => {
166
+ const acceptsJson = req.headers.accept && req.headers.accept.includes('application/json');
167
+ const isApiRequest = req.query.format === 'json' || acceptsJson;
168
+
169
+ if (!isApiRequest) {
170
+ // Default to HTML for browser requests
171
+ return res.render('metrics', {
172
+ title: 'Metrics',
173
+ headerIcon: 'šŸ“ˆ',
174
+ headerTitle: 'System Metrics',
175
+ subtitle: 'Performance monitoring and analytics',
176
+ currentPage: 'metrics',
177
+ includeCharts: true,
178
+ pageScript: 'metrics.js'
179
+ });
180
+ }
181
+
182
+ // Return JSON for API requests
183
+ res.json({
184
+ timestamp: new Date().toISOString(),
185
+ history: monitor.getMetricsHistory()
186
+ });
187
+ });
188
+
189
+ // ============================================
190
+ // EXAMPLE APPLICATION ROUTES
191
+ // ============================================
192
+
193
+ // Home route
194
+ app.get('/', (req, res) => {
195
+ const acceptsJson = req.headers.accept && req.headers.accept.includes('application/json');
196
+ const isApiRequest = req.query.format === 'json' || acceptsJson;
197
+
198
+ if (!isApiRequest) {
199
+ // Default to HTML for browser requests
200
+ return res.render('home', {
201
+ title: 'Home',
202
+ headerIcon: 'šŸ ',
203
+ headerTitle: 'Node Monitor',
204
+ subtitle: null,
205
+ currentPage: 'home',
206
+ includeCharts: false,
207
+ pageScript: null
208
+ });
209
+ }
210
+
211
+ // Return JSON for API clients
212
+ res.json({
213
+ message: 'Welcome to Node Monitor Example App',
214
+ endpoints: {
215
+ home: '/',
216
+ health: '/health',
217
+ healthInfo: '/health/info',
218
+ dashboard: '/monitor/dashboard',
219
+ status: '/monitor/status',
220
+ system: '/monitor/system',
221
+ metrics: '/monitor/metrics',
222
+ examples: {
223
+ success: '/api/success',
224
+ error: '/api/error',
225
+ slow: '/api/slow',
226
+ customNotification: '/api/notify'
227
+ }
228
+ }
229
+ });
230
+ });
231
+
232
+ // Remove the old inline HTML (keeping this comment for reference)
233
+ /*
234
+ // Old home route with inline HTML - now replaced with EJS
235
+ app.get('/', (req, res) => {
236
+ const acceptsHtml = req.headers.accept && req.headers.accept.includes('text/html');
237
+
238
+ if (acceptsHtml) {
239
+ // Serve HTML landing page
240
+ res.send(`
241
+ */
242
+
243
+ // Success endpoint
244
+ app.get('/api/success', (req, res) => {
245
+ monitor.logInfo('Success endpoint called');
246
+ res.json({ message: 'Success!' });
247
+ });
248
+
249
+ // Error endpoint (demonstrates error tracking)
250
+ app.get('/api/error', (req, res, next) => {
251
+ const error = NodeMonitor.createError('This is a test error', 500, {
252
+ testData: 'example'
253
+ });
254
+ next(error);
255
+ });
256
+
257
+ // Slow endpoint (demonstrates slow request tracking)
258
+ app.get('/api/slow', monitor.asyncHandler(async (req, res) => {
259
+ // Simulate slow operation
260
+ await new Promise(resolve => setTimeout(resolve, 4000));
261
+ res.json({ message: 'This was a slow request' });
262
+ }));
263
+
264
+ // Test notification endpoint (GET request for easy testing)
265
+ app.get('/api/notify-test', monitor.asyncHandler(async (req, res) => {
266
+ const result = await monitor.notify(
267
+ 'info',
268
+ 'Test Notification',
269
+ 'This is a test email notification from Node Monitor. If you received this, your email configuration is working correctly!',
270
+ {
271
+ testTime: new Date().toISOString(),
272
+ recipient: 'manish.proses@gmail.com',
273
+ status: 'Email configuration is working! āœ…'
274
+ }
275
+ );
276
+
277
+ res.json({
278
+ message: 'Test notification sent!',
279
+ result,
280
+ instructions: 'Check your email inbox at manish.proses@gmail.com'
281
+ });
282
+ }));
283
+
284
+ // Custom notification endpoint (POST)
285
+ app.post('/api/notify', monitor.asyncHandler(async (req, res) => {
286
+ const { level, subject, message, details } = req.body;
287
+
288
+ const result = await monitor.notify(
289
+ level || 'info',
290
+ subject || 'Test Notification',
291
+ message || 'This is a test notification',
292
+ details || {}
293
+ );
294
+
295
+ res.json({
296
+ message: 'Notification sent',
297
+ result
298
+ });
299
+ }));
300
+
301
+ // Error logs viewer endpoint
302
+ app.get('/monitor/error-logs', monitor.asyncHandler(async (req, res) => {
303
+ const fs = require('fs');
304
+ const path = require('path');
305
+
306
+ const logsDir = path.join(__dirname, 'logs');
307
+ const { date, format } = req.query;
308
+
309
+ try {
310
+ // Ensure logs directory exists
311
+ if (!fs.existsSync(logsDir)) {
312
+ fs.mkdirSync(logsDir, { recursive: true });
313
+ }
314
+
315
+ // Get list of error log files
316
+ const files = fs.readdirSync(logsDir)
317
+ .filter(f => f.startsWith('error-') && f.endsWith('.log'))
318
+ .sort()
319
+ .reverse();
320
+
321
+ if (format === 'json') {
322
+ // Return list of available log files
323
+ const logFiles = files.map(f => {
324
+ const stats = fs.statSync(path.join(logsDir, f));
325
+ return {
326
+ filename: f,
327
+ date: f.replace('error-', '').replace('.log', ''),
328
+ size: stats.size,
329
+ modified: stats.mtime
330
+ };
331
+ });
332
+
333
+ return res.json({ files: logFiles });
334
+ }
335
+
336
+ // Render HTML view
337
+ res.render('error-logs', {
338
+ title: 'API Error Logs',
339
+ headerIcon: 'šŸ“‹',
340
+ headerTitle: 'API Error Logs',
341
+ subtitle: 'View and analyze API errors',
342
+ currentPage: 'error-logs',
343
+ files: files.length > 0 ? files : []
344
+ });
345
+ } catch (error) {
346
+ res.status(500).json({ error: error.message });
347
+ }
348
+ }));
349
+
350
+ // Get specific error log file content
351
+ app.get('/monitor/error-logs/:filename', monitor.asyncHandler(async (req, res) => {
352
+ const fs = require('fs');
353
+ const path = require('path');
354
+ const { filename } = req.params;
355
+ const { format, limit = 100 } = req.query;
356
+
357
+ // Security: only allow error log files
358
+ if (!filename.startsWith('error-') || !filename.endsWith('.log')) {
359
+ return res.status(400).json({ error: 'Invalid log file' });
360
+ }
361
+
362
+ const logPath = path.join(__dirname, 'logs', filename);
363
+
364
+ if (!fs.existsSync(logPath)) {
365
+ return res.status(404).json({ error: 'Log file not found' });
366
+ }
367
+
368
+ try {
369
+ const content = fs.readFileSync(logPath, 'utf8');
370
+ const lines = content.trim().split('\n').filter(line => line.trim());
371
+
372
+ // Parse JSON logs
373
+ const errors = lines
374
+ .map((line, index) => {
375
+ try {
376
+ return JSON.parse(line);
377
+ } catch (e) {
378
+ return null;
379
+ }
380
+ })
381
+ .filter(e => e !== null)
382
+ .reverse() // Most recent first
383
+ .slice(0, parseInt(limit));
384
+
385
+ if (format === 'json') {
386
+ return res.json({
387
+ filename,
388
+ total: lines.length,
389
+ errors
390
+ });
391
+ }
392
+
393
+ // Return raw content for download
394
+ res.setHeader('Content-Type', 'application/json');
395
+ res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
396
+ res.send(content);
397
+ } catch (error) {
398
+ res.status(500).json({ error: error.message });
399
+ }
400
+ }));
401
+
402
+ // Async error example
403
+ app.get('/api/async-error', monitor.asyncHandler(async (req, res) => {
404
+ // This error will be caught by asyncHandler
405
+ throw new Error('Async operation failed');
406
+ }));
407
+
408
+ // Database simulation endpoint
409
+ app.get('/api/db-test', monitor.asyncHandler(async (req, res) => {
410
+ // In a real app, you would query your database here
411
+ monitor.logInfo('Database query simulated');
412
+ res.json({ message: 'Database query successful' });
413
+ }));
414
+
415
+ // ============================================
416
+ // CUSTOM HEALTH CHECKS
417
+ // ============================================
418
+
419
+ // Register custom health check
420
+ monitor.registerHealthCheck('api-responsive', async () => {
421
+ // Check if API is responsive
422
+ return true; // Return true if healthy, false if not
423
+ });
424
+
425
+ monitor.registerHealthCheck('external-service', async () => {
426
+ // Example: Check external service availability
427
+ try {
428
+ // const response = await axios.get('https://api.example.com/health');
429
+ // return response.status === 200;
430
+ return true;
431
+ } catch {
432
+ return false;
433
+ }
434
+ });
435
+
436
+ // ============================================
437
+ // DATABASE MONITORING (EXAMPLE)
438
+ // ============================================
439
+
440
+ // Uncomment and configure based on your database
441
+
442
+ // MongoDB/Mongoose example:
443
+ // const mongoose = require('mongoose');
444
+ // mongoose.connect('mongodb://localhost:27017/myapp');
445
+ // monitor.registerDatabase('mongodb', 'mongoose', mongoose.connection);
446
+
447
+ // PostgreSQL example:
448
+ // const { Pool } = require('pg');
449
+ // const pgPool = new Pool({ connectionString: 'postgresql://...' });
450
+ // monitor.registerDatabase('postgres', 'postgresql', pgPool);
451
+
452
+ // MySQL example:
453
+ // const mysql = require('mysql2/promise');
454
+ // const mysqlPool = mysql.createPool({ host: 'localhost', user: 'root', database: 'myapp' });
455
+ // monitor.registerDatabase('mysql', 'mysql', mysqlPool);
456
+
457
+ // Redis example:
458
+ // const Redis = require('ioredis');
459
+ // const redis = new Redis();
460
+ // monitor.registerDatabase('redis', 'redis', redis);
461
+
462
+ // ============================================
463
+ // ERROR HANDLING
464
+ // ============================================
465
+
466
+ // 404 handler (must be after all routes)
467
+ app.use(monitor.notFoundHandler());
468
+
469
+ // Error handler (must be last)
470
+ app.use(monitor.errorMiddleware());
471
+
472
+ // ============================================
473
+ // START SERVER
474
+ // ============================================
475
+
476
+ const server = app.listen(PORT, () => {
477
+ console.log(`\nšŸš€ Server running on http://localhost:${PORT}`);
478
+ console.log(`šŸ“Š Health check: http://localhost:${PORT}/health`);
479
+ console.log(`šŸ“ˆ Dashboard: http://localhost:${PORT}/monitor/dashboard`);
480
+ console.log(`\nāœ… Node Monitor is active and monitoring your application\n`);
481
+
482
+ // Start monitoring services
483
+ monitor.start();
484
+
485
+ // Setup graceful shutdown
486
+ monitor.setupGracefulShutdown(server);
487
+ });
488
+
489
+ // Handle server errors
490
+ server.on('error', (error) => {
491
+ monitor.logError('server_error', 'Server error occurred', {
492
+ error: error.message,
493
+ code: error.code
494
+ });
495
+ });
496
+
497
+ // Export for testing
498
+ module.exports = { app, monitor, server };
499
+