UNPKG

openhim-core

Version:

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

283 lines (225 loc) 9.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.saveEvents = saveEvents; exports.createSecondaryRouteEvents = createSecondaryRouteEvents; exports.createTransactionEvents = createTransactionEvents; exports.koaMiddleware = koaMiddleware; var _moment = _interopRequireDefault(require("moment")); var _winston = _interopRequireDefault(require("winston")); var events = _interopRequireWildcard(require("../model/events")); var _config = require("../config"); function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } _config.config.events = _config.config.get('events'); let normalizationBuffer; if (!_config.config.events) { // maybe we're using outdated config _config.config.events = _config.config.get('visualizer'); _config.config.events.normalizationBuffer = _config.config.events.orchestrationTsBufferMillis; } const enableTSNormalization = _config.config.events.enableTSNormalization != null ? _config.config.events.enableTSNormalization : false; if (enableTSNormalization === true) { normalizationBuffer = 100; } else { normalizationBuffer = 0; } const timestampAsMillis = ts => (0, _moment.default)(new Date(ts)).valueOf(); // Determine the difference between baseTS and the earliest timestamp // present in a collection of routes (buffered for normalization) function calculateEarliestRouteDiff(baseTS, routes) { let earliestTS = 0; for (const route of Array.from(routes)) { const ts = timestampAsMillis(route.request.timestamp); if (earliestTS < ts) { earliestTS = ts; } } let tsDiff = baseTS - earliestTS; tsDiff += normalizationBuffer; return tsDiff; } function determineStatusType(statusCode) { let status = 'success'; if (statusCode >= 500 && statusCode <= 599) { status = 'error'; } return status; } function saveEvents(trxEvents, callback) { const now = new Date(); for (const event of Array.from(trxEvents)) { event.created = now; } // bypass mongoose for quick batch inserts return events.EventModel.collection.insertMany(trxEvents, err => callback(err)); } function createRouteEvents(dst, transactionId, channel, route, type, tsAdjustment, autoRetryAttempt) { if (route != null && route.request != null && route.request.timestamp != null && route.response != null && route.response.timestamp != null) { let startTS = timestampAsMillis(route.request.timestamp); let endTS = timestampAsMillis(route.response.timestamp); if (enableTSNormalization === true) { startTS += tsAdjustment; endTS += tsAdjustment; } if (startTS > endTS) { startTS = endTS; } dst.push({ channelID: channel._id, transactionID: transactionId, normalizedTimestamp: startTS, type, event: 'start', name: route.name, mediator: route.mediatorURN, autoRetryAttempt }); return dst.push({ channelID: channel._id, transactionID: transactionId, normalizedTimestamp: endTS, type, event: 'end', name: route.name, mediator: route.mediatorURN, status: route.response.status, statusType: determineStatusType(route.response.status), autoRetryAttempt }); } } function createChannelStartEvent(dst, transactionId, requestTimestamp, channel, autoRetryAttempt) { return dst.push({ channelID: channel._id, transactionID: transactionId, normalizedTimestamp: timestampAsMillis(requestTimestamp), type: 'channel', event: 'start', name: channel.name, autoRetryAttempt }); } function createChannelEndEvent(dst, transactionId, requestTimestamp, channel, response, autoRetryAttempt) { const startTS = timestampAsMillis(requestTimestamp); let endTS = timestampAsMillis(response.timestamp); if (endTS < startTS) { endTS = startTS; } return dst.push({ channelID: channel._id, transactionID: transactionId, normalizedTimestamp: endTS + normalizationBuffer, type: 'channel', event: 'end', name: channel.name, status: response.status, statusType: determineStatusType(response.status), autoRetryAttempt }); } function createPrimaryRouteEvents(dst, transactionId, requestTimestamp, channel, routeName, mediatorURN, response, autoRetryAttempt) { const startTS = timestampAsMillis(requestTimestamp); dst.push({ channelID: channel._id, transactionID: transactionId, normalizedTimestamp: startTS, type: 'primary', event: 'start', name: routeName, mediator: mediatorURN, autoRetryAttempt }); let endTS = timestampAsMillis(response.timestamp); if (endTS < startTS) { endTS = startTS; } return dst.push({ channelID: channel._id, transactionID: transactionId, normalizedTimestamp: endTS + normalizationBuffer, type: 'primary', event: 'end', name: routeName, status: response.status, statusType: determineStatusType(response.status), mediator: mediatorURN, autoRetryAttempt }); } function createOrchestrationEvents(dst, transactionId, requestTimestamp, channel, orchestrations) { let tsDiff; if (requestTimestamp) { const startTS = timestampAsMillis(requestTimestamp); tsDiff = calculateEarliestRouteDiff(startTS, orchestrations); } return Array.from(orchestrations).map(orch => createRouteEvents(dst, transactionId, channel, orch, 'orchestration', tsDiff)); } function createSecondaryRouteEvents(dst, transactionId, requestTimestamp, channel, routes) { const startTS = timestampAsMillis(requestTimestamp); let tsDiff = calculateEarliestRouteDiff(startTS, routes); const result = []; for (const route of Array.from(routes)) { let item; createRouteEvents(dst, transactionId, channel, route, 'route', tsDiff); if (route.orchestrations) { // find TS difference tsDiff = calculateEarliestRouteDiff(startTS, route.orchestrations); item = Array.from(route.orchestrations).map(orch => createRouteEvents(dst, transactionId, channel, orch, 'orchestration', tsDiff)); } result.push(item); } return result; } function createTransactionEvents(dst, transaction, channel) { function getPrimaryRouteName() { for (const r of Array.from(channel.routes)) { if (r.primary) { return r.name; } } return null; } const timestamp = (transaction.request != null ? transaction.request.timestamp : undefined) ? transaction.request.timestamp : new Date(); if (transaction.request && transaction.response) { createPrimaryRouteEvents(dst, transaction._id, timestamp, channel, getPrimaryRouteName(), null, transaction.response); } if (transaction.orchestrations) { createOrchestrationEvents(dst, transaction._id, timestamp, channel, transaction.orchestrations); } if (transaction.routes) { return createSecondaryRouteEvents(dst, transaction._id, timestamp, channel, transaction.routes); } } async function koaMiddleware(ctx, next) { const runAsync = method => { const f = () => method(ctx, err => { if (err) { return _winston.default.error(err); } }); return setTimeout(f, 0); }; runAsync((ctx, done) => { _winston.default.debug(`Storing channel start event for transaction: ${ctx.transactionId}`); const trxEvents = []; createChannelStartEvent(trxEvents, ctx.transactionId, ctx.requestTimestamp, ctx.authorisedChannel, ctx.currentAttempt); return saveEvents(trxEvents, done); }); await next(); runAsync((ctx, done) => { _winston.default.debug(`Storing channel end and primary routes events for transaction: ${ctx.transactionId}`); const trxEvents = []; const mediatorURN = ctx.mediatorResponse != null ? ctx.mediatorResponse['x-mediator-urn'] : undefined; const orchestrations = ctx.mediatorResponse != null ? ctx.mediatorResponse.orchestrations : undefined; if (ctx.primaryRoute != null) { createPrimaryRouteEvents(trxEvents, ctx.transactionId, ctx.requestTimestamp, ctx.authorisedChannel, ctx.primaryRoute.name, mediatorURN, ctx.response, ctx.currentAttempt); } if (orchestrations) { createOrchestrationEvents(trxEvents, ctx.transactionId, ctx.requestTimestamp, ctx.authorisedChannel, orchestrations, ctx.currentAttempt); } createChannelEndEvent(trxEvents, ctx.transactionId, ctx.requestTimestamp, ctx.authorisedChannel, ctx.response, ctx.currentAttempt); return saveEvents(trxEvents, done); }); } //# sourceMappingURL=events.js.map