UNPKG

@dyihoon90/glogging

Version:

HTTP request logging middleware & transaction function decorator for express, using winston

194 lines 9.49 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.LoggedClass = LoggedClass; exports.LoggedMethod = LoggedMethod; exports.LoggedFunction = LoggedFunction; var GLogger_auditLogger_1 = require("./GLogger.auditLogger"); var ObjUtils_1 = require("./utils/ObjUtils"); /** * Default options for transaction logging */ var DEFAULT_TXN_LOGGING_OPTIONS = { toLogResults: false, toLogSuccessTxn: true }; /** * #### Class decorator function that adds logging to all class methods * - All class methods _must_ take in an IExpressRequest object (extended from express.Request) as first parameter * - Creates success audit log of level `info` on return * - Creates fail audit log of level `warn` on error thrown * - Modifies all class methods except the constructor method * - Arrow functions are _not_ considered class methods * @param logger a GLogger instance * @param metadata metadata including transaction category, transaction module, & optional filename * @param options Optional option parameter * - toLogResult - whether to log the return value of the decorated function. Defaults to false. * - redactedProperties(optional) - if `toLogResult` set to true, use this array for properties you don't want logged out. * @example result = [{key1: 'a',key2: 'b'}, {key1: 'c',key2: 'd'}]; redactedProperties = ['key1', 0]; loggedResult = [{key2: 'd'}] */ function LoggedClass(logger, metadata, options) { return function (target) { for (var _i = 0, _a = Reflect.ownKeys(target.prototype); _i < _a.length; _i++) { var propertyName = _a[_i]; var descriptor = Reflect.getOwnPropertyDescriptor(target.prototype, propertyName); var isMethod = (descriptor === null || descriptor === void 0 ? void 0 : descriptor.value) instanceof Function; if (!isMethod || propertyName === 'constructor') { continue; } if (typeof (descriptor === null || descriptor === void 0 ? void 0 : descriptor.value) === 'function') { Object.defineProperty(target.prototype, propertyName, LoggedMethod(logger, metadata, options)(target, propertyName, descriptor)); } // Object.defineProperty(target.prototype, propertyName, descriptor); } }; } /** * #### Method decorator function that adds logging to method * - Methods _must_ take in an IExpressRequest object (extended from express.Request) as first parameter * - Creates success audit log of level `info` on return * - Creates fail audit log of level `warn` on error thrown * - Modifies all class methods except the constructor method * - Arrow functions are _not_ considered class methods * @param logger a GLogger instance * @param metadata metadata including transaction category, transaction module, & optional filename * @param options Optional option parameter * - toLogResult - whether to log the return value of the decorated function. Defaults to false. * - redactedProperties(optional) - if `toLogResult` set to true, use this array for properties you don't want logged out. * @example result = [{key1: 'a',key2: 'b'}, {key1: 'c',key2: 'd'}]; redactedProperties = ['key1', 0]; loggedResult = [{key2: 'd'}] */ function LoggedMethod(logger, metadata, options) { return function (target, key, descriptor) { var originalMethod = descriptor.value; if (typeof originalMethod !== 'function') { throw new TypeError("@LoggedMethod decorator can only be applied to methods not: ".concat(typeof originalMethod)); } return { configurable: false, get: function () { var _this = this; if (this === target.prototype) { return originalMethod; } descriptor.value = function (req) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } return executeFunctionWithLogs.apply(void 0, __spreadArray([logger, metadata, originalMethod.bind(_this), key, req, options], args, false)); }; var boundFn = descriptor.value; return boundFn; }, set: function (value) { descriptor.value = value; } }; }; } /** * #### decorator function that adds logging to a normal function / arrow function * - Function must take in an IExpressRequest object (extended from express.Request) as first parameter * - Creates success audit log of level `info` on return * - Creates fail audit log of level `warn` on error thrown * @param logger a GLogger instance * @param metadata metadata including transaction category, transaction module, & optional filename * @param options Optional option parameter * - toLogResult - whether to log the return value of the decorated function. Defaults to false. * - redactedProperties(optional) - if `toLogResult` set to true, use this array for properties you don't want logged out. * @example result = [{key1: 'a',key2: 'b'}, {key1: 'c',key2: 'd'}]; redactedProperties = ['key1', 0]; loggedResult = [{key2: 'd'}] */ function LoggedFunction(logger, metadata, options) { return function (decoratedFunc, req) { var args = []; for (var _i = 2; _i < arguments.length; _i++) { args[_i - 2] = arguments[_i]; } return executeFunctionWithLogs.apply(void 0, __spreadArray([logger, metadata, decoratedFunc, decoratedFunc.name, req, options], args, false)); }; } /** * Executes a function and logs the result * @param logger a GLogger instance * @param metadata metadata including transaction category, transaction module, & optional filename * @param decoratedFunc the function to execute * @param decoratedFuncName the name of the decorated function * @param req the request object * @param options optional logging options * @param args the arguments to pass to the decorated function * @returns */ function executeFunctionWithLogs(logger, _a, decoratedFunc, decoratedFuncName, req, options) { var _b; var trxCategory = _a.trxCategory, trxModule = _a.trxModule, filename = _a.filename; var args = []; for (var _i = 6; _i < arguments.length; _i++) { args[_i - 6] = arguments[_i]; } var startTime = new Date().getTime(); var fnName = String(decoratedFuncName); var auditLoggerInstance = new GLogger_auditLogger_1.GLoggerAuditLogger(logger); var logFailure = auditLoggerInstance.logTransactionFailure.bind(auditLoggerInstance, { req: req }, { trxCategory: trxCategory, filename: filename, trxName: fnName, trxModule: trxModule }, startTime); try { var promiseOrValue = decoratedFunc.apply(void 0, __spreadArray([req], args, false)); var opt_1 = __assign(__assign({}, DEFAULT_TXN_LOGGING_OPTIONS), options); var logSuccess_1 = auditLoggerInstance.logTransactionSuccess.bind(auditLoggerInstance, "Transaction: ".concat(fnName, " success"), { req: req }, { trxCategory: trxCategory, filename: filename, trxName: fnName, trxModule: trxModule }, startTime); var redact_1 = ObjUtils_1.redactProperties.bind(null, (_b = opt_1.redactedProperties) !== null && _b !== void 0 ? _b : []); // Scenario where decoratedFunc is asynchronous returning Promise if (promiseOrValue instanceof Promise) { return promiseOrValue .then(function (result) { if (opt_1.toLogSuccessTxn) { if (opt_1.toLogResults) { opt_1.redactedProperties && result ? logSuccess_1(redact_1(result)) : logSuccess_1(result); } else { logSuccess_1(); } } return result; }) .catch(function (e) { logFailure(e); throw e; }); } // Scenario where decoratedFunc is synchronous returning value // Why separate? if we `await` sync decoratedFunc, return value gets casted into Promise, becoming async if (opt_1.toLogSuccessTxn) { if (opt_1.toLogResults) { opt_1.redactedProperties && promiseOrValue ? logSuccess_1(redact_1(promiseOrValue)) : logSuccess_1(promiseOrValue); } else { logSuccess_1(); } } return promiseOrValue; } catch (e) { logFailure(e); throw e; } } //# sourceMappingURL=GLogger.decorator.js.map