'use strict'; const _ = require('lodash'); const assert = require('assert'); const moment = require('moment'); const SAPPassport = require('@sap/e2e-trace').Passport; const consts = require('../constants'); const Logger = require('../logging-tools/Logger'); const NetworkLogger = require('../logging-tools/NetworkLogger'); const Tracer = require('../logging-tools/Tracer'); class LogContext { constructor(appContext, options) { this._timeCreated = moment(); this._appContext = appContext; this._options = processOptions(options); this._sapPassport = parseSAPPassport(this); } getAppContext() { return this._appContext; } getLogger(category) { return new Logger(this, category); } getTracer(location) { return new Tracer(this, location); } get id() { return get(this, 'id', resolveId); } get correlationId() { return get(this, 'correlationId', resolveCorrelationId); } enableNetworkLog(res) { assert(_.isObject(res), 'Provided response should be an object'); assert(this._options.hasOwnProperty('req'), 'The "req" property should be set to context in advance in order to enable network log'); this._options.res = res; if (this._appContext._env.loggingOff) { return; } res.on('finish', () => { const networkLogger = new NetworkLogger(this); networkLogger.info(); }); } } function processOptions(options) { assert(options === undefined || _.isObject(options), 'Expected an object for log context options (if provided)'); options = _.extend({}, options); assert(options.id === undefined || _.isString(options.id), '"id" (if provided) should be a string'); assert(options.correlationId === undefined || _.isString(options.correlationId), '"correlationId" (if provided) should be a string'); assert(options.req === undefined || _.isObject(options.req), '"req" (if provided) should be an object'); return options; } function get(ctx, prop, fnResolve) { const options = ctx._options; if (!options.hasOwnProperty(prop)) { options[prop] = fnResolve(ctx); } return options[prop]; } function resolveId(ctx) { const req = ctx._options.req; return (req && (req.headers['x-request-id'] || req.headers['x-vcap-request-id'])) || ctx._appContext._idGen.nextId(); } function resolveCorrelationId(ctx) { const req = ctx._options.req; return (req && req.headers['x-correlationid']) || ctx.id; } function parseSAPPassport(ctx) { const req = ctx._options.req; if (!req || !req.headers[SAPPassport.HEADER_NAME]) { return; } try { return new SAPPassport(req.headers[SAPPassport.HEADER_NAME]).readUniqueIdentifiers(); } catch (err) { ctx.getLogger(consts.LIB_CATEGORY).error(err, 'Could not parse SAP Passport'); } } module.exports = LogContext;