prometheus-api-metrics
Version:
API and process monitoring with Prometheus for Node.js micro-service
98 lines • 4.89 kB
JavaScript
'use strict';
const Prometheus = require('prom-client');
require('pkginfo')(module, ['name']);
const debug = require('debug')(module.exports.name);
const utils = require('./utils');
const ExpressMiddleware = require('./express-middleware');
const KoaMiddleware = require('./koa-middleware');
const setupOptions = {};
module.exports = (appVersion, projectName, framework = 'express') => {
return (options = {}) => {
const { metricsPath, defaultMetricsInterval = 10000, durationBuckets, requestSizeBuckets, responseSizeBuckets, useUniqueHistogramName, metricsPrefix, excludeRoutes, includeQueryParams, additionalLabels = [], extractAdditionalLabelValuesFn } = options;
debug(`Init metrics middleware with options: ${JSON.stringify(options)}`);
setupOptions.metricsRoute = utils.validateInput({
input: metricsPath,
isValidInputFn: utils.isString,
defaultValue: '/metrics',
errorMessage: 'metricsPath should be an string'
});
setupOptions.excludeRoutes = utils.validateInput({
input: excludeRoutes,
isValidInputFn: utils.isArray,
defaultValue: [],
errorMessage: 'excludeRoutes should be an array'
});
setupOptions.includeQueryParams = includeQueryParams;
setupOptions.defaultMetricsInterval = defaultMetricsInterval;
setupOptions.additionalLabels = utils.validateInput({
input: additionalLabels,
isValidInputFn: utils.isArray,
defaultValue: [],
errorMessage: 'additionalLabels should be an array'
});
setupOptions.extractAdditionalLabelValuesFn = utils.validateInput({
input: extractAdditionalLabelValuesFn,
isValidInputFn: utils.isFunction,
defaultValue: () => ({}),
errorMessage: 'extractAdditionalLabelValuesFn should be a function'
});
const metricNames = utils.getMetricNames({
http_request_duration_seconds: 'http_request_duration_seconds',
app_version: 'app_version',
http_request_size_bytes: 'http_request_size_bytes',
http_response_size_bytes: 'http_response_size_bytes',
defaultMetricsPrefix: ''
}, useUniqueHistogramName, metricsPrefix, projectName);
Prometheus.collectDefaultMetrics({ timeout: defaultMetricsInterval, prefix: `${metricNames.defaultMetricsPrefix}` });
PrometheusRegisterAppVersion(appVersion, metricNames.app_version);
const metricLabels = [
'method',
'route',
'code',
...additionalLabels
].filter(Boolean);
const defaultDurationSecondsBuckets = [0.001, 0.005, 0.015, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5];
const defaultSizeBytesBuckets = [5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000];
setupOptions.responseTimeHistogram = Prometheus.register.getSingleMetric(metricNames.http_request_duration_seconds) || new Prometheus.Histogram({
name: metricNames.http_request_duration_seconds,
help: 'Duration of HTTP requests in seconds',
labelNames: metricLabels,
buckets: durationBuckets || defaultDurationSecondsBuckets
});
setupOptions.requestSizeHistogram = Prometheus.register.getSingleMetric(metricNames.http_request_size_bytes) || new Prometheus.Histogram({
name: metricNames.http_request_size_bytes,
help: 'Size of HTTP requests in bytes',
labelNames: metricLabels,
buckets: requestSizeBuckets || defaultSizeBytesBuckets
});
setupOptions.responseSizeHistogram = Prometheus.register.getSingleMetric(metricNames.http_response_size_bytes) || new Prometheus.Histogram({
name: metricNames.http_response_size_bytes,
help: 'Size of HTTP response in bytes',
labelNames: metricLabels,
buckets: responseSizeBuckets || defaultSizeBytesBuckets
});
return frameworkMiddleware(framework);
};
};
function PrometheusRegisterAppVersion(appVersion, metricName) {
const version = new Prometheus.Gauge({
name: metricName,
help: 'The service version by package.json',
labelNames: ['version', 'major', 'minor', 'patch']
});
const [major, minor, patch] = appVersion.split('.').map(Number);
version.labels(appVersion, major, minor, patch).set(1);
}
function frameworkMiddleware(framework) {
switch (framework) {
case 'koa': {
const middleware = new KoaMiddleware(setupOptions);
return middleware.middleware.bind(middleware);
}
default: {
const middleware = new ExpressMiddleware(setupOptions);
return middleware.middleware.bind(middleware);
}
}
}
//# sourceMappingURL=metrics-middleware.js.map