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.
package/dist/index.d.ts
ADDED
|
@@ -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']`
|