HTTP Metrics Middleware
http-metrics-middleware is an Express.js middleware designed to integrate Prometheus metrics into Node.js applications, currently stable at version 2.2.1. It provides a convenient wrapper around `prom-client`, offering a set of default HTTP request metrics such as duration histograms and summaries, as well as status code counts. The library maintains a regular release cadence, primarily driven by dependency updates, security patches, and minor enhancements. Key differentiators include its configurable options for metric labels, such as normalized URL paths, and custom time/quantile buckets, allowing fine-grained control over the collected data. While primarily built for Express, it can be seamlessly integrated into Koa applications using `koa-connect`. It focuses on providing a robust, opinionated solution for common HTTP metrics without requiring extensive manual setup of individual `prom-client` metrics.
Common errors
-
ReferenceError: MetricsMiddleware is not defined
cause Attempting to import the `MetricsMiddleware` class using ESM `import` syntax (`import { MetricsMiddleware } from 'http-metrics-middleware'`) in a CommonJS module.fixUse the CommonJS `require` syntax: `const MetricsMiddleware = require('http-metrics-middleware')`. -
GET /metrics 404 Not Found
cause The middleware responsible for exposing the Prometheus metrics endpoint was not properly initialized or added to the Express application.fixEnsure you have called `app.use(metrics.initRoutes())` after creating an instance of `MetricsMiddleware`. -
Error: A metric with the name http_request_duration_seconds has already been registered.
cause Attempting to create a custom `prom-client` metric with a name that conflicts with one of the default metrics provided by `http-metrics-middleware`.fixEither disable the conflicting default metric via `http-metrics-middleware` options (e.g., `enableDurationHistogram: false`) or choose a unique name for your custom metric. -
Prometheus scrape endpoint returns an empty response or only default Node.js metrics.
cause The middleware is active but no HTTP requests are being made to your Express application, or the middleware is placed too late in the Express middleware chain to capture requests.fixEnsure requests are hitting your application. Place `app.use(metrics.initRoutes())` early in your middleware chain, preferably before any routes that you want to measure. Custom metrics will only appear if their `inc()` or `observe()` methods are called.
Warnings
- breaking Version 1.2.0 and subsequent versions of `http-metrics-middleware` require Node.js v10 or above. Older Node.js environments will not be supported.
- gotcha Enabling the `includePath` option can lead to high cardinality in your Prometheus metrics if your application has dynamic URL paths with many unique values. This can drastically increase memory usage and storage requirements for Prometheus.
- breaking Updates to underlying dependencies like `express` (v4.21.2 in v2.2.0, v4.19.2 in v2.1.4) and `prom-client` (v13.1.0 in v2.1.2, latest in v2.1.5) may introduce breaking changes from those libraries. Review their respective changelogs.
- breaking In version 2.1.5, the archived dev-dependency `@after-work.js/aw` was removed and replaced by `mocha` as part of a CVE fix. While primarily a dev dependency, be aware of changes in the test runner if you integrate with internal testing utilities.
Install
-
npm install http-metrics-middleware -
yarn add http-metrics-middleware -
pnpm add http-metrics-middleware
Imports
- MetricsMiddleware
import { MetricsMiddleware } from 'http-metrics-middleware'const MetricsMiddleware = require('http-metrics-middleware') - promClient
const promClient = require('http-metrics-middleware').promClient - initRoutes
app.use(metrics.initRoutes)
app.use(metrics.initRoutes())
Quickstart
const express = require('express');
const MetricsMiddleware = require('http-metrics-middleware');
const promClient = require('http-metrics-middleware').promClient;
const app = express();
const port = 3000;
// Initialize the middleware with custom options
const metrics = new MetricsMiddleware({
metricsPath: '/app-metrics', // Custom path for metrics endpoint
includePath: true, // Include path label (use with caution for high cardinality)
timeBuckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 2], // More granular buckets
});
// Use the middleware to expose the metrics endpoint
app.use(metrics.initRoutes());
// Example custom metric using the exposed promClient
const myCustomCounter = new promClient.Counter({
name: 'my_app_custom_operations_total',
help: 'Total number of custom operations',
labelNames: ['operation_type'],
});
// Sample API route to increment custom metric
app.get('/api/data', (req, res) => {
myCustomCounter.inc({ operation_type: 'read' });
res.status(200).json({ message: 'Data fetched successfully' });
});
app.post('/api/data', (req, res) => {
myCustomCounter.inc({ operation_type: 'write' });
res.status(201).json({ message: 'Data created successfully' });
});
// Root route
app.get('/', (req, res) => {
res.send('Hello from http-metrics-middleware example!');
});
app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`);
console.log(`Prometheus metrics available at http://localhost:${port}/app-metrics`);
});