UNPKG

openhim-core

Version:

The OpenHIM core application that provides logging and routing of http requests

191 lines (171 loc) 4.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.recordTransactionMetrics = recordTransactionMetrics; exports.calculateMetrics = calculateMetrics; var _model = require("./model"); var _moment = _interopRequireDefault(require("moment")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const TRANSACTION_STATUS_KEYS = { Processing: 'processing', Successful: 'successful', Completed: 'completed', 'Completed with error(s)': 'completedWithErrors', Failed: 'failed' }; const METRIC_UPDATE_OPTIONS = { upsert: true, setDefaultsOnInsert: true }; async function recordTransactionMetric(fields, update) { return _model.MetricModel.updateOne(fields, Object.assign({}, update, { $setOnInsert: fields }), METRIC_UPDATE_OPTIONS); } async function recordTransactionMetrics(transaction) { if (!transaction.response || !transaction.response.timestamp || !(transaction.response.timestamp instanceof Date)) { // Don't record metrics if there is no response i.e. an error // or if the response does not have a timestamp // or if the timestamp isnt an instance of Date return; } const responseTime = transaction.response.timestamp.getTime() - transaction.request.timestamp.getTime(); const statusKey = TRANSACTION_STATUS_KEYS[transaction.status]; const update = { $inc: { requests: 1, responseTime, [statusKey]: 1 }, $min: { minResponseTime: responseTime }, $max: { maxResponseTime: responseTime } }; // Update metrics for the minute bucket const minuteUpdate = recordTransactionMetric({ type: _model.METRIC_TYPE_MINUTE, startTime: (0, _moment.default)(transaction.request.timestamp).startOf('minute').toDate(), channelID: transaction.channelID }, update); // Update metrics for the hour bucket const hourUpdate = recordTransactionMetric({ type: _model.METRIC_TYPE_HOUR, startTime: (0, _moment.default)(transaction.request.timestamp).startOf('hour').toDate(), channelID: transaction.channelID }, update); // Update metrics for the day bucket const dayUpdate = recordTransactionMetric({ type: _model.METRIC_TYPE_DAY, startTime: (0, _moment.default)(transaction.request.timestamp).startOf('day').toDate(), channelID: transaction.channelID }, update); await Promise.all([minuteUpdate, hourUpdate, dayUpdate]); } const METRICS_GROUPINGS = { requests: { $sum: '$requests' }, responseTime: { $sum: '$responseTime' }, minResponseTime: { $min: '$minResponseTime' }, maxResponseTime: { $max: '$maxResponseTime' }, successful: { $sum: '$successful' }, failed: { $sum: '$failed' }, processing: { $sum: '$processing' }, completed: { $sum: '$completed' }, completedWithErrors: { $sum: '$completedWithErrors' } }; /** * Calculate metrics for all channels, filtered by the given filters. * * @param {Object} filters * @param {Date} filters.startDate Start date * @param {Date} filters.endDate End date * @param {Object[]} filters.channels Array of channel IDs * @param {String} [filters.timeSeries] Time period * @param {boolean} [groupByChannel=true] Whether to group metrics by channel */ async function calculateMetrics(filters, groupByChannel = true) { const pipeline = [{ $match: { startTime: { $gte: filters.startDate, $lte: filters.endDate }, channelID: { $in: filters.channels }, type: mapTimeSeriesToMetricType(filters.timeSeries) } }]; if (!groupByChannel) { // Combine metrics for different channels if not grouping by channel pipeline.push({ $group: Object.assign({}, METRICS_GROUPINGS, { _id: { startTime: '$startTime', type: '$type' }, startTime: { $first: '$startTime' }, type: { $first: '$type' } }) }); } if (!filters.timeSeries) { // Combine metrics by channel if not grouping by time series pipeline.push({ $group: Object.assign({}, METRICS_GROUPINGS, { _id: { channelID: '$channelID' }, channelID: { $first: '$channelID' } }) }); } pipeline.push({ $sort: { startTime: 1, channelID: 1 } }); return _model.MetricModel.aggregate(pipeline); } function mapTimeSeriesToMetricType(timeSeries) { switch (timeSeries) { case 'minute': return _model.METRIC_TYPE_MINUTE; case 'hour': return _model.METRIC_TYPE_HOUR; case 'day': case 'week': case 'month': case 'year': return _model.METRIC_TYPE_DAY; default: // Should be the lowest metric type which does not expire return _model.METRIC_TYPE_HOUR; } } //# sourceMappingURL=metrics.js.map