axios-prometheus-adapter 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ export { AxiosPrometheusAdapterConfig, createAxiosPrometheusMiddleware } from './lib/AxiosPrometheusAdapter';
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAxiosPrometheusMiddleware = void 0;
4
+ var AxiosPrometheusAdapter_1 = require("./lib/AxiosPrometheusAdapter");
5
+ Object.defineProperty(exports, "createAxiosPrometheusMiddleware", { enumerable: true, get: function () { return AxiosPrometheusAdapter_1.createAxiosPrometheusMiddleware; } });
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;AAAA,uEAA6G;AAAtE,yIAAA,+BAA+B,OAAA"}
@@ -0,0 +1,8 @@
1
+ import { AxiosInstance } from 'axios';
2
+ import client from 'prom-client';
3
+ export type AxiosPrometheusAdapterConfig = {
4
+ name: string;
5
+ help: string;
6
+ labelNames: string[];
7
+ };
8
+ export declare const createAxiosPrometheusMiddleware: (axiosInstance: AxiosInstance, registry: client.Registry, config?: AxiosPrometheusAdapterConfig) => void;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createAxiosPrometheusMiddleware = void 0;
7
+ const prom_client_1 = __importDefault(require("prom-client"));
8
+ const createAxiosPrometheusMiddleware = (axiosInstance, registry, config) => {
9
+ const clientRequestDuration = new prom_client_1.default.Histogram({
10
+ name: 'http_client_requests_seconds_count',
11
+ help: 'http_client_requests_seconds_count',
12
+ labelNames: ['status_code', 'method', 'protocol', 'host', 'path'],
13
+ ...config,
14
+ });
15
+ // todo: chack user
16
+ registry.registerMetric(clientRequestDuration);
17
+ axiosInstance.interceptors.request.use((config) => {
18
+ const end = clientRequestDuration.startTimer();
19
+ config.metadata = {
20
+ endTimer: end,
21
+ };
22
+ return config;
23
+ });
24
+ axiosInstance.interceptors.response.use((response) => {
25
+ const labels = {
26
+ status_code: response.status,
27
+ method: response.request.method,
28
+ protocol: response.request.protocol,
29
+ host: response.request.host,
30
+ path: response.request.path,
31
+ };
32
+ response.config.metadata.endTimer(labels);
33
+ return response;
34
+ }, error => {
35
+ const labels = {
36
+ status_code: error.response.status,
37
+ method: error.response.request.method,
38
+ protocol: error.response.request.protocol,
39
+ host: error.response.request.host,
40
+ path: error.response.request.path,
41
+ };
42
+ error.config.metadata.endTimer(labels);
43
+ return Promise.reject(error);
44
+ });
45
+ };
46
+ exports.createAxiosPrometheusMiddleware = createAxiosPrometheusMiddleware;
47
+ //# sourceMappingURL=AxiosPrometheusAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AxiosPrometheusAdapter.js","sourceRoot":"","sources":["../../lib/AxiosPrometheusAdapter.ts"],"names":[],"mappings":";;;;;;AACA,8DAAiC;AAQ1B,MAAM,+BAA+B,GAAG,CAC7C,aAA4B,EAC5B,QAAyB,EACzB,MAAqC,EAC/B,EAAE;IACR,MAAM,qBAAqB,GAAG,IAAI,qBAAM,CAAC,SAAS,CAAC;QACjD,IAAI,EAAE,oCAAoC;QAC1C,IAAI,EAAE,oCAAoC;QAC1C,UAAU,EAAE,CAAC,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC;QACjE,GAAG,MAAM;KACV,CAAC,CAAC;IAEH,mBAAmB;IAEnB,QAAQ,CAAC,cAAc,CAAC,qBAAqB,CAAC,CAAC;IAE/C,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAW,EAAE,EAAE;QACrD,MAAM,GAAG,GAAG,qBAAqB,CAAC,UAAU,EAAE,CAAC;QAE/C,MAAM,CAAC,QAAQ,GAAG;YAChB,QAAQ,EAAE,GAAG;SACd,CAAC;QACF,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,aAAa,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAa,EAAE,EAAE;QACxD,MAAM,MAAM,GAAG;YACb,WAAW,EAAE,QAAQ,CAAC,MAAM;YAC5B,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM;YAC/B,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ;YACnC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI;YAC3B,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI;SAC5B,CAAC;QACF,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC1C,OAAO,QAAQ,CAAC;IAClB,CAAC,EAAE,KAAK,CAAC,EAAE;QACT,MAAM,MAAM,GAAG;YACb,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM;YAClC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM;YACrC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ;YACzC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI;YACjC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI;SAClC,CAAC;QACF,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACvC,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AA9CW,QAAA,+BAA+B,mCA8C1C"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "axios-prometheus-adapter",
3
+ "version": "0.0.2",
4
+ "description": "Provides prometheus metrics for outgoing axios requests",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "readme.md"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "start": "ts-node-dev examples/index.ts",
14
+ "test": "jest"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/PauloPepp/axios-prometheus-adapter.git"
19
+ },
20
+ "author": "",
21
+ "license": "ISC",
22
+ "jest": {
23
+ "testTimeout": 30000,
24
+ "testEnvironment": "node",
25
+ "transform": {
26
+ "^.+\\.(t|j)s$": "ts-jest"
27
+ },
28
+ "restoreMocks": true,
29
+ "clearMocks": true,
30
+ "moduleFileExtensions": [
31
+ "ts",
32
+ "js",
33
+ "json"
34
+ ],
35
+ "testMatch": [
36
+ "./**/*.spec.ts"
37
+ ]
38
+ },
39
+ "dependencies": {
40
+ "axios": "^1.2.4",
41
+ "prom-client": "^14.1.1"
42
+ },
43
+ "devDependencies": {
44
+ "@types/axios": "^0.14.0",
45
+ "@types/express": "^4.17.16",
46
+ "@types/jest": "^29.4.0",
47
+ "@typescript-eslint/eslint-plugin": "^5.50.0",
48
+ "@typescript-eslint/parser": "^5.50.0",
49
+ "eslint": "^8.33.0",
50
+ "express": "^4.18.2",
51
+ "jest": "^29.4.0",
52
+ "ts-jest": "^29.0.5",
53
+ "ts-node-dev": "^2.0.0",
54
+ "typescript": "^4.9.5"
55
+ }
56
+ }
package/readme.md ADDED
@@ -0,0 +1,117 @@
1
+ # Axios Prometheus Adapter
2
+
3
+ ## Install
4
+ It requires `prom-client` library to be installed.
5
+ ```
6
+ npm i axios-prometheus-adapter
7
+
8
+ yarn add axios-prometheus-adapter
9
+ ```
10
+
11
+ ## Usage
12
+ ### Set up your code
13
+ You can use it with default metrics, or with custom metrics as well.
14
+
15
+ Here is an example, how to use it with default metrics, and with the global axios instance:
16
+ ```ts
17
+ import axios from 'axios';
18
+ import { createAxiosPrometheusMiddleware } from 'axios-prometheus-adapter';
19
+ import { collectDefaultMetrics, Registry } from 'prom-client';
20
+
21
+ const registry = new Registry();
22
+ collectDefaultMetrics({ register: registry });
23
+ createAxiosPrometheusMiddleware(axios, registry);
24
+ ```
25
+
26
+ This library does not depend on any framework like express, of fastify.
27
+
28
+ Here is an example, how to use it with express:
29
+ ```ts
30
+ const app = express();
31
+ const port = 3000;
32
+
33
+ app.get('/', async (req, res) => {
34
+ await axios('https://jsonplaceholder.typicode.com/posts/1');
35
+ await axios('https://jsonplaceholder.typicode.com/posts/2');
36
+ res.sendStatus(200);
37
+ });
38
+
39
+ app.get('/metrics', async (req, res) => {
40
+ const metrics = await registry.metrics();
41
+ res.send(metrics);
42
+ });
43
+
44
+ app.listen(port, () => {
45
+ console.log(`Example app listening on port ${port}`);
46
+ });
47
+ ```
48
+
49
+ ### Output
50
+ Calling the `/` endpoint first will trigger two API calls, and return with a status code 200. To collect metrics of api calls
51
+ require to have api calls first.
52
+ ```sh
53
+ curl http://0.0.0.0/
54
+ ```
55
+
56
+ After this first call we can call the `/metrics` endpoint to get some metics data:
57
+ ```sh
58
+ curl http://0.0.0.0/metrics
59
+ ```
60
+ Output:
61
+ ```
62
+ [[[DEFAULT NODE METRICS]]]
63
+ ...
64
+ # HELP http_client_requests_seconds_count http_client_requests_seconds_count
65
+ # TYPE http_client_requests_seconds_count histogram
66
+ http_client_requests_seconds_count_bucket{le="0.005",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/1"} 0
67
+ http_client_requests_seconds_count_bucket{le="0.01",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/1"} 0
68
+ http_client_requests_seconds_count_bucket{le="0.025",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/1"} 0
69
+ http_client_requests_seconds_count_bucket{le="0.05",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/1"} 0
70
+ http_client_requests_seconds_count_bucket{le="0.1",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/1"} 0
71
+ http_client_requests_seconds_count_bucket{le="0.25",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/1"} 0
72
+ http_client_requests_seconds_count_bucket{le="0.5",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/1"} 1
73
+ http_client_requests_seconds_count_bucket{le="1",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/1"} 1
74
+ http_client_requests_seconds_count_bucket{le="2.5",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/1"} 1
75
+ http_client_requests_seconds_count_bucket{le="5",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/1"} 1
76
+ http_client_requests_seconds_count_bucket{le="10",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/1"} 1
77
+ http_client_requests_seconds_count_bucket{le="+Inf",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/1"} 1
78
+ http_client_requests_seconds_count_sum{status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/1"} 0.257366432
79
+ http_client_requests_seconds_count_count{status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/1"} 1
80
+ http_client_requests_seconds_count_bucket{le="0.005",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/2"} 0
81
+ http_client_requests_seconds_count_bucket{le="0.01",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/2"} 0
82
+ http_client_requests_seconds_count_bucket{le="0.025",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/2"} 0
83
+ http_client_requests_seconds_count_bucket{le="0.05",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/2"} 0
84
+ http_client_requests_seconds_count_bucket{le="0.1",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/2"} 0
85
+ http_client_requests_seconds_count_bucket{le="0.25",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/2"} 1
86
+ http_client_requests_seconds_count_bucket{le="0.5",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/2"} 1
87
+ http_client_requests_seconds_count_bucket{le="1",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/2"} 1
88
+ http_client_requests_seconds_count_bucket{le="2.5",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/2"} 1
89
+ http_client_requests_seconds_count_bucket{le="5",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/2"} 1
90
+ http_client_requests_seconds_count_bucket{le="10",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/2"} 1
91
+ http_client_requests_seconds_count_bucket{le="+Inf",status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/2"} 1
92
+ http_client_requests_seconds_count_sum{status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/2"} 0.107517055
93
+ http_client_requests_seconds_count_count{status_code="200",method="GET",protocol="https:",host="jsonplaceholder.typicode.com",path="/posts/2"} 1
94
+ ```
95
+
96
+ ### Custom config
97
+ You can overwrite the name, the help and the labels property of this metrics by providing an optional third argument of the
98
+ `createAxiosPrometheusMiddleware` function.
99
+ ```ts
100
+ createAxiosPrometheusMiddleware(axios, registry, {
101
+ name: 'your_custom_metric_name',
102
+ help: 'your costum help description',
103
+ labelNames: ['status_code', 'method']
104
+ });
105
+ ```
106
+
107
+ Here is the type of the config object:
108
+ ```ts
109
+ export type AxiosPrometheusAdapterConfig = {
110
+ name: string,
111
+ help: string,
112
+ labelNames: string[]
113
+ };
114
+ ```
115
+
116
+ `labelNames` is an array with predefined values. By default we support the following labels:
117
+ `['status_code', 'method', 'protocol', 'host', 'path']`