UNPKG

openhim-core

Version:

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

206 lines (161 loc) 7.14 kB
moment = require 'moment' logger = require 'winston' events = require '../model/events' messageStore = require '../middleware/messageStore' config = require '../config/config' config.events = config.get('events') if !config.events # maybe we're using outdated config config.events = config.get('visualizer') config.events.normalizationBuffer = config.events.orchestrationTsBufferMillis enableTSNormalization = config.events.enableTSNormalization ? false if enableTSNormalization is true normalizationBuffer = 100 else normalizationBuffer = 0 timestampAsMillis = (ts) -> moment(new Date(ts)).valueOf() # Determine the difference between baseTS and the earliest timestamp # present in a collection of routes (buffered for normalization) calculateEarliestRouteDiff = (baseTS, routes) -> earliestTS = 0 for route in routes ts = timestampAsMillis route.request.timestamp if earliestTS < ts then earliestTS = ts tsDiff = baseTS - earliestTS tsDiff += normalizationBuffer return tsDiff determineStatusType = (statusCode) -> status = 'success' if 500 <= statusCode <= 599 status = 'error' return status exports.saveEvents = saveEvents = (trxEvents, callback) -> now = new Date event.created = now for event in trxEvents # bypass mongoose for quick batch inserts # index needs to be ensured manually since the collection might not already exist events.Event.collection.ensureIndex { created: 1 }, { expireAfterSeconds: 3600 }, -> events.Event.collection.insert trxEvents, (err) -> return if err then callback err else callback() createRouteEvents = (dst, transactionId, channel, route, type, tsAdjustment, autoRetryAttempt) -> if route?.request?.timestamp? and route?.response?.timestamp? startTS = timestampAsMillis route.request.timestamp endTS = timestampAsMillis route.response.timestamp if enableTSNormalization is true startTS = startTS + tsAdjustment endTS = endTS + tsAdjustment if startTS > endTS then startTS = endTS dst.push channelID: channel._id transactionID: transactionId normalizedTimestamp: startTS type: type event: 'start' name: route.name mediator: route.mediatorURN autoRetryAttempt: autoRetryAttempt dst.push channelID: channel._id transactionID: transactionId normalizedTimestamp: endTS type: type event: 'end' name: route.name mediator: route.mediatorURN status: route.response.status statusType: determineStatusType route.response.status autoRetryAttempt: autoRetryAttempt createChannelStartEvent = (dst, transactionId, requestTimestamp, channel, autoRetryAttempt) -> dst.push channelID: channel._id transactionID: transactionId normalizedTimestamp: timestampAsMillis requestTimestamp type: 'channel' event: 'start' name: channel.name autoRetryAttempt: autoRetryAttempt createChannelEndEvent = (dst, transactionId, requestTimestamp, channel, response, autoRetryAttempt) -> startTS = timestampAsMillis requestTimestamp endTS = timestampAsMillis response.timestamp if endTS < startTS then endTS = startTS 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: autoRetryAttempt createPrimaryRouteEvents = (dst, transactionId, requestTimestamp, channel, routeName, mediatorURN, response, autoRetryAttempt) -> startTS = timestampAsMillis requestTimestamp dst.push channelID: channel._id transactionID: transactionId normalizedTimestamp: startTS type: 'primary' event: 'start' name: routeName mediator: mediatorURN autoRetryAttempt: autoRetryAttempt endTS = timestampAsMillis response.timestamp if endTS < startTS then endTS = startTS 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: autoRetryAttempt createOrchestrationEvents = (dst, transactionId, requestTimestamp, channel, orchestrations) -> if requestTimestamp startTS = timestampAsMillis requestTimestamp tsDiff = calculateEarliestRouteDiff startTS, orchestrations createRouteEvents dst, transactionId, channel, orch, 'orchestration', tsDiff for orch in orchestrations exports.createSecondaryRouteEvents = createSecondaryRouteEvents = (dst, transactionId, requestTimestamp, channel, routes) -> startTS = timestampAsMillis requestTimestamp tsDiff = calculateEarliestRouteDiff startTS, routes for route in routes createRouteEvents dst, transactionId, channel, route, 'route', tsDiff if route.orchestrations # find TS difference tsDiff = calculateEarliestRouteDiff startTS, route.orchestrations createRouteEvents dst, transactionId, channel, orch, 'orchestration', tsDiff for orch in route.orchestrations exports.createTransactionEvents = (dst, transaction, channel) -> getPrimaryRouteName = () -> for r in channel.routes if r.primary then return r.name return null timestamp = if transaction.request?.timestamp then transaction.request.timestamp else new Date() if transaction.request and 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 createSecondaryRouteEvents dst, transaction._id, timestamp, channel, transaction.routes exports.koaMiddleware = (next) -> ctx = this runAsync = (method) -> do (ctx) -> f = -> method ctx, (err) -> logger.err err if err setTimeout f, 0 runAsync (ctx, done) -> logger.debug "Storing channel start event for transaction: #{ctx.transactionId}" trxEvents = [] createChannelStartEvent trxEvents, ctx.transactionId, ctx.requestTimestamp, ctx.authorisedChannel, ctx.currentAttempt saveEvents trxEvents, done yield next runAsync (ctx, done) -> logger.debug "Storing channel end and primary routes events for transaction: #{ctx.transactionId}" trxEvents = [] mediatorURN = ctx.mediatorResponse?['x-mediator-urn'] orchestrations = ctx.mediatorResponse?.orchestrations 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 saveEvents trxEvents, done