/* * (c) Copyright Ascensio System SIA 2010-2024 * * This program is a free software product. You can redistribute it and/or * modify it under the terms of the GNU Affero General Public License (AGPL) * version 3 as published by the Free Software Foundation. In accordance with * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect * that Ascensio System SIA expressly excludes the warranty of non-infringement * of any third-party rights. * * This program is distributed WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html * * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish * street, Riga, Latvia, EU, LV-1050. * * The interactive user interfaces in modified source and object code versions * of the Program must display Appropriate Legal Notices, as required under * Section 5 of the GNU AGPL version 3. * * Pursuant to Section 7(b) of the License you must retain the original Product * logo when distributing the program. Pursuant to Section 7(e) we decline to * grant you any rights under trademark law for use of our trademarks. * * All the Product's GUI elements, including illustrations and icon sets, as * well as technical writing content are licensed under the terms of the * Creative Commons Attribution-ShareAlike 4.0 International. See the License * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode * */ 'use strict'; const config = require('config'); const util = require('util'); const fs = require('fs'); const log4js = require('log4js'); const layouts = require('log4js/lib/layouts'); const logConfigPath = config.get('log.filePath'); const logOptions = config.get('log.options'); // https://stackoverflow.com/a/36643588 const dateToJSONWithTZ = function (d) { const timezoneOffsetInHours = -(d.getTimezoneOffset() / 60); //UTC minus local time const sign = timezoneOffsetInHours >= 0 ? '+' : '-'; const leadingZero = Math.abs(timezoneOffsetInHours) < 10 ? '0' : ''; //It's a bit unfortunate that we need to construct a new Date instance //(we don't want _d_ Date instance to be modified) const correctedDate = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()); correctedDate.setHours(d.getHours() + timezoneOffsetInHours); const iso = correctedDate.toISOString().replace('Z', ''); return iso + sign + leadingZero + Math.abs(timezoneOffsetInHours).toString() + ':00'; }; log4js.addLayout('json', () => { return function (logEvent) { logEvent['startTime'] = dateToJSONWithTZ(logEvent['startTime']); logEvent['message'] = util.format(...logEvent['data']); delete logEvent['data']; return JSON.stringify(logEvent); }; }); /** * Custom pattern layout that supports %x{usid} using USERSESSIONID from context. * @param {object} cfg * @returns {function} */ log4js.addLayout('patternWithTokens', cfg => { const pattern = cfg && cfg.pattern ? cfg.pattern : '%m'; const baseTokens = cfg && cfg.tokens ? cfg.tokens : {}; const tokens = Object.assign({}, baseTokens, { usid(ev) { const id = ev && ev.context && ev.context.USERSESSIONID; return id ? ` [${id}]` : ''; } }); return layouts.patternLayout(pattern, tokens); }); const cachedLogConfig = JSON.parse(fs.readFileSync(logConfigPath, 'utf8')); let curLogConfig = cachedLogConfig; function configureLogger(options) { const mergedOptions = config.util.extendDeep({}, cachedLogConfig, options); log4js.configure(mergedOptions); curLogConfig = mergedOptions; } configureLogger(logOptions); const logger = log4js.getLogger('nodeJS'); if (config.get('log.options.replaceConsole')) { console.log = logger.info.bind(logger); console.info = logger.info.bind(logger); console.warn = logger.warn.bind(logger); console.error = logger.error.bind(logger); console.debug = logger.debug.bind(logger); } exports.getLogger = function () { return log4js.getLogger.apply(log4js, Array.prototype.slice.call(arguments)); }; exports.trace = function () { return logger.trace.apply(logger, Array.prototype.slice.call(arguments)); }; exports.debug = function () { return logger.debug.apply(logger, Array.prototype.slice.call(arguments)); }; exports.info = function () { return logger.info.apply(logger, Array.prototype.slice.call(arguments)); }; exports.warn = function () { return logger.warn.apply(logger, Array.prototype.slice.call(arguments)); }; exports.error = function () { return logger.error.apply(logger, Array.prototype.slice.call(arguments)); }; exports.fatal = function () { return logger.fatal.apply(logger, Array.prototype.slice.call(arguments)); }; exports.shutdown = function (callback) { return log4js.shutdown(callback); }; exports.configureLogger = configureLogger; exports.getLoggerConfig = function () { return curLogConfig; };