UNPKG

express-insights

Version:

Production-ready Express middleware for backend health monitoring with metrics, HTML/JSON output, authentication, and service checks.

363 lines (294 loc) 13.4 kB
# express-insights **Production-ready Express middleware for comprehensive backend health monitoring** Monitor your Express application's health with customizable JSON/HTML output, system metrics, service checks, authentication, rate limiting, and Prometheus integration. --- ## Table of Contents - [Features](#features) - [Installation](#installation) - [Quick Start](#quick-start) - [API Endpoints](#api-endpoints) - [Custom Service Checks](#custom-service-checks) - [Authentication & Rate Limiting](#authentication--rate-limiting) - [Frontend Integration](#frontend-integration) - [React Example](#react-example) - [Plain HTML + JS Example](#plain-html--js-example) - [Example Output](#example-output) - [HTML UI](#html-ui) - [JSON Response](#json-response) - [Prometheus Metrics](#prometheus-metrics) - [Options Reference](#options-reference) - [Error Handling & Troubleshooting](#error-handling--troubleshooting) - [License](#license) --- ## Features - Health check endpoint with JSON or HTML responses - 🧠 Smart resource monitoring with alerts for memory and CPU load - 🔍 Custom service checks (e.g., database, Redis, external APIs) - 📈 Prometheus-compatible metrics endpoint - 🔐 Optional authentication and rate limiting - 🌐 CORS support for cross-origin requests - 💾 Optional network and disk usage statistics - ⚙️ Configurable light/dark themes and auto-refresh for HTML output - 🧰 Plug-and-play middleware for Express.js applications - 📝 Detailed logging with Winston integration - 🕒 Caching for optimized performance --- ## Installation Install the package and its dependencies via npm: ```bash npm install express-insights express winston check-disk-space validator sanitize-html dotenv ``` Ensure you have Node.js version 14 or higher. The middleware depends on the following packages: - `express`: Web framework for Node.js - `winston`: Logging library - `check-disk-space`: Disk usage monitoring - `validator`: Input validation - `sanitize-html`: HTML sanitization - `dotenv`: Environment variable management --- ## Quick Start Set up the health check middleware in your Express application: ```javascript const express = require('express'); const { healthCheck } = require('express-insights'); const app = express(); // Configure the health check middleware healthCheck(app, { route: '/health', // Endpoint for health checks htmlResponse: true, // Enable HTML output style: 'dark', // Use dark theme for HTML message: 'My API Health', // Custom HTML header enableMetrics: true, // Enable metrics endpoints includeNetwork: true, // Include network interface stats includeDisk: true, // Include disk usage stats log: { level: 'info', // Log level: info, warn, error destination: 'console' // Log to console (or 'file' for file output) }, authentication: (auth) => auth === 'Bearer my-token' // Simple token-based auth }); app.listen(3000, () => console.log('Server running on http://localhost:3000')); ``` Access the health check at `http://localhost:3000/health` (JSON) or `http://localhost:3000/health?html=true` (HTML). --- ## API Endpoints | Endpoint | Description | |------------------------------|------------------------------------------| | `/health` | Main health check (JSON or HTML) | | `/health?html=true` | Forces HTML response | | `/health/metrics` | Internal request metrics (JSON) | | `/health/metrics/prometheus` | Prometheus-compatible metrics output | --- ## Custom Service Checks Add custom async checks for services like databases or external APIs: ```javascript const customDbCheck = { name: 'database', timeout: 3000, // Timeout in milliseconds retries: 2, // Number retries on failure check: async () => { const isAlive = await db.ping(); // Replace with your database ping logic if (!isAlive) throw new Error('Database unreachable'); return true; } }; healthCheck(app, { route: '/health', customChecks: [customDbCheck] }); ``` Service check results appear in the `services` object of the response. If all services are unhealthy, the overall status is `unhealthy`; if some are unhealthy, the status is `degraded`. --- ## Authentication & Rate Limiting Secure the endpoint with authentication and limit request rates: ```javascript healthCheck(app, { route: '/health', authentication: (token) => token === 'Bearer secret123', // Custom auth logic rateLimit: { windowMs: 10000, // 10-second window max: 5 // Max 5 requests per IP } }); ``` You can also use a static API key or environment variable: ```javascript healthCheck(app, { authentication: process.env.HEALTH_CHECK_TOKEN // e.g., 'secret123' }); ``` --- ## Frontend Integration Display health stats in a frontend application by fetching the `/health` endpoint. ### React Example ```jsx import { useEffect, useState } from 'react'; const HealthStatus = () => { const [status, setStatus] = useState(null); useEffect(() => { fetch('http://localhost:3000/health', { headers: { Authorization: 'Bearer my-token' } // Include if authentication is enabled }) .then((res) => res.json()) .then((data) => setStatus(data)) .catch((err) => console.error('Health check failed:', err)); }, []); if (!status) return <p>Loading health status...</p>; return ( <div style={{ padding: '20px', fontFamily: 'Arial' }}> <h2>🚦 Backend Health Status</h2> <p><strong>Status:</strong> {status.status}</p> <p><strong>Uptime:</strong> {status.uptime}</p> <p><strong>Memory Usage:</strong> {status.memory.heapUsed} ({status.memory.heapUsedPercent})</p> <p><strong>CPU Load (1min):</strong> {status.system?.loadavg?.['1min']}</p> <p><strong>Environment:</strong> {status.environment}</p> </div> ); }; export default HealthStatus; ``` ### Plain HTML + JS Example ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Backend Health</title> </head> <body> <h2>🚦 Backend Health</h2> <pre id="output">Loading...</pre> <script> fetch('http://localhost:3000/health', { headers: { Authorization: 'Bearer my-token' } // Include if authentication is enabled }) .then(res => res.json()) .then(data => { document.getElementById('output').textContent = JSON.stringify(data, null, 2); }) .catch(err => { document.getElementById('output').textContent = 'Health check failed: ' + err.message; }); </script> </body> </html> ``` --- ## Example Output ### HTML UI The HTML output provides a clean, responsive dashboard with system and service status. ![HTML Health Screenshot](https://raw.githubusercontent.com/yourusername/express-insights/main/assets/preview-dark.png) ### JSON Response ```json { "status": "healthy", "uptime": "2d 1h 22m 17s", "version": "1.0.0", "environment": "production", "memory": { "rss": "125.6 MB", "heapTotal": "120.3 MB", "heapUsed": "85.4 MB", "heapUsedPercent": "71.12%", "external": "2.1 MB", "arrayBuffers": "0.9 MB" }, "system": { "platform": "linux", "type": "Linux", "release": "5.15.0", "arch": "x64", "hostname": "server-01", "uptime": "15d 3h 45m 12s", "cpus": { "count": 4, "model": "Intel Xeon" }, "memory": { "total": "16 GB", "free": "4.2 GB", "used": "11.8 GB", "usedPercent": "73.75%", "alert": null }, "loadavg": { "1min": "0.33", "5min": "0.45", "15min": "0.50", "alert": null } }, "services": { "database": "healthy" } } ``` ### Prometheus Metrics Enable with `enableMetrics: true` to access `/health/metrics/prometheus`: ``` # HELP health_check_requests_total Total health check requests # TYPE health_check_requests_total counter health_check_requests_total 18 # HELP health_check_healthy_total Total healthy responses # TYPE health_check_healthy_total counter health_check_healthy_total 16 # HELP health_check_unhealthy_total Total unhealthy responses # TYPE health_check_unhealthy_total counter health_check_unhealthy_total 2 # HELP health_check_response_time_ms Average response time in ms # TYPE health_check_response_time_ms gauge health_check_response_time_ms 134.25 ``` --- ## Options Reference | Option | Type | Default | Description | |-----------------------|-------------------|------------------------------|-----------------------------------------------------------------------------| | `route` | `string` | `/health` | Path for the health check endpoint (must start with `/`) | | `htmlResponse` | `boolean` | `false` | Enable HTML output for the health endpoint | | `style` | `string` | `'light'` | Theme for HTML output: `'light'` or `'dark'` | | `message` | `string` | `'Backend Health Check'` | Custom header for HTML output | | `version` | `string` | `'1.0.0'` | Application version displayed in output | | `includeNetwork` | `boolean` | `false` | Include network interface details in stats | | `includeDisk` | `boolean` | `false` | Include disk usage stats (requires `check-disk-space`) | | `checks.database` | `boolean` | `false` | Enable built-in database check (placeholder; customize as needed) | | `customChecks` | `array` | `[]` | Array of custom service checks `{ name, check, timeout?, retries? }` | | `authentication` | `function|string` | `null` | Authentication logic or static API key (e.g., `'secret123'` or env var) | | `rateLimit` | `object` | `null` | Rate limiting: `{ windowMs: number, max: number }` | | `enableMetrics` | `boolean` | `false` | Enable `/metrics` and `/metrics/prometheus` endpoints | | `cors` | `boolean|object` | `false` | Enable CORS: `true` (all origins) or `{ allowedOrigins: string|string[] }` | | `cacheTTL` | `number` | `5000` | Cache duration for stats in milliseconds | | `timeout` | `number` | `5000` | Default timeout for service checks in milliseconds | | `retries` | `number` | `1` | Default retry count for failed service checks | | `autoRefreshInterval` | `number` | `30000` | Auto-refresh interval for HTML output lovingly in milliseconds | | `log.level` | `string` | `'info'` | Log level: `'info'`, `'warn'`, `'error'` | | `log.destination` | `string` | `'console'` | Log output: `'console'`, `'file'`, or provide `customLogger` | | `log.filePath` | `string` | `'./health-check.log'` | Path for file logging (if `destination: 'file'`) | | `resourceThresholds` | `object` | `{ memoryUsedPercent: 80, cpuLoad1Min: 2.0 }` | Thresholds for memory and CPU alerts | ### Example Options ```javascript healthCheck(app, { route: '/status', htmlResponse: true, style: 'dark', message: 'API Status Dashboard', version: '2.1.3', includeDisk: true, includeNetwork: true, cors: { allowedOrigins: ['https://myapp.com'] }, log: { level: 'warn', destination: 'file', filePath: 'logs/health.log' }, resourceThresholds: { memoryUsedPercent: 90, cpuLoad1Min: 1.5 } }); ``` --- ## Error Handling & Troubleshooting - **Authentication Errors (401)**: Ensure the correct token is sent in the `Authorization` header or `apiKey` query parameter. Check your `authentication` configuration. - **Rate Limit Errors (429)**: The client has exceeded the `rateLimit.max` within `rateLimit.windowMs`. Wait for the `Retry-After` duration. - **CORS Errors (403)**: Verify that the request's `Origin` header matches the `cors.allowedOrigins` list or set `cors: true` for all origins. - **Disk Usage Errors**: Ensure `check-disk-space` is installed and the disk path is accessible (e.g., `C:` on Windows, `/` on Unix). - **Service Check Failures**: Implement retry logic in custom checks and ensure the `check` function handles exceptions gracefully. - **Logging Issues**: Check the `log.filePath` for write permissions if using `destination: 'file'`. For detailed logs, set `log.level: 'info'` or use a custom Winston logger.