UNPKG

@imqueue/core

Version:

Simple JSON-based messaging queue for inter service communication

224 lines 7.27 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.IMQ_LOG_TIME_FORMAT = exports.IMQ_LOG_ARGS = exports.IMQ_LOG_TIME = exports.IMQ_LOG_LEVEL = exports.LogLevel = void 0; exports.verifyLogLevel = verifyLogLevel; exports.logDebugInfo = logDebugInfo; exports.profile = profile; /*! * Decorator: @profile * * I'm Queue Software Project * Copyright (C) 2025 imqueue.com <support@imqueue.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. * * If you want to use this code in a closed source (commercial) project, you can * purchase a proprietary commercial license. Please contact us at * <support@imqueue.com> to get commercial licensing options. */ require("reflect-metadata"); var LogLevel; (function (LogLevel) { // noinspection JSUnusedGlobalSymbols LogLevel["LOG"] = "log"; LogLevel["INFO"] = "info"; LogLevel["WARN"] = "warn"; LogLevel["ERROR"] = "error"; })(LogLevel || (exports.LogLevel = LogLevel = {})); /** * Checks if log level is set to proper value or returns default one * * @param {*} level * @return {LogLevel} */ function verifyLogLevel(level) { switch (level) { case LogLevel.LOG: case LogLevel.INFO: case LogLevel.WARN: case LogLevel.ERROR: return level; default: return LogLevel.INFO; } } exports.IMQ_LOG_LEVEL = verifyLogLevel(process.env.IMQ_LOG_LEVEL); const DEFAULT_OPTIONS = { logLevel: exports.IMQ_LOG_LEVEL, }; /** * Environment variable IMQ_LOG_TIME=[1, 0] - enables/disables profiled * timings logging * * @type {boolean} */ exports.IMQ_LOG_TIME = !!+(process.env.IMQ_LOG_TIME || 0); /** * Environment variable IMQ_LOG_ARGS=[1, 0] - enables/disables profiled * call arguments to be logged * * @type {boolean} */ exports.IMQ_LOG_ARGS = !!+(process.env.IMQ_LOG_ARGS || 0); /** * Environment variable IMQ_LOG_TIME_FORMAT=[ * 'microseconds', * 'milliseconds', * 'seconds' * ]. Specifies profiled time logging format, by default is 'microseconds' * * @type {AllowedTimeFormat | string} */ exports.IMQ_LOG_TIME_FORMAT = process.env.IMQ_LOG_TIME_FORMAT || 'microseconds'; /** * Prints debug information * * @param {boolean} debugTime * @param {boolean} debugArgs * @param {string} className * @param {any[]} args * @param {string} methodName * @param {number} start * @param {ILogger} logger * @param {LogLevel} logLevel */ function logDebugInfo({ debugTime, debugArgs, className, args, methodName, start, logger, logLevel, }) { const log = logger && typeof logger[logLevel] === 'function' ? logger[logLevel].bind(logger) : undefined; if (debugTime) { // noinspection TypeScriptUnresolvedFunction const time = parseInt((process.hrtime.bigint() - BigInt(start)), 10) / 1000; let timeStr; // istanbul ignore next switch (exports.IMQ_LOG_TIME_FORMAT) { case 'milliseconds': timeStr = (time / 1000).toFixed(3) + ' ms'; break; case 'seconds': timeStr = (time / 1000000).toFixed(3) + ' sec'; break; default: timeStr = time + ' μs'; break; } if (log) { log(`${className}.${methodName}() executed in ${timeStr}`); } } if (debugArgs) { let argStr = ''; const cache = []; try { argStr = JSON.stringify(args, (key, value) => { if (typeof value === 'object' && value !== null) { if (~cache.indexOf(value)) { try { return JSON.parse(JSON.stringify(value)); } catch (error) { return; } } cache.push(value); } return value; }, 2); } catch (err) { logger.error(err); } if (log) { log(`${className}.${methodName}() called with args: ${argStr}`); } } } /** * Implements '@profile' decorator. * * @example * ~~~typescript * import { profile } from '@imqueue/core'; * * class MyClass { * * @profile(true) // forced profiling * public myMethod() { * // ... * } * * @profile() // profiling happened only depending on env DEBUG flag * private innerMethod() { * // ... * } * } * ~~~ * * @return {( * target: any, * methodName: (string), * descriptor: TypedPropertyDescriptor<(...args: any[]) => any> * ) => void} */ function profile(options) { options = Object.assign({}, DEFAULT_OPTIONS, options); const { enableDebugTime, enableDebugArgs, logLevel } = options; let debugTime = exports.IMQ_LOG_TIME; let debugArgs = exports.IMQ_LOG_ARGS; if (typeof enableDebugTime === 'boolean') { debugTime = enableDebugTime; } if (typeof enableDebugArgs === 'boolean') { debugArgs = enableDebugArgs; } return function wrapper(target, methodName, descriptor) { /* istanbul ignore next */ const original = descriptor.value || target[methodName]; descriptor.value = function (...args) { if (!(debugTime || debugArgs)) { return original.apply(this || target, args); } /* istanbul ignore next */ const className = typeof target === 'function' && target.name ? target.name // static : target.constructor.name; // dynamic // noinspection TypeScriptUnresolvedFunction const start = process.hrtime.bigint(); const result = original.apply(this || target, args); const debugOptions = { args, className, debugArgs, debugTime, logLevel: logLevel ? verifyLogLevel(logLevel) : exports.IMQ_LOG_LEVEL, logger: (this || target).logger, methodName, start, }; /* istanbul ignore next */ if (result && typeof result.then === 'function') { // async call detected result.then((res) => { logDebugInfo(debugOptions); return res; }).catch(() => { logDebugInfo(debugOptions); }); return result; } logDebugInfo(debugOptions); return result; }; }; } //# sourceMappingURL=profile.js.map