An open API service indexing awesome lists of open source software.

https://github.com/last9/openapm-nodejs

APM for NodeJS using Prometheus
https://github.com/last9/openapm-nodejs

apm application-monitoring instrumentation metrics monitoring nodejs openmetrics opensource

Last synced: about 1 year ago
JSON representation

APM for NodeJS using Prometheus

Awesome Lists containing this project

README

          

# @last9/openapm

An APM solution based on metrics and open-source tools such as Prometheus and Grafana for NodeJs-based applications.

## Table of Contents

1. [Installation](#installation)
2. [Usage](#usage)
3. [Options](#options)
4. [API Reference](#api-reference)
5. [Setup Locally](#setup-locally)
6. [Grafana Dashboard View](#grafana-dashboard-view)

## Installation

```
npm install --save @last9/openapm@latest
```

## Usage

```js
const express = require('express');
const { OpenAPM } = require('@last9/openapm');

const app = express();
const openapm = new OpenAPM();

// Instrument services

app.listen(3000);

const gracefullyShutdown = () => {
app.close(() => {
openapm
.shutdown()
.then(() => {
console.log('OpenAPM shutdown successful.');
})
.catch((err) => {
console.log('Error shutting down OpenAPM', err);
});
});
};

process.on('SIGINT', gracefullyShutdown);
process.on('SIGTERM', gracefullyShutdown);
```

1. [Express](#express)
2. [MySQL](#mysql)
3. [NestJS](#nestjs)
4. [Next.js](#nextjs)

### Express

In the example below, the metrics will be served on `localhost:9097/metrics`. To
change the port, you can update it through the options
([See the options documentation](#options)).

```js
const { OpenAPM } = require('@last9/openapm');
const openapm = new OpenAPM();

openapm.instrument('express');
```

### MySQL

This currently supports instrumentation for all Node.js ORMs, which are [mysql2](https://www.npmjs.com/package/mysql2) compatible.

Ensure to add this line of code before you initialize db `connection/pool/poolCluster`.

```js
openapm.instrument('mysql');
```

### NestJS

OpenAPM currently supports RED Metrics for NestJS v4 and above.

```js
openapm.instrument('nestjs');
```

### Next.js

OpenAPM supports RED metrics for both pages and app router in a Next.js application.

```js
openapm.instrument('nextjs');
```

> Note: You can only use the library if Next.js runs in a Node.js environment. Since OpenAPM relies on prom-client for capturing metrics data, a serverless environment might not be able persist them.

## Options

### Usage

```js
const openapm = new OpenAPM({
// Options go here
});
```

1. `path`: The path at which the metrics will be served. For eg. `/metrics`
2. `metricsServerPort`: (Optional) The port at which the metricsServer will run.
3. `environment`: (Optional) The application environment. Defaults to
`production`.
4. `defaultLabels`: (Optional) Any default labels to be included.
5. `requestsCounterConfig`: (Optional) Requests counter configuration, same as
[Counter](https://github.com/siimon/prom-client#counter) in `prom-client`.
Defaults to

```js
{
name: 'http_requests_total',
help: 'Total number of requests',
labelNames: ['path', 'method', 'status'],
}
```

6. `requestDurationHistogramConfig`: (Optional) Requests Duration histogram
configuration, the same as
[Histogram](https://github.com/siimon/prom-client#histogram) in
`prom-client`. Defaults to
```js
{
name: 'http_requests_duration_milliseconds',
help: 'Duration of HTTP requests in milliseconds',
labelNames: ['path', 'method', 'status'],
buckets: promClient.exponentialBuckets(0.25, 1.5, 31),
}
```
7. `extractLabels`: (Optional) Extract labels from URL params (WIP: Headers, Subdomain)
```js
// To extract from the URL params
{
...
extractLabels: {
tenant: { // Here 'tenant' is the label name
from : 'params',
key: 'org' // Which key to extract from the params
mask: ':org' // Replacement string
}
}
}
```
8. `excludeDefaultLabels`: (Optional) Provide labels to exclude from the default labels

```js
{
...
excludeDefaultLabels: ['environment', 'version']
}
```

9. `levitateConfig`: (Optional) Configuration for Levitate TSDB. Adding this configuration will enable the [Change Events](https://docs.last9.io/docs/change-events).

10. `enableMetricsServer`: (Optional) Defaults to `true`. When set to `false` the OpenAPM won't start a metrics server. To get the metrics users can rely on the `.getMetrics()` function.

```js
{
...
levitateConfig: {
host: 'https://app.last9.io',
orgSlug: 'last9', /** The slug can be obtained from the Last9 dashboard.*/
dataSourceName: 'data-source', /** The data source can be obtained from the data source pages in the Last9 dashboard*/
refreshTokens: {
write: '0d2a1a9a45XXXXXXXXXXXXXX3f1342790d2a1a9a45XXXXXXXXXXXXXX3f1342790d2a1a9a45XXXXXXXXXXXXXX3f134279' /** You can get this from the API access page on Last9 dashboard*/
}
}
}
```

11. `enabled`: (Optional) Defaults to `true`. When set to `false` OpenAPM will be disabled and no metrics will be collected or emitted.

```
const openapm = new OpenAPM({
enabled: process.env.NODE_ENV === 'production'
})
```

12. `additionalLabels`: (Optional) Accepts an array of label keys that will be emitted with the metrics. This option is used in tandem with the `setOpenAPMLabels` API. Checkout [API Reference](#api-reference)

```
const openapm = new OpenAPM({
additionalLabels: ['slug']
})
```

## API Reference

1. `instrument`: Used to instrument supported technologies. Refer the [usage](#usage) section.

2. `getMetrics`: Returns a Promise of string which contains metrics in Prometheus exposition format. You can use this function to expose a metrics endpoint if `enableMetricsServer` is set to false. For example,

```js
const openapm = new OpenAPM({
enableMetricsServer: false
});

openapm.instrument('express');

const app = express();

app.get('/metrics', async (_, res) => {
const metrics = await openapm.getMetrics();
res.setHeader('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');
res.end(metrics);
});
```

3. `shutdown`: Returns a promise which is resolved after the cleanup in OpenAPM. The cleanup includes closing the metrics server if it has started and cleared the prom-client register.

```js
const gracefullyShutdown = () => {
server.close(() => {
openapm
.shutdown()
.then(() => {
console.log('OpenAPM shutdown successful.');
})
.catch((err) => {
console.log('Error shutting down OpenAPM', err);
});
});
};

process.on('SIGINT', gracefullyShutdown);
process.on('SIGTERM', gracefullyShutdown);
```

4. `setOpenAPMLabels`: Unlike other APIs. You can directly import `setOpenAPMLabels` in any file to set custom labels to the request. Make sure to mention the label key in `additionalLabels` option. This function can set multiple labels in the metrics emitted by the ongoing HTTP request.

Note: `setOpenAPMLabels` currently works with **express** and **Nest.js** only.

```js
import { OpenAPM, setOpenAPMLabels } from '@last9/openapm';

const openapm = new OpenAPM({
additionalLabels: ['slug']
});

const handler = () => {
setOpenAPMLabels({ slug: 'org-slug' });
};
```

5. Defining custom metrics

OpenAPM exposes underlying `prom-client` via `getMetricClient` function.

```js
const { getMetricClient } = require('@last9/openapm');

// initialize custom metric
const client = getMetricClient();
const counter = new client.Counter({
name: 'cancelation_calls',
help: 'no. of times cancel operation is called'
});

// handler
app.get('/cancel/:ids', (req, res) => {
counter.inc();
res.status(200).json({});
});
```

Follow the [documentation of prom-client](https://github.com/siimon/prom-client?tab=readme-ov-file#custom-metrics)
to get familiar with the DSL for defining custom metrics.

## Setup locally

Make sure you are in the express directory.

- Install packages

```
npm install
```

- Build package

- This will build the package and store the JS and type declaration files in
the `dist` folder.

```
npm run build
```

# Grafana Dashboard View

1. Import [this](./APM-Grafana-Dashboard.json) dashboard into your Grafana
2. Select your data source
3. Save the dashboard

![APM Dashboard](images/apm-dashboard-1.png)
![APM Dashboard](images/apm-dashboard-2.png)
![APM Dashboard](images/apm-dashboard-3.png)

# About Last9

[Last9](https://last9.io) builds reliability tools for SRE and DevOps.