UNPKG

@pyrologic/pyrologjs

Version:
1,384 lines (1,370 loc) 40.2 kB
/** * logging levels */ var Level; (function (Level) { /** logs everything */ Level[Level["ALL"] = 0] = "ALL"; /** TRACE level */ Level[Level["TRACE"] = 1] = "TRACE"; /** DEBUG level */ Level[Level["DEBUG"] = 2] = "DEBUG"; /** INFO level */ Level[Level["INFO"] = 3] = "INFO"; /** WARN level */ Level[Level["WARN"] = 4] = "WARN"; /** ERROR level */ Level[Level["ERROR"] = 5] = "ERROR"; /** FATAL level */ Level[Level["FATAL"] = 6] = "FATAL"; /** loggers at this level do not log at all */ Level[Level["OFF"] = 7] = "OFF"; })(Level || (Level = {})); /** * retrieves the name of a logging level * @param level logging level * @returns the corresponding name (string) */ function Level2String(level) { switch (level) { case Level.ALL: return "ALL"; case Level.TRACE: return "TRACE"; case Level.DEBUG: return "DEBUG"; case Level.INFO: return "INFO"; case Level.WARN: return "WARN"; case Level.ERROR: return "ERROR"; case Level.FATAL: return "FATAL"; case Level.OFF: return "OFF"; } } /** * converts a logging level into the matching level identifier * @param level the logging level * @returns the matching level identifier */ function Level2LevelString(level) { return Level2String(level); } /** * converts an arbitrary string into a valid level identifier * @param s arbitrary string * @returns the corresponding level identifier */ function String2LevelString(s) { switch (s) { case "ALL": return "ALL"; case "TRACE": return "TRACE"; case "DEBUG": return "DEBUG"; case "INFO": return "INFO"; case "WARN": return "WARN"; case "ERROR": return "ERROR"; case "FATAL": return "FATAL"; case "OFF": return "OFF"; default: return "INFO"; } } /** * converts a string providing a level name into the corresponding Level enumeration value * @param s string providing a level name * @returns the corresponding Level enumeration value */ function String2Level(s) { const level = Level[String2LevelString(s)]; return level !== undefined ? level : Level.INFO; } /** * executes a callback function for each logging level * @param f the callback function */ function forEachLevel(f) { for (let l = Level.ALL; l <= Level.OFF; ++l) { f(l); } } class CallbackAppender { constructor(cf) { if (typeof cf !== 'function') { throw new Error('Invalid callback function specified!'); } this._cf = cf; } /** * @override */ appendLog(...logs) { this._cf(logs); } } class PyroConfigItem { constructor(name, level, wf) { this._name = name; this._level = level; this._writeFnc = wf; this._levelStyles = new Map(); Object.freeze(this); } get name() { return this._name; } get level() { return this._level; } get writeFnc() { return this._writeFnc; } get levelStyles() { return this._levelStyles; } /** * @override */ addLevelStyle(level, style) { this._levelStyles.set(level, style); } } /** * Global options for all loggers * this class is a singleton */ class GlobalOptions { /** * constructs a new instance */ constructor() { this._globalStyles = new Map(); this._useDebug = false; this._suspended = false; } /** * returns the singleton instance * @returns the singleton instance */ static getInstance() { return globalOptions; } /** * use console.debug() * @returns {boolean} true if DEBUG level and below should use console.debug(); false if console.log() should be used instead */ get useDebug() { return this._useDebug; } /** * sets the "use console.debug()" flag */ set useDebug(d) { this._useDebug = !!d; } /** * @returns {boolean} true if logging is currently suspended; false otherwise */ get suspended() { return this._suspended; } /** * sets the "suspended" flag */ set suspended(s) { this._suspended = s; } /** * sets global options * @param o an object providing one or more global options */ setOptions(o) { if (typeof o === 'object') { if (('useDebug' in o) && (typeof o.useDebug === 'boolean')) { this._useDebug = !!o.useDebug; } if (('suspended' in o) && (typeof o.suspended === 'boolean')) { this._suspended = !!o.suspended; } } } /** * * @param level the logging level * @returns the global style definition for the given level or undefined if there's no matching global style definition */ getLevelStyle(level) { return this._globalStyles.get(level); } /** * sets the global style definition for a logging level * @param level the logging level * @param style the global style definition */ setLevelStyle(level, style) { this._globalStyles.set(level, style); } } const globalOptions = new GlobalOptions(); /** * styling of logging messages * see https://developer.chrome.com/docs/devtools/console/format-style */ /** * all supported color values */ const Colors = { BLACK: { fgRef: 30, bgRef: 40 }, RED: { fgRef: 31, bgRef: 41 }, GREEN: { fgRef: 32, bgRef: 42 }, ORANGE: { fgRef: 33, bgRef: 43 }, DARKBLUE: { fgRef: 34, bgRef: 44 }, PURPLE: { fgRef: 35, bgRef: 45 }, TURQUOISE: { fgRef: 36, bgRef: 46 }, GRAY: { fgRef: 37, bgRef: 47 }, DARKGRAY: { fgRef: 90, bgRef: 100 }, LIGHTRED: { fgRef: 91, bgRef: 101 }, LIGHTGREEN: { fgRef: 92, bgRef: 102 }, YELLOW: { fgRef: 93, bgRef: 103 }, BLUE: { fgRef: 94, bgRef: 104 }, PINK: { fgRef: 95, bgRef: 105 }, CYAN: { fgRef: 96, bgRef: 106 }, WHITE: { fgRef: 97, bgRef: 107 }, NONE: { fgRef: 0, bgRef: 0 }, }; /** * general utility class */ class Utils { /** * indicates whether styled console output is possible * @returns true if styled console output is possible; false otherwise */ static canConsoleStyles() { if (Utils._can_console_styles === undefined) { let webkit = false; let nodejs = false; try { // check for WebKit / Chromium based browser webkit = typeof navigator !== "undefined" && !!(navigator.userAgent) && navigator.userAgent.includes("AppleWebKit"); } catch (e) { webkit = false; } if (!webkit) { // check for nodejs / deno try { nodejs = typeof process !== "undefined"; } catch (e) { nodejs = false; } } Utils._can_console_styles = nodejs || webkit; } return Utils._can_console_styles; } /** * checks whether the specified object is a real, non-empty string * @param str the object supposed to be a string * @returns true if the given object is a non-empty string; false other wise */ static isString(str) { return (typeof str === 'string') && (str.length > 0); } /** * ensures that a string is returned * @param str the object supposed to be a string * @returns the given string if it is a valid string; an empty string otherwise */ static ensureString(str) { return Utils.isString(str) ? str : ''; } /** * checks whether the given name parameter is a valid string; throws an error if not * @param name a string specifying a name * @returns the given string */ static ensureName(name) { if (!Utils.isString(name)) { throw new Error(`Invalid name specified: "${name}" (type: ${typeof name})!`); } return name; } /** * checks whether all elements of the given array are valid strings; throws an error if not * @param names array of strings to be * @param errmsg optional error message that's thrown in the case of an error */ static checkNames(names, errmsg = "") { const cnt = names.length; for (let i = 0; i < cnt; ++i) { const n = names[i]; if (!Utils.isString(n)) { const msg = Utils.isString(errmsg) ? errmsg : `Invalid element at index #${i}: "${n}"!`; throw new Error(msg); } } return names; } /** * splits a path string into parts * @param path the path string * @returns {string[]} the configuration path */ static splitPath(path) { const p = []; path.split('.').forEach((s) => p.push(s.trim())); return p; } /** * splits a logger name into a configuration path * @param {string} name logger name * @returns {string[]} the configuration path */ static getPath(name) { return Utils.checkNames(Utils.splitPath(name), `Invalid logger path "${name}"!`); } /** * normalizes a logger name or path * @param name the logger name or path * @returns the normalized logger path */ static normalizePath(name) { const path = Utils.getPath(name); return path.join('.'); } /** * retrieves the stack trace * @param skip number of stack entries to skip * @returns the stack trace as string */ static getStack(skip = 1) { const err = new Error(); const stack = Utils.ensureString(err.stack); if (Utils.isString(stack)) { let s = stack; let c = skip; if (!stack.startsWith('Error')) { // Chromium has an additional line beginning with "Error\n" - Firefox and Safari do not! --c; } while (c >= 0) { const index = s.indexOf('\n'); if ((index < 0) || ((s.length - 1) < (index + 1))) { break; } s = s.substring(index + 1); --c; } return s; } else { return ''; } } /** * retrieves the name of the calling function * @param skip number of stack entries to skip; 0 used default * @param separator optional separator character that replaces '.' * @returns the name of the calling function */ static getFunctionName(skip = 0, separator = '#') { const eff_skip = (typeof skip === 'number') ? skip + 2 : 2; const stack = Utils.getStack(eff_skip); if (Utils.isString(stack)) { let s = stack.trim(); if (s.startsWith('at ')) { s = s.substring(3); } const si = s.indexOf(' ('); if ((si !== -1) && ((si + 1) < (s.length - 1))) { s = s.substring(0, si); } const ai = s.indexOf('@'); if ((ai >= 0) && ((s.length - 1) >= (ai + 1))) { s = s.substring(0, ai); } const pi = s.indexOf('/<'); // that's sometimes the case in Firefox if (pi !== -1) { s = s.substring(0, pi); } let hi = s.indexOf('https://'); if (hi === -1) { hi = s.indexOf('http://'); } if (hi !== -1) { s = (hi > 0) ? s.substring(0, hi) : '<anonymous>'; } if ((s.length > 0) && Utils.isString(separator)) { s = s.replace('.', separator); } return s; } else { return ''; } } } Utils._can_console_styles = undefined; class PyroLogger { /** * constructs a new instance * @param n logger name * @param l initial logging level * @param wf flag whether to write the name of the calling function / method * @param a the optional appender */ constructor(n, l, wf, pg, sp, a) { this._styleProvider = sp; this._options = GlobalOptions.getInstance(); this._styles = new Map(); this._name = n; this._level = l; this._writeFnc = !!wf; this._fncOffset = 0; this._suspended = false; this._pfxGenerator = pg; this._appender = a; this.updateStyles(); } /** * @returns the name of this logger */ get name() { return this._name; } /** * @returns {Level} the current logging level of this logger */ get level() { return this._level; } ; /** * @returns the flag whether to write the name of the calling function / method along with each logging output */ get writeFnc() { return this._writeFnc; } /** * @returns the offset for the call stack used to get the name of the calling function */ get fncOffset() { return this._fncOffset; } /** * @returns the "suspended" state of this logger */ get suspended() { return this._suspended; } /** * sets a new logging level of this logger * @param {Level} l new logging level of this logger */ setLevel(l) { this._level = l; } /** * sets a new appender * @param a the new appender; may be null */ setAppender(a) { this._appender = a; } /** * sets a new prefix generator * @param pg the new prefix generator; must not be null */ setPrefixGenerator(pg) { this._pfxGenerator = pg; } /** * sets the flag whether to write the name of the calling function / method along with each logging output * @param wf new value */ setWriteFnc(wf) { this._writeFnc = !!wf; } /** * updates the style definitions for this logger */ updateStyles() { this._styles.clear(); const styleProvider = this._styleProvider; const self = this; forEachLevel((level) => { const sd = styleProvider.getStyleDef(self.name, level); if (sd !== undefined) { self._styles.set(level, sd); } }); } /** * @returns {String} a short informational string about this logger */ toString() { return `{Logger "${this._name}" [${Level2String(this._level)}]}`; } /** * @override */ isEnabledFor(l) { return !this._options.suspended && (l >= this.level) && (l !== Level.OFF); } /** * @override */ isDebugEnabled() { return this.isEnabledFor(Level.DEBUG); } /** * @override */ isTraceEnabled() { return this.isEnabledFor(Level.TRACE); } /** * creates the prefix text that's prepended to each logging output * @param l logging level * @returns the prefix text */ _getPrefix(l) { try { this._fncOffset += 4; return this._pfxGenerator.createPrefix(this, l); } finally { this._fncOffset -= 4; } } /** * @returns true if this logger is currently suspended; false otherwise */ get _isSuspended() { return this.suspended || this._options.suspended; } /** * adds a style value to the given style descriptor * @param dsc the current style descriptor * @param value the style value * @returns the new style descriptor */ _addStyleDsc(dsc, value) { return `${dsc}${dsc.length ? ';' : ''}${value}`; } /** * creates a style descriptor from a style definition * @param style the style definition * @returns the style descriptor */ _createStyleDescriptor(style) { let dsc = ''; if (Utils.canConsoleStyles()) { // the environment supports this if (style.color && style.color !== Colors.NONE) { dsc = this._addStyleDsc(dsc, style.color.fgRef); } if (style.background && style.background !== Colors.NONE) { dsc = this._addStyleDsc(dsc, style.background.bgRef); } if (style.styles.bold) { dsc = this._addStyleDsc(dsc, 1); } if (style.styles.italic) { dsc = this._addStyleDsc(dsc, 3); } if (style.styles.underline) { dsc = this._addStyleDsc(dsc, 4); } if (style.styles.linethrough) { dsc = this._addStyleDsc(dsc, 9); } } return dsc; } /** * applies the style definition to the data to be logged * @param style the style definition * @param prefix the prefix text * @param data data to be logged * @returns the styled data to be logged */ _applyStyle(style, prefix, data) { if (style !== undefined) { const dsc = this._createStyleDescriptor(style); if (Utils.isString(dsc)) { // we've got a valid, non-empty style descriptor const styled_data = []; let text = `\x1B[${dsc}m`; // add prefix text if present if (Utils.isString(prefix)) { text += `${prefix} `; } // add placeholders for each value according to its type for (let i = 0; i < data.length; ++i) { if (i > 0) { text += ' '; } const value = data[i]; if (Utils.isString(value)) { text += '%s'; } else if (typeof value === 'number') { text += Number.isInteger(value) ? '%d' : '%f'; } else if (value instanceof HTMLElement) { text += '%o'; } else { text += '%O'; } } // reset formatting text += '\x1B[0m'; // first item is the prefix text with styling and all placeholders styled_data.push(text); // all other items are the actual data to be logged styled_data.push(...data); // done return styled_data; } } // use data "as is" but consider the prefix if (Utils.isString(prefix)) { const all_data = []; all_data.push(prefix, ...data); return all_data; } else { // no prefix, nothing to do return data; } } /** * @override */ writeLog(l, ...data) { if (!this._isSuspended && (this._level !== Level.OFF) && (l !== Level.OFF) && this.isEnabledFor(l)) { const prefix = this._getPrefix(l); const style = this._styles.get(l); const styled_data = this._applyStyle(style, prefix, data); switch (l) { case Level.ALL: case Level.TRACE: case Level.DEBUG: if (this._options.useDebug) { console.debug(...styled_data); } else { console.log(...styled_data); } break; case Level.INFO: console.info(...styled_data); break; case Level.WARN: console.warn(...styled_data); break; case Level.ERROR: case Level.FATAL: console.error(...styled_data); break; default: console.log(...styled_data); break; } if (this._appender !== null) { this._appender.appendLog(prefix, ...data); } } } /** * @override */ trace(...data) { this.writeLog(Level.TRACE, ...data); } /** * @override */ debug(...data) { this.writeLog(Level.DEBUG, ...data); } /** * @override */ info(...data) { this.writeLog(Level.INFO, ...data); } /** * @override */ warn(...data) { this.writeLog(Level.WARN, ...data); } /** * @override */ error(...data) { this.writeLog(Level.ERROR, ...data); } /** * @override */ fatal(...data) { this.writeLog(Level.FATAL, ...data); } /** * @override */ writeStackTrace(l, skip, message) { if (this.isEnabledFor(l)) { this.writeLog(l, (Utils.isString(message) ? message : '') + '\n' + Utils.getStack(skip)); } } /** * @override */ setFncOffset(offs) { this._fncOffset = offs; } /** * @override */ setSuspended(suspended) { this._suspended = suspended; } /** * @override */ addStyle(level, style) { this._styles.set(level, style); } } /** * some common constants */ /** * the name of the default configuration */ const DEFAULT_CONFIG = '@default'; /** * the name of configuration's root node */ const ROOT_NODE_NAME = '@rootNode'; /** * configuration tree */ /** * an internal tree node class */ class Node { constructor(n, p, nc) { this._name = Utils.ensureName(n); if ((p !== null) && (n === ROOT_NODE_NAME)) { throw new Error('Cannot create child node with internal root node name!'); } this._parent = p; this._config = nc; this._children = new Map(); if (p !== null) { p._addChild(this); } } get name() { return this._name; } get parent() { return this._parent; } get config() { return this._config; } hasConfig() { return this._config !== null; } setConfig(cf) { this._config = cf; } hasChild(name) { return this._children.has(name); } getChild(name) { return this._children.get(name); } clear() { if (this._children.size > 0) { try { this._children.forEach((c) => c.clear()); } finally { this._children.clear(); } } } _addChild(child) { if (child._parent !== this) { throw new Error('Invalid child node with different parent node!'); } if (!this.hasChild(child.name)) { this._children.set(Utils.ensureName(child.name), child); } else { throw new Error(`Duplicate node "${child.name}"!`); } } } /** * the class ConfigTree holds the hierarchical logger configuration */ class ConfigTree { /** * constructs a new instance * @param {ConfigItem} rc root configuration item; provides the default configuration */ constructor(rc) { this._rootNode = new Node(ROOT_NODE_NAME, null, rc); } /** * @returns {ConfigItem} the default configurations */ get defaultConfig() { return this._rootNode.config; } /** * clears the configuration tree, drops all configuration nodes */ clear() { this._rootNode.clear(); } /** * searches for a matching logger configuration in the configuration tree * @param {string} name logger name * @returns {ConfigItem} the matching logger configuration or null if something went wrong */ findConfig(name) { let node = this._findNode(this._rootNode, Utils.getPath(name), 1); while ((node !== null) && (node.config === null)) { node = node.parent; } return (node !== null) ? node.config : this._rootNode.config; } /** * searches for a node in the configuration tree * @param {Node} node parent node * @param {string[]} path configuration node path * @param {number} level recursion level * @returns {Node} the matching node */ _findNode(node, path, level) { if (level > path.length) { return node; } const child = node.getChild(path[level - 1]); if (child !== undefined) { return this._findNode(child, path, level + 1); } else { return node; } } /** * applies a logger configuration * @param config array of configuration items */ _applyConfiguration(config) { for (let ci of config) { try { const names = Utils.getPath(ci.name); const node = this._ensureNode(this._rootNode, names, 1); node.setConfig(ci); console.debug(`Configuration node "${names.join('.')}" is set to level "${ci.level}."`); } catch (error) { console.error('Skipping invalid configuration item.', error); } } } /** * ensures that a tree node exists for a given path * @param {Node} node parent node * @param {string[]} path configuration node path * @param {Number} level current recursion level * @returns {Node} the child node referred by the path */ _ensureNode(node, path, level) { const name = path[level - 1]; if (!node.hasChild(name)) { new Node(name, node, null); } const child = node.getChild(name); return level < path.length ? this._ensureNode(child, path, level + 1) : child; } /** * applies a logger configuration * @param config array of configuration items */ static applyConfiguration(config) { let nci = []; let dci = null; for (let ci of config) { const name = Utils.normalizePath(ci.name); const level = Level[ci.level]; if (typeof level === 'undefined') { throw new Error(`Invalid level "${ci.level}"!`); } if (DEFAULT_CONFIG === name) { if (dci === null) { dci = ci; } } else { nci.push(ci); } } if (dci === null) { // create default configuration dci = new PyroConfigItem(DEFAULT_CONFIG, 'ERROR', false); } const tree = new ConfigTree(dci); if (nci.length > 0) { tree._applyConfiguration(nci); } return tree; } } class PyroPrefixGenerator { /** * constructs a new instance */ constructor() { // empty so far } /** * @returns the singleton instance */ static getInstance() { return pyroPrefixGenerator; } /** * @override */ createPrefix(logger, level) { return `${(new Date()).toISOString()} ${logger.name} [${Level2String(level)}]` + (logger.writeFnc ? ` (${Utils.getFunctionName(logger.fncOffset)})` : '') + ':'; } } const pyroPrefixGenerator = new PyroPrefixGenerator(); /** * a callback prefix generator that wraps a callback function */ class CallbackPrefixGenerator { constructor(fn) { this._pgf = fn; } /** * @override */ createPrefix(logger, level) { return this._pgf(logger, level); } } class LoggerFactory { /** * constructs the instance */ constructor() { this._loggers = new Map(); this._defLevel = Level.INFO; this._writeFnc = null; this._config = null; this._appender = null; this._pfxGenerator = null; } /** * returns the logger factory instance * @returns {LoggerFactory} the logger factory instance */ static getInstance() { return loggerFactory; } /** * the name of the default configuration item */ get defaultName() { return DEFAULT_CONFIG; } /** * the default level for new loggers */ get defaultLevel() { return this._defLevel; } /** * sets the default level */ set defaultLevel(l) { this._defLevel = l; } /** * flag whether to write the name of the calling function / method along with each output * @returns {Boolean | null} true if new loggers should write the function name along with each log output; false if not; null if not specified */ get writeFnc() { return this._writeFnc; } /** * sets the "write function name" flag */ set writeFnc(wf) { this._writeFnc = wf; } /** * returns a logger * @param name logger name * @returns {Logger} the logger */ getLogger(name) { const path = Utils.normalizePath(name); if (!this._loggers.has(path)) { // time to create it this._loggers.set(path, new PyroLogger(path, this.getLevel(path), this._getEffWriteFnc(this.getWriteFnc(path)), this.prefixGenerator, this, this._appender)); } return this._loggers.get(path); } /** * retrieves a logger configuration item * @param name logger name * @returns the matching configuration item or null if no matching configuration item was found */ _getConfig(name) { var _a; if (this._config !== null) { return (_a = this._config) === null || _a === void 0 ? void 0 : _a.findConfig(name); } else { return null; } } /** * retrieves the parent configuration item of a configuration item * @param config configuration item * @returns the parent configuration item of the given item or null if there's no parent item */ _getParentConfig(config) { const name = config.name; const pos = name.lastIndexOf('.'); if (pos > 0) { return this._getConfig(name.substring(0, pos)); } return null; } /** * retrieves the effective "write function name" setting * @param wf logger's "write function name" flag * @returns the effective "write function name" setting */ _getEffWriteFnc(wf) { return (wf !== null) ? wf.valueOf() : ((this._writeFnc !== null) ? this._writeFnc.valueOf() : false); } /** * retrieves the configured level of a logger * @param name logger name * @returns the level for that logger; if no configuration exists for the specified logger then the default level is returned */ getLevel(name) { const config = this._getConfig(name); return config !== null ? Level[config.level] : this._defLevel; } /** * retrieves the "write function name" flag for the specified logger * @param name logger name * @returns true if the specified logger should write the function name along with each log output; false if not; null if not specified */ getWriteFnc(name) { const config = this._getConfig(name); return config !== null ? config.writeFnc : this.writeFnc; } /** * @override */ getStyleDef(name, level) { const config = this._getConfig(name); let style = undefined; if (config !== null) { const ls = Level2LevelString(level); style = config.levelStyles.get(ls); let parent = this._getParentConfig(config); while ((style === undefined) && (parent !== null)) { style = parent.levelStyles.get(ls); parent = this._getParentConfig(parent); } } return style !== undefined ? style : GlobalOptions.getInstance().getLevelStyle(level); } /** * creates a new callback appender * @param cf callback function * @param set flag whether to set this appender immediately * @returns the created appender */ createAppender(cf, set) { const appender = new CallbackAppender(cf); if (set) { this.setAppender(appender); } return appender; } /** * sets a new appender * @param appender the new appender, may be null */ setAppender(appender) { this._appender = appender; this._loggers.forEach((l) => l.setAppender(appender)); } /** * sets a new prefix generator * @param generator new prefix generator */ setPrefixGenerator(generator) { this._pfxGenerator = generator; const pg = this.prefixGenerator; this._loggers.forEach((l) => l.setPrefixGenerator(pg)); } /** * creates a prefix generator * @param fn actual prefix generator function * @param set flag whether to set this prefix generator immediately as current prefix generator * @returns the created prefix generator instance */ createPrefixGenerator(fn, set) { const pg = new CallbackPrefixGenerator(fn); if (set) { this.setPrefixGenerator(pg); } return pg; } /** * @returns the default prefix generator */ get prefixGenerator() { return this._pfxGenerator !== null ? this._pfxGenerator : PyroPrefixGenerator.getInstance(); } /** * creates a level style descriptor * @param param0 * @returns the level style descriptor */ createLevelStyle({ color = Colors.NONE, background = Colors.NONE, bold = false, italic = false, underline = false, linethrough = false }) { const textStyle = { bold: !!bold, italic: !!italic, underline: !!underline, linethrough: !!linethrough, }; const styleDef = { color: color ? color : Colors.NONE, background: background ? background : Colors.NONE, styles: textStyle, }; return styleDef; } /** * creates a configuration item * @param name logger name * @param level logging level * @param wf flag whether to write the name of the calling function / method * @returns the created configuration item */ createConfigItem(name, level, wf) { return new PyroConfigItem(Utils.normalizePath(name), level, wf); } /** * applies a logger configuration * @param config array of configuration items */ applyConfiguration(config) { if (this._config !== null) { // drop old configuration this._config.clear(); this._config = null; } // read and evaluate configuration items const cfg = ConfigTree.applyConfiguration(config); this._config = cfg; this._defLevel = Level[cfg.defaultConfig.level]; this._writeFnc = cfg.defaultConfig.writeFnc; if (this._loggers.size > 0) { // update existing loggers const self = this; this._loggers.forEach((pl) => { pl.setLevel(self.getLevel(pl.name)); pl.setWriteFnc(self._getEffWriteFnc(self.getWriteFnc(pl.name))); pl.updateStyles(); }); } } } const loggerFactory = new LoggerFactory(); class PyroLog { constructor() { this._lf = LoggerFactory.getInstance(); Object.freeze(this); } static _create() { return new PyroLog(); } /** * returns the singleton instance * @returns the singleton instance */ static getInstance() { return pyroLog; } /** * the logger factory instance */ get Factory() { return this._lf; } /** * the name of the default configuration item */ get defaultName() { return this._lf.defaultName; } /** * the default level for new loggers */ get defaultLevel() { return this._lf.defaultLevel; } /** * the stack trace as string */ get stackTrace() { return Utils.getStack(2); } /** * the name of the calling function as string */ get functionName() { return Utils.getFunctionName(1, '#'); } /** * returns a logger * @param name logger name * @returns {Logger} the logger */ getLogger(name) { return this._lf.getLogger(name); } /** * sets global options * @param o an object providing one or more global options */ setGlobalOptions(o) { GlobalOptions.getInstance().setOptions(o); } /** * creates a level style descriptor * @param param0 * @returns the level style descriptor */ createLevelStyle({ color = Colors.NONE, background = Colors.NONE, bold = false, italic = false, underline = false, linethrough = false }) { return this._lf.createLevelStyle({ color, background, bold, italic, underline, linethrough }); } /** * creates a new callback appender * @param cf callback function * @param set flag whether to set this appender immediately * @returns the created appender */ createAppender(cf, set) { return this._lf.createAppender(cf, set); } /** * sets a new appender * @param appender the new appender, may be null */ setAppender(appender) { this._lf.setAppender(appender); } /** * sets a new prefix generator * @param generator new prefix generator */ setPrefixGenerator(generator) { this._lf.setPrefixGenerator(generator); } /** * creates a prefix generator * @param fn actual prefix generator function * @param set flag whether to set this prefix generator immediately as current prefix generator * @returns the created prefix generator instance */ createPrefixGenerator(fn, set) { return this._lf.createPrefixGenerator(fn, set); } /** * creates a logger configuration item * @param name logger name * @param level logging level * @param wf flag whether to write the name of the calling function / method * @returns the created configuration item */ createConfigItem(name, level, wf = null) { return this._lf.createConfigItem(name, level, wf); } /** * applies a logger configuration * @param config array of configuration items */ applyConfiguration(config) { this._lf.applyConfiguration(config); } /** * sets the global style definition for a logging level * @param level the logging level * @param style the global style definition */ setLevelStyle(level, style) { GlobalOptions.getInstance().setLevelStyle(level, style); } /** * writes the current stack trace to the specified logger * @param logger target logger * @param level logging level * @param message optional message text */ writeStackTrace(logger, level, message) { logger.writeStackTrace(Level[level], 3, message); } } // create the singleton instance const pyroLog = PyroLog._create(); // create Level enumeration as JS object const JsLevel = Object.freeze({ ALL: Level.ALL, TRACE: Level.TRACE, DEBUG: Level.DEBUG, INFO: Level.INFO, WARN: Level.WARN, ERROR: Level.ERROR, FATAL: Level.FATAL, OFF: Level.OFF }); export { Colors, JsLevel, Level, Level2LevelString, Level2String, PyroLog, Utils as PyroLogUtils, PyroLogger, String2Level, String2LevelString, forEachLevel }; //# sourceMappingURL=pyrolog.js.map