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
Markdown
# 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.

### 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.