{"id":28200983,"url":"https://github.com/payu/prometheus-api-metrics","last_synced_at":"2025-06-12T18:32:06.919Z","repository":{"id":40390941,"uuid":"135303797","full_name":"PayU/prometheus-api-metrics","owner":"PayU","description":"API and process monitoring with Prometheus for Node.js micro-service","archived":false,"fork":false,"pushed_at":"2025-03-09T15:11:02.000Z","size":1105,"stargazers_count":129,"open_issues_count":43,"forks_count":46,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-05-23T23:01:02.501Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/PayU.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-29T13:54:39.000Z","updated_at":"2025-04-01T07:19:43.000Z","dependencies_parsed_at":"2024-03-27T07:32:23.111Z","dependency_job_id":"991eb209-5a92-4ee6-854b-21f39dc54471","html_url":"https://github.com/PayU/prometheus-api-metrics","commit_stats":{"total_commits":112,"total_committers":22,"mean_commits":5.090909090909091,"dds":0.5178571428571428,"last_synced_commit":"a1f7691c1eb95cb1b02438e7d5b248bc9608618e"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"purl":"pkg:github/PayU/prometheus-api-metrics","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PayU%2Fprometheus-api-metrics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PayU%2Fprometheus-api-metrics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PayU%2Fprometheus-api-metrics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PayU%2Fprometheus-api-metrics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PayU","download_url":"https://codeload.github.com/PayU/prometheus-api-metrics/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PayU%2Fprometheus-api-metrics/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259519258,"owners_count":22870327,"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":[],"created_at":"2025-05-16T22:14:47.574Z","updated_at":"2025-06-12T18:32:06.910Z","avatar_url":"https://github.com/PayU.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Prometheus API Monitoring\n\n[![NPM Version][npm-image]][npm-url]\n[![NPM Downloads][downloads-image]][downloads-url]\n[![Build Status][travis-image]][travis-url]\n[![Test Coverage][coveralls-image]][coveralls-url]\n[![Known Vulnerabilities][snyk-image]][snyk-url]\n[![Apache 2.0 License][license-image]][license-url]\n\n\u003c!-- **Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)* --\u003e\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n\n- [Goal](#goal)\n- [Features](#features)\n- [Usage](#usage)\n  - [Options](#options)\n  - [Access the metrics](#access-the-metrics)\n- [Custom Metrics](#custom-metrics)\n  - [Note](#note)\n- [Additional Metric Labels](#additional-metric-labels)\n- [Request.js HTTP request duration collector](#requestjs-http-request-duration-collector)\n  - [Usage](#usage-1)\n    - [Initialize](#initialize)\n    - [Options](#options-1)\n    - [request](#request)\n    - [request-promise-native](#request-promise-native)\n    - [axios](#axios)\n- [Usage in koa](#usage-in-koa)\n- [Test](#test)\n- [Prometheus Examples Queries](#prometheus-examples-queries)\n  - [Apdex](#apdex)\n  - [95th Response Time by specific route and status code](#95th-response-time-by-specific-route-and-status-code)\n  - [Median Response Time Overall](#median-response-time-overall)\n  - [Median Request Size Overall](#median-request-size-overall)\n  - [Median Response Size Overall](#median-response-size-overall)\n  - [Average Memory Usage - All services](#average-memory-usage---all-services)\n  - [Average Eventloop Latency - All services](#average-eventloop-latency---all-services)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Goal\n\nAPI and process monitoring with [Prometheus](https://prometheus.io) for Node.js micro-service\n\n**Note: Prometheus (`prom-client`) is a peer dependency since 1.x version**\n\n## Features\n\n- [Collect API metrics for each call](#usage)\n  - Response time in seconds\n  - Request size in bytes\n  - Response size in bytes\n  - Add prefix to metrics names - custom or project name\n  - Exclude specific routes from being collect\n  - Number of open connections to the server\n- Process Metrics as recommended by Prometheus [itself](https://prometheus.io/docs/instrumenting/writing_clientlibs/#standard-and-runtime-collectors)\n- Endpoint to retrieve the metrics - used for Prometheus scraping\n  - Prometheus format\n  - JSON format (`${path}.json`)\n- Support custom metrics\n- [Http function to collect request.js HTTP request duration](#requestjs-http-request-duration-collector)\n\n## Usage\n\n```js\nconst apiMetrics = require('prometheus-api-metrics');\napp.use(apiMetrics())\n```\n\n### Options\n\n| Option                   | Type      | Description | Default Value |\n|--------------------------|-----------|-------------|---------------|\n| `metricsPath`            | `String`  | Path to access the metrics | `/metrics` |\n| `defaultMetricsInterval` | `Number`  | Interval to collect the process metrics in milliseconds | `10000` |\n| `durationBuckets`        | `Array\u003cNumber\u003e` | Buckets for response time in seconds | `[0.001, 0.005, 0.015, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5]` |\n| `requestSizeBuckets`     | `Array\u003cNumber\u003e` | Buckets for request size in bytes | `[5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000]` |\n| `responseSizeBuckets`    | `Array\u003cNumber\u003e` | Buckets for response size in bytes | `[5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000]` |\n| `useUniqueHistogramName` | `Boolean` | Add to metrics names the project name as a prefix (from package.json) | `false` |\n| `metricsPrefix`          | `String`  | A custom metrics names prefix, the package will add underscore between your prefix to the metric name | |\n| `excludeRoutes`          | `Array\u003cString\u003e` | Array of routes to exclude. Routes should be in your framework syntax | |\n| `includeQueryParams`     | `Boolean` | Indicate if to include query params in route, the query parameters will be sorted in order to eliminate the number of unique labels | `false` |\n| `additionalLabels`       | `Array\u003cString\u003e` | Indicating custom labels that can be included on each `http_*` metric. Use in conjunction with `extractAdditionalLabelValuesFn`. |\n| `extractAdditionalLabelValuesFn` | `Function` | A function that can be use to generate the value of custom labels for each of the `http_*` metrics. When using koa, the function takes `ctx`, when using express, it takes `req, res` as arguments | |\n\n### Access the metrics\n\nTo get the metrics in Prometheus format use:\n\n```sh\ncurl http[s]://\u003chost\u003e:[port]/metrics\n```\n\nTo get the metrics in JSON format use:\n\n```sh\ncurl http[s]://\u003chost\u003e:[port]/metrics.json\n```\n\n**Note:**\n\n1. If you pass to the middleware the `metricsPath` option the path will be the one that you chose.\n\n2. If you are using express framework and no route was found for the request (e.g: 404 status code), the request will not be collected. that's because we'll risk memory leak since the route is not a pattern but a hardcoded string.\n\n## Custom Metrics\n\nYou can expand the API metrics with more metrics that you would like to expose.\nAll you have to do is:\n\nRequire prometheus client\n\n```js\nconst Prometheus = require('prom-client');\n```\n\nCreate new metric from the kind that you like\n\n```js\nconst checkoutsTotal = new Prometheus.Counter({\n  name: 'checkouts_total',\n  help: 'Total number of checkouts',\n  labelNames: ['payment_method']\n});\n```\n\nUpdate it:\n\n```js\ncheckoutsTotal.inc({\n  payment_method: paymentMethod\n})\n```\n\nThe custom metrics will be exposed under the same endpoint as the API metrics.\n\nFor more info about the Node.js Prometheus client you can read [here](https://github.com/siimon/prom-client#prometheus-client-for-nodejs--)\n\n### Note\n\nThis will work only if you use the default Prometheus registry - do not use `new Prometheus.Registry()`\n\n## Additional Metric Labels\n\nYou can define additional metric labels by using `additionalLabels` and `extractAdditionalLabelValuesFn` options.\n\nFor instance:\n\n```js\nconst apiMetrics = require('prometheus-api-metrics');\napp.use(apiMetrics({\n  additionalLabels: ['customer', 'cluster'],\n  extractAdditionalLabelValuesFn: (req, res) =\u003e {\n      const { headers } = req.headers;\n      return {\n        customer: headers['x-custom-header-customer'],\n        cluster: headers['x-custom-header-cluster']\n      }\n  }\n}))\n```\n\n## Request.js HTTP request duration collector\n\nThis feature enables you to easily process the result of Request.js timings feature.\n\n### Usage\n\n#### Initialize\n\nYou can choose to initialized this functionality as a Class or not\n\n**Class:**\n\n```js\nconst HttpMetricsCollector = require('prometheus-api-metrics').HttpMetricsCollector;\nconst collector = new HttpMetricsCollector();\ncollector.init();\n```\n\n**Singleton:**\n\n```js\nconst HttpMetricsCollector = require('prometheus-api-metrics').HttpMetricsCollector;\nHttpMetricsCollector.init();\n```\n\n#### Options\n\n- durationBuckets - the histogram buckets for request duration.\n- countClientErrors - Boolean that indicates whether to collect client errors as Counter, this counter will have target and error code labels.\n- useUniqueHistogramName - Add to metrics names the project name as a prefix (from package.json)\n- prefix - A custom metrics names prefix, the package will add underscore between your prefix to the metric name.\n\nFor Example:\n\n#### request\n\n```js\nrequest({ url: 'http://www.google.com', time: true }, (err, response) =\u003e {\n    Collector.collect(err || response);\n});\n```\n\n#### request-promise-native\n\n```js\nreturn requestPromise({ method: 'POST', url: 'http://www.mocky.io/v2/5bd9984b2f00006d0006d1fd', route: 'v2/:id', time: true, resolveWithFullResponse: true }).then((response) =\u003e {\n    Collector.collect(response);\n}).catch((error) =\u003e {\n    Collector.collect(error);\n});\n```\n\n**Notes:**\n\n1. In order to use this feature you must use `{ time: true }` as part of your request configuration and then pass to the collector the response or error you got.\n2. In order to use the timing feature in request-promise/request-promise-native you must also use `resolveWithFullResponse: true`\n3. Override - you can override the `route` and `target` attribute instead of taking them from the request object. In order to do that you should set a `metrics` object on your request with those attribute:\n```js\nrequest({ method: 'POST', url: 'http://www.mocky.io/v2/5bd9984b2f00006d0006d1fd', metrics: { target: 'www.google.com', route: 'v2/:id' }, time: true }, (err, response) =\u003e {...};\n});\n```\n\n#### axios\n\n```js\nconst axios = require('axios');\nconst axiosTime = require('axios-time');\n\naxiosTime(axios);\n\ntry {\n    const response = await axios({ baseURL: 'http://www.google.com', method: 'get', url: '/' });\n    Collector.collect(response);\n} catch (error) {\n    Collector.collect(error);\n}\n```\n\n**Notes:**\n\n- In order to collect metrics from axios client the [`axios-time`](https://www.npmjs.com/package/axios-time) package is required.\n\n## Usage in koa\n\nThis package supports koa server that uses [`koa-router`](https://www.npmjs.com/package/koa-router) and [`koa-bodyparser`](https://www.npmjs.com/package/koa-bodyparser)\n\n```js\nconst { koaMiddleware } = require('prometheus-api-metrics')\n\napp.use(koaMiddleware())\n```\n\n## Test\n\n```sh\nnpm test\n```\n\n## Prometheus Examples Queries\n\n### [Apdex](https://en.wikipedia.org/wiki/Apdex)\n\n```\n(sum(rate(http_request_duration_seconds_bucket{\u003cSERVICE_LABEL_FIELD\u003e=\"\u003cSERVICE_LABEL\u003e\"\u003e, route=\"\u003cROUTE_NAME\u003e\", le=\"0.05\"}[10m])) by (\u003cSERVICE_LABEL_FIELD\u003e) + sum(rate(http_request_duration_seconds_bucket{\u003cSERVICE_LABEL_FIELD\u003e=\"\u003cSERVICE_LABEL\u003e\", route=\"\u003cROUTE_NAME\u003e\", le=\"0.1\"}[10m])) by (\u003cSERVICE_LABEL_FIELD\u003e)) / 2 / sum(rate(http_request_duration_seconds_count{\u003cSERVICE_LABEL_FIELD\u003e=\"\u003cSERVICE_LABEL\u003e\", route=\"\u003cROUTE_NAME\u003e\"}[10m])) by (\u003cSERVICE_LABEL_FIELD\u003e)\n```\n\n### 95th Response Time by specific route and status code\n\n```\nhistogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{\u003cSERVICE_LABEL_FIELD\u003e=\"\u003cSERVICE_LABEL\u003e\", route=\"\u003cROUTE_NAME\u003e\", code=\"200\"}[10m])) by (le))\n```\n\n### Median Response Time Overall\n\n```\nhistogram_quantile(0.50, sum(rate(http_request_duration_seconds_bucket{\u003cSERVICE_LABEL_FIELD\u003e=\"\u003cSERVICE_LABEL\u003e\"}[10m])) by (le))\n```\n\n### Median Request Size Overall\n\n```\nhistogram_quantile(0.50, sum(rate(http_request_size_bytes_bucket{\u003cSERVICE_LABEL_FIELD\u003e=\"\u003cSERVICE_LABEL\u003e\"}[10m])) by (le))\n```\n\n### Median Response Size Overall\n\n```\nhistogram_quantile(0.50, sum(rate(http_response_size_bytes_bucket{\u003cSERVICE_LABEL_FIELD\u003e=\"\u003cSERVICE_LABEL\u003e\"}[10m])) by (le))\n```\n\n### Average Memory Usage - All services\n\n```\navg(nodejs_external_memory_bytes / 1024 / 1024) by (\u003cSERVICE_LABEL_FIELD)\n```\n\n### Average Eventloop Latency - All services\n\n```\navg(nodejs_eventloop_lag_seconds) by (\u003cSERVICE_LABEL_FIELD)\n```\n\n[npm-image]: https://img.shields.io/npm/v/prometheus-api-metrics.svg?style=flat\n[npm-url]: https://npmjs.org/package/prometheus-api-metrics\n[travis-image]: https://travis-ci.org/PayU/prometheus-api-metrics.svg?branch=master\n[travis-url]: https://travis-ci.org/PayU/prometheus-api-metrics\n[coveralls-image]: https://coveralls.io/repos/github/PayU/prometheus-api-metrics/badge.svg?branch=master\n[coveralls-url]: https://coveralls.io/github/PayU/prometheus-api-metrics?branch=master\n[downloads-image]: http://img.shields.io/npm/dm/prometheus-api-metrics.svg?style=flat\n[downloads-url]: https://npmjs.org/package/prometheus-api-metrics\n[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat\n[license-url]: LICENSE\n[snyk-image]: https://snyk.io/test/npm/prometheus-api-metrics/badge.svg\n[snyk-url]: https://snyk.io/test/npm/prometheus-api-metrics\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpayu%2Fprometheus-api-metrics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpayu%2Fprometheus-api-metrics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpayu%2Fprometheus-api-metrics/lists"}