{"id":19065746,"url":"https://github.com/last9/openapm-nodejs","last_synced_at":"2025-04-28T12:22:50.796Z","repository":{"id":181935706,"uuid":"667698724","full_name":"last9/openapm-nodejs","owner":"last9","description":"APM for NodeJS using Prometheus","archived":false,"fork":false,"pushed_at":"2024-07-19T15:00:09.000Z","size":8055,"stargazers_count":66,"open_issues_count":9,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-18T15:17:35.816Z","etag":null,"topics":["apm","application-monitoring","instrumentation","metrics","monitoring","nodejs","openmetrics","opensource"],"latest_commit_sha":null,"homepage":"https://last9.io","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/last9.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-18T05:39:48.000Z","updated_at":"2025-02-14T02:20:47.000Z","dependencies_parsed_at":"2023-08-09T06:12:38.824Z","dependency_job_id":"3f1c904d-740a-42d6-b4d0-dce0b1ea75c5","html_url":"https://github.com/last9/openapm-nodejs","commit_stats":null,"previous_names":["last9/nodejs-openapm","last9/openapm-nodejs"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/last9%2Fopenapm-nodejs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/last9%2Fopenapm-nodejs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/last9%2Fopenapm-nodejs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/last9%2Fopenapm-nodejs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/last9","download_url":"https://codeload.github.com/last9/openapm-nodejs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251311697,"owners_count":21569080,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apm","application-monitoring","instrumentation","metrics","monitoring","nodejs","openmetrics","opensource"],"created_at":"2024-11-09T00:52:24.616Z","updated_at":"2025-04-28T12:22:50.769Z","avatar_url":"https://github.com/last9.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ca href=\"https://last9.io\"\u003e\u003cimg src=\"https://last9.github.io/assets/last9-github-badge.svg\" align=\"right\" /\u003e\u003c/a\u003e\n\n# @last9/openapm\n\nAn APM solution based on metrics and open-source tools such as Prometheus and Grafana for NodeJs-based applications.\n\n## Table of Contents\n\n1. [Installation](#installation)\n2. [Usage](#usage)\n3. [Options](#options)\n4. [API Reference](#api-reference)\n5. [Setup Locally](#setup-locally)\n6. [Grafana Dashboard View](#grafana-dashboard-view)\n\n## Installation\n\n```\nnpm install --save @last9/openapm@latest\n```\n\n## Usage\n\n```js\nconst express = require('express');\nconst { OpenAPM } = require('@last9/openapm');\n\nconst app = express();\nconst openapm = new OpenAPM();\n\n// Instrument services\n\napp.listen(3000);\n\nconst gracefullyShutdown = () =\u003e {\n  app.close(() =\u003e {\n    openapm\n      .shutdown()\n      .then(() =\u003e {\n        console.log('OpenAPM shutdown successful.');\n      })\n      .catch((err) =\u003e {\n        console.log('Error shutting down OpenAPM', err);\n      });\n  });\n};\n\nprocess.on('SIGINT', gracefullyShutdown);\nprocess.on('SIGTERM', gracefullyShutdown);\n```\n\n1. [Express](#express)\n2. [MySQL](#mysql)\n3. [NestJS](#nestjs)\n4. [Next.js](#nextjs)\n\n### Express\n\nIn the example below, the metrics will be served on `localhost:9097/metrics`. To\nchange the port, you can update it through the options\n([See the options documentation](#options)).\n\n```js\nconst { OpenAPM } = require('@last9/openapm');\nconst openapm = new OpenAPM();\n\nopenapm.instrument('express');\n```\n\n### MySQL\n\nThis currently supports instrumentation for all Node.js ORMs, which are [mysql2](https://www.npmjs.com/package/mysql2) compatible.\n\nEnsure to add this line of code before you initialize db `connection/pool/poolCluster`.\n\n```js\nopenapm.instrument('mysql');\n```\n\n### NestJS\n\nOpenAPM currently supports RED Metrics for NestJS v4 and above.\n\n```js\nopenapm.instrument('nestjs');\n```\n\n### Next.js\n\nOpenAPM supports RED metrics for both pages and app router in a Next.js application.\n\n```js\nopenapm.instrument('nextjs');\n```\n\n\u003e 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.\n\n## Options\n\n### Usage\n\n```js\nconst openapm = new OpenAPM({\n  // Options go here\n});\n```\n\n1. `path`: The path at which the metrics will be served. For eg. `/metrics`\n2. `metricsServerPort`: (Optional) The port at which the metricsServer will run.\n3. `environment`: (Optional) The application environment. Defaults to\n   `production`.\n4. `defaultLabels`: (Optional) Any default labels to be included.\n5. `requestsCounterConfig`: (Optional) Requests counter configuration, same as\n   [Counter](https://github.com/siimon/prom-client#counter) in `prom-client`.\n   Defaults to\n\n   ```js\n   {\n      name: 'http_requests_total',\n      help: 'Total number of requests',\n      labelNames: ['path', 'method', 'status'],\n    }\n   ```\n\n6. `requestDurationHistogramConfig`: (Optional) Requests Duration histogram\n   configuration, the same as\n   [Histogram](https://github.com/siimon/prom-client#histogram) in\n   `prom-client`. Defaults to\n   ```js\n    {\n        name: 'http_requests_duration_milliseconds',\n        help: 'Duration of HTTP requests in milliseconds',\n        labelNames: ['path', 'method', 'status'],\n        buckets: promClient.exponentialBuckets(0.25, 1.5, 31),\n      }\n   ```\n7. `extractLabels`: (Optional) Extract labels from URL params (WIP: Headers, Subdomain)\n   ```js\n   // To extract from the URL params\n   {\n      ...\n      extractLabels: {\n         tenant: { // Here 'tenant' is the label name\n            from : 'params',\n            key: 'org' // Which key to extract from the params\n            mask: ':org' // Replacement string\n         }\n      }\n   }\n   ```\n8. `excludeDefaultLabels`: (Optional) Provide labels to exclude from the default labels\n\n```js\n{\n  ...\n  excludeDefaultLabels: ['environment', 'version']\n}\n```\n\n9. `levitateConfig`: (Optional) Configuration for Levitate TSDB. Adding this configuration will enable the [Change Events](https://docs.last9.io/docs/change-events).\n\n10. `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.\n\n```js\n{\n   ...\n   levitateConfig: {\n      host: 'https://app.last9.io',\n      orgSlug: 'last9', /** The slug can be obtained from the Last9 dashboard.*/\n      dataSourceName: 'data-source', /** The data source can be obtained from the data source pages in the Last9 dashboard*/\n      refreshTokens: {\n         write: '0d2a1a9a45XXXXXXXXXXXXXX3f1342790d2a1a9a45XXXXXXXXXXXXXX3f1342790d2a1a9a45XXXXXXXXXXXXXX3f134279' /** You can get this from the API access page on Last9 dashboard*/\n      }\n   }\n}\n```\n\n11. `enabled`: (Optional) Defaults to `true`. When set to `false` OpenAPM will be disabled and no metrics will be collected or emitted.\n\n```\nconst openapm = new OpenAPM({\n  enabled: process.env.NODE_ENV === 'production'\n})\n```\n\n12. `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)\n\n```\nconst openapm = new OpenAPM({\n  additionalLabels: ['slug']\n})\n```\n\n## API Reference\n\n1. `instrument`: Used to instrument supported technologies. Refer the [usage](#usage) section.\n\n2. `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,\n\n```js\nconst openapm = new OpenAPM({\n  enableMetricsServer: false\n});\n\nopenapm.instrument('express');\n\nconst app = express();\n\napp.get('/metrics', async (_, res) =\u003e {\n  const metrics = await openapm.getMetrics();\n  res.setHeader('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');\n  res.end(metrics);\n});\n```\n\n3. `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.\n\n```js\nconst gracefullyShutdown = () =\u003e {\n  server.close(() =\u003e {\n    openapm\n      .shutdown()\n      .then(() =\u003e {\n        console.log('OpenAPM shutdown successful.');\n      })\n      .catch((err) =\u003e {\n        console.log('Error shutting down OpenAPM', err);\n      });\n  });\n};\n\nprocess.on('SIGINT', gracefullyShutdown);\nprocess.on('SIGTERM', gracefullyShutdown);\n```\n\n4. `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.\n\nNote: `setOpenAPMLabels` currently works with **express** and **Nest.js** only.\n\n```js\nimport { OpenAPM, setOpenAPMLabels } from '@last9/openapm';\n\nconst openapm = new OpenAPM({\n  additionalLabels: ['slug']\n});\n\nconst handler = () =\u003e {\n  setOpenAPMLabels({ slug: 'org-slug' });\n};\n```\n\n5. Defining custom metrics\n\nOpenAPM exposes underlying `prom-client` via `getMetricClient` function.\n\n```js\nconst { getMetricClient } = require('@last9/openapm');\n\n// initialize custom metric\nconst client = getMetricClient();\nconst counter = new client.Counter({\n  name: 'cancelation_calls',\n  help: 'no. of times cancel operation is called'\n});\n\n// handler\napp.get('/cancel/:ids', (req, res) =\u003e {\n  counter.inc();\n  res.status(200).json({});\n});\n```\n\nFollow the [documentation of prom-client](https://github.com/siimon/prom-client?tab=readme-ov-file#custom-metrics)\nto get familiar with the DSL for defining custom metrics.\n\n## Setup locally\n\nMake sure you are in the express directory.\n\n- Install packages\n\n```\nnpm install\n```\n\n- Build package\n\n  - This will build the package and store the JS and type declaration files in\n    the `dist` folder.\n\n```\nnpm run build\n```\n\n# Grafana Dashboard View\n\n1. Import [this](./APM-Grafana-Dashboard.json) dashboard into your Grafana\n2. Select your data source\n3. Save the dashboard\n\n![APM Dashboard](images/apm-dashboard-1.png)\n![APM Dashboard](images/apm-dashboard-2.png)\n![APM Dashboard](images/apm-dashboard-3.png)\n\n# About Last9\n\n[Last9](https://last9.io) builds reliability tools for SRE and DevOps.\n\n\u003ca href=\"https://last9.io\"\u003e\u003cimg src=\"https://last9.github.io/assets/email-logo-green.png\" alt=\"\" loading=\"lazy\" height=\"40px\" /\u003e\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flast9%2Fopenapm-nodejs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flast9%2Fopenapm-nodejs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flast9%2Fopenapm-nodejs/lists"}