# @godspeedsystems/express-prometheus-middleware

> RED/USE metrics for express applications

Latest version **0.0.1** (published 2024-03-12) · ISC license · 0 weekly downloads

## Install

```sh
npm install @godspeedsystems/express-prometheus-middleware
pnpm add @godspeedsystems/express-prometheus-middleware
yarn add @godspeedsystems/express-prometheus-middleware
bun add @godspeedsystems/express-prometheus-middleware
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.0.1 |
| Published | 2024-03-12 |
| First published | 2024-03-12 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 2 |
| Unpacked size | 14.6 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | Gurjot Kaur |
| Maintainers | kushal023, siddarthvader12, avtar, ashutosh.godspeed, gurjot20, godspeed-systems |
| Keywords | express, prometheus, metrics, godspeedsystems |

## Links

- npm: https://www.npmjs.com/package/@godspeedsystems/express-prometheus-middleware
- Repository: https://github.com/godspeedsystems/express-prometheus-middleware
- Homepage: https://github.com/godspeedsystems/express-prometheus-middleware#readme
- Issues: https://github.com/godspeedsystems/express-prometheus-middleware/issues
- npm.io page: https://npm.io/package/@godspeedsystems/express-prometheus-middleware

## Dependencies (2)

- [response-time](https://npm.io/package/response-time.md) ^2.3.2
- [url-value-parser](https://npm.io/package/url-value-parser.md) ^2.0.0

## Recent versions

- 0.0.1 (latest) — 2024-03-12

## README

# Express Prometheus Middleware

This is a middleware for express servers, that expose metrics for prometheus.

The metrics exposed allows to calculate common RED (Request, Error rate, Duration of requests), and USE (Utilisation, Error rate, and Saturation), metrics

## Install

``` bash
npm i --save @mindgrep/express-prometheus-middleware
```

## Usage

### Options

| Name | Description | Default |
| :-: | :- | :- |
| metricsPath | Url route that will expose the metrics for scraping. | `/metrics` |
| metricsApp  | Express app that will expose metrics endpoint, if an app is provided, use it, instead of instantiating a new one | `null` |
| collectDefaultMetrics | Whether or not to collect `prom-client` default metrics. These metrics are usefull for collecting saturation metrics, for example. | `true` |
| collectGCMetrics | Whether or not to collect garbage collection metrics via module `prometheus-gc-stats`. Dependency `prometheus-gc-stats` is marked as optional, hence if this option is set to `true` but npm/yarn could not install the dependency, no garbage collection metric will be collected. | `false` |
| requestDurationBuckets | Buckets for the request duration metrics (in seconds) histogram | Uses `prom-client` utility: `Prometheus.exponentialBuckets(0.05, 1.75, 8)` |
| requestLengthBuckets | Buckets for the request length metrics (in bytes) histogram | no buckets (The request length metrics are not collected): `[]` |
| responseLengthBuckets | Buckets for the response length metrics (in bytes) histogram | no buckets (The response length metrics are not collected) `[]` |
| normalizePath | Optional, list of regexes to be used as argument to [url-value-parser](https://www.npmjs.com/package/url-value-parser), this will cause extra route params,  to be replaced later argument.  | no normalizePath: `[]` |
| authenticate | Optional authentication callback, the function should receive as argument, the `req` object and return truthy for sucessfull authentication, or falsy, otherwise. This option supports Promise results. | `null` |
| suffix | Optional suffix for the metrics name | no suffix added |
| customLabels | Optional Array containing extra labels, used together with  `transformLabels` | no extra labels: `[]` |
| transformLabels | Optional `function(labels, req, res)` adds to the labels object dynamic values for each label in `customLabels` | `null` |
| normalizeStatus | Optional parameter to disable normalization of the status code. Example of normalized and non-normalized status code respectively: 4xx and 422.| true
### Example

```js
const express = require('express');
const promMid = require('express-prometheus-middleware');
const app = express();

const PORT = 9091;
app.use(promMid({
  metricsPath: '/metrics',
  collectDefaultMetrics: true,
  requestDurationBuckets: [0.1, 0.5, 1, 1.5],
  requestLengthBuckets: [512, 1024, 5120, 10240, 51200, 102400],
  responseLengthBuckets: [512, 1024, 5120, 10240, 51200, 102400],
  normalizePath: [
    ['^/test/.*', '/httpMetricTest'],
    ['^/status/.*', '/status'],
    ['^/hello*', '/hello'],
    ['^/birds/.*', '/#birds'],
    // From deep to surface
    ['^/customers/.*/companies/.*/users/.*', '/customers/#customer/companies/#company/users/#user'],
    ['^/customers/.*/companies/.*', '/customers/#customer/companies/#company'],
    ['^/customers/.*/add/.*', '/customers/#customer/add/#add'],
  ],
  /**
   * Uncomenting the `authenticate` callback will make the `metricsPath` route
   * require authentication. This authentication callback can make a simple
   * basic auth test, or even query a remote server to validate access.
   * To access /metrics you could do:
   * curl -X GET user:password@localhost:9091/metrics
   */
  // authenticate: req => req.headers.authorization === 'Basic dXNlcjpwYXNzd29yZA==',
  /**
   * The prefix option will cause all metrics to have the given prefix.
   * E.g.: `app_prefix_http_requests_total`
   */
  // prefix: 'app_prefix_',
  /**
   * Can add custom labels with customLabels and transformLabels options
   */
  // customLabels: ['contentType'],
  // transformLabels(labels, req) {
  //   // eslint-disable-next-line no-param-reassign
  //   labels.contentType = req.headers['content-type'];
  // },
}));

// curl -X GET localhost:9091/hello?name=Chuck%20Norris
app.get('/hello', (req, res) => {
  console.log('GET /hello');
  const { name = 'Anon' } = req.query;
  res.json({ message: `Hello, ${name}!` });
});

app.listen(PORT, () => {
  console.log(`Example api is listening on http://localhost:${PORT}`);
});
```

### Metrics exposed

- Default metrics from [prom-client](https://github.com/siimon/prom-client)
- `http_requests_total`: Counter for total requests received, has labels `route`, `method`, `status`
- `http_request_duration_seconds`: - Duration of HTTP requests in seconds, has labels `route`, `method`, `status`

The labels `route` and `status` are normalized:

- `route`: will normalize id like route params
- `status`: will normalize to status code family groups, like `2XX` or `4XX`.

### Example prometheus queries

In the examples below, Suppose you tagged your application as "myapp", in the prometheus scrapping config.

#### Running instances

```js
sum(up{app="myapp"})
```

#### Overall error rate

Rate of http status code 5XX responses

```js
sum(rate(http_requests_total{status="5XX", app="myapp"}[5m]))
```

#### 95% of requests served within seconds

```js
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{app="myapp"}[5m])) by (le))
```

#### 95% of request length

```js
histogram_quantile(0.95, sum(rate(http_request_length_bytes_bucket{app="myapp"}[5m])) by (le))
```

#### 95% of response length

```js
histogram_quantile(0.95, sum(rate(http_response_length_bytes_bucket{app="myapp"}[5m])) by (le))
```

#### Average response time in seconds

```js
sum(rate(http_request_duration_seconds_sum{app="myapp"}[5m])) by (instance) / sum(rate(http_request_duration_seconds_count{app="myapp"}[5m])) by (instance)
```

#### Overall Request rate

```js
sum(rate(http_requests_total{app="myapp"}[5m])) by (instance)
```

#### Request rate by route

In this example we are removing some health/status-check routes, replace them with your needs.

```js
sum(rate(http_requests_total{app="myapp", route!~"/|/healthz"}[5m])) by (instance, route)
```

#### CPU usage

```js
rate(process_cpu_system_seconds_total{app="myapp"}[5m])
rate(process_cpu_user_seconds_total{app="myapp"}[5m])
```

#### Memory usage

```js
nodejs_heap_size_total_bytes{app="myapp"}
nodejs_heap_size_used_bytes{app="myapp"}
```

---
_Source: https://npm.io/package/@godspeedsystems/express-prometheus-middleware · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
