prometheus-api-metrics
Advanced tools
Comparing version
# Master | ||
# 3.1.0 - 3 September, 2020 | ||
- Added support for axios responses while using axios-time plugin | ||
# 3.0.0 - 2 September, 2020 | ||
@@ -4,0 +8,0 @@ |
{ | ||
"name": "prometheus-api-metrics", | ||
"version": "3.0.0", | ||
"version": "3.1.0", | ||
"description": "API and process monitoring with Prometheus for Node.js micro-service", | ||
@@ -36,6 +36,7 @@ "author": "Idan Tovi", | ||
"dependencies": { | ||
"@types/express": "^4.17.6", | ||
"@types/express-serve-static-core": "^4.17.5", | ||
"@types/koa": "^2.11.3", | ||
"@types/express": "^4.17.8", | ||
"@types/express-serve-static-core": "^4.17.12", | ||
"@types/koa": "^2.11.4", | ||
"debug": "^3.2.6", | ||
"lodash.get": "^4.4.2", | ||
"pkginfo": "^0.4.1" | ||
@@ -47,11 +48,15 @@ }, | ||
"devDependencies": { | ||
"@nestjs/common": "^4.6.4", | ||
"@nestjs/core": "^4.6.4", | ||
"@nestjs/testing": "^4.6.4", | ||
"@nestjs/common": "^7.4.4", | ||
"@nestjs/core": "^7.4.4", | ||
"@nestjs/platform-express": "^7.4.4", | ||
"@nestjs/testing": "^7.4.4", | ||
"@types/mocha": "^5.2.6", | ||
"@types/node": "^9.6.50", | ||
"@types/supertest": "^2.0.7", | ||
"@types/node": "^9.6.57", | ||
"@types/supertest": "^2.0.10", | ||
"axios": "^0.20.0", | ||
"axios-time": "^1.0.0", | ||
"body-parser": "^1.18.3", | ||
"chai": "^4.2.0", | ||
"coveralls": "^3.0.0", | ||
"chai-as-promised": "^7.1.1", | ||
"coveralls": "^3.1.0", | ||
"doctoc": "^1.4.0", | ||
@@ -61,3 +66,3 @@ "eslint": "^6.8.0", | ||
"eslint-plugin-chai-friendly": "^0.5.0", | ||
"eslint-plugin-import": "^2.20.2", | ||
"eslint-plugin-import": "^2.22.0", | ||
"eslint-plugin-mocha": "^6.3.0", | ||
@@ -68,18 +73,17 @@ "eslint-plugin-node": "^11.1.0", | ||
"express": "^4.16.4", | ||
"koa": "^2.7.0", | ||
"koa": "^2.13.0", | ||
"koa-bodyparser": "^4.2.1", | ||
"koa-router": "^7.4.0", | ||
"lodash.clonedeep": "^4.5.0", | ||
"mocha": "^5.2.0", | ||
"mocha": "^8.1.3", | ||
"nock": "^10.0.6", | ||
"node-mocks-http": "^1.7.3", | ||
"nyc": "^15.0.1", | ||
"node-mocks-http": "^1.9.0", | ||
"nyc": "^15.1.0", | ||
"prom-client": "^12.0.0", | ||
"reflect-metadata": "0.1.10", | ||
"reflect-metadata": "^0.1.13", | ||
"request": "^2.88.0", | ||
"request-promise-native": "^1.0.7", | ||
"request-promise-native": "^1.0.9", | ||
"rewire": "^4.0.1", | ||
"rxjs": "^5.5.12", | ||
"sinon": "^5.0.10", | ||
"sleep": "^6.1.0", | ||
"stryker": "^0.30.1", | ||
@@ -92,3 +96,3 @@ "stryker-api": "^0.21.5", | ||
"ts-node": "^7.0.1", | ||
"typescript": "^3.3.3" | ||
"typescript": "^3.9.7" | ||
}, | ||
@@ -95,0 +99,0 @@ "repository": { |
@@ -25,2 +25,3 @@ # Prometheus API Monitoring | ||
- [request-promise-native](#request-promise-native) | ||
- [axios](#axios) | ||
- [Test](#test) | ||
@@ -170,2 +171,3 @@ - [Usage in koa](#usage-in-koa) | ||
**Notes:** | ||
@@ -180,2 +182,20 @@ 1. 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. | ||
#### axios | ||
```js | ||
const axios = require('axios'); | ||
const axiosTime = require('axios-time'); | ||
axiosTime(axios); | ||
try { | ||
const response = await axios({ baseURL: 'http://www.google.com', method: 'get', url: '/' }); | ||
Collector.collect(response); | ||
} catch (error) { | ||
Collector.collect(error); | ||
} | ||
``` | ||
**Notes:** | ||
* In order to collect metrics from axios client the [`axios-time`](https://www.npmjs.com/package/axios-time) package is required. | ||
## Usage in koa | ||
@@ -182,0 +202,0 @@ This 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) |
const Prometheus = require('prom-client'); | ||
const utils = require('./utils'); | ||
const get = require('lodash.get'); | ||
let southboundResponseTimeHistogram, southboundClientErrors = null; | ||
@@ -15,2 +17,4 @@ let projectName; | ||
const OBSERVER_TYPES = ['total', 'socket', 'lookup', 'connect']; | ||
class HttpMetricsCollector { | ||
@@ -35,7 +39,4 @@ constructor(options){ | ||
if (response.timings) { | ||
response.request.metrics = response.request.metrics || {}; | ||
southboundResponseTimeHistogram.observe({ target: response.request.metrics.target || response.request.originalHost, method: response.request.method, route: response.request.metrics.route || response.request.path, status_code: response.statusCode, type: 'total' }, response.timingPhases.total / 1000); | ||
southboundResponseTimeHistogram.observe({ target: response.request.metrics.target || response.request.originalHost, method: response.request.method, route: response.request.metrics.route || response.request.path, status_code: response.statusCode, type: 'socket' }, response.timingPhases.wait / 1000); // timings.socket | ||
southboundResponseTimeHistogram.observe({ target: response.request.metrics.target || response.request.originalHost, method: response.request.method, route: response.request.metrics.route || response.request.path, status_code: response.statusCode, type: 'lookup' }, response.timingPhases.dns / 1000); // timings.lookup - timings.socket | ||
southboundResponseTimeHistogram.observe({ target: response.request.metrics.target || response.request.originalHost, method: response.request.method, route: response.request.metrics.route || response.request.path, status_code: response.statusCode, type: 'connect' }, response.timingPhases.tcp / 1000); // timings.connect - timings.socket | ||
const responseData = extractResponseData(response); | ||
addObservers(southboundResponseTimeHistogram, responseData); | ||
} | ||
@@ -45,2 +46,50 @@ } | ||
function addObservers(southboundResponseTimeHistogram, responseData) { | ||
const { target, method, route, status_code, timings } = responseData; | ||
OBSERVER_TYPES.forEach(type => { | ||
if (typeof responseData.timings[type] !== 'undefined') { | ||
southboundResponseTimeHistogram.observe({ target, method, route, status_code, type }, timings[type]); | ||
} | ||
}); | ||
} | ||
function extractResponseData(response) { | ||
let status_code, route, method, target, timings; | ||
// check if response client is axios | ||
if (isAxiosResponse(response)) { | ||
status_code = response.status; | ||
method = response.config.method.toUpperCase(); | ||
route = get(response, 'config.metrics.route', response.config.url); | ||
target = get(response, 'config.metrics.target', response.config.baseURL); | ||
timings = { | ||
total: response.timings.elapsedTime / 1000 | ||
}; | ||
} else { // response is request-promise | ||
status_code = response.statusCode; | ||
method = response.request.method; | ||
route = get(response, 'request.metrics.route', response.request.path); | ||
target = get(response, 'request.metrics.target', response.request.originalHost); | ||
timings = { | ||
total: response.timingPhases.total / 1000, | ||
socket: response.timingPhases.wait / 1000, | ||
lookup: response.timingPhases.dns / 1000, | ||
connect: response.timingPhases.tcp / 1000 | ||
}; | ||
} | ||
return { | ||
target, | ||
method, | ||
route, | ||
status_code, | ||
timings | ||
}; | ||
} | ||
function isAxiosResponse(response) { | ||
return response.config && response.hasOwnProperty('data'); | ||
} | ||
function _init(options = {}) { | ||
@@ -84,2 +133,2 @@ let metricNames = { | ||
_collectHttpTiming(res, southboundResponseTimeHistogram, southboundClientErrors); | ||
}; | ||
}; |
45812
2.66%458
9.05%263
8.23%7
16.67%46
6.98%+ Added
+ Added
Updated
Updated