UNPKG

@visulima/pail

Version:

Highly configurable Logger for Node.js, Edge and Browser.

385 lines (379 loc) 11.4 kB
import { configure } from 'safe-stable-stringify'; import { L as LOG_TYPES, a as EXTENDED_RFC_5424_LOG_LEVELS, E as EMPTY_SYMBOL } from './constants-BYYZ5WNW.mjs'; import { w as writeConsoleLogBasedOnLevel } from './write-console-log-Tptfzg9D.mjs'; import { g as getLongestLabel } from './get-longest-label-CM8kLFWH.mjs'; var __defProp$3 = Object.defineProperty; var __name$3 = (target, value) => __defProp$3(target, "name", { value, configurable: true }); class RawReporter { static { __name$3(this, "RawReporter"); } // eslint-disable-next-line class-methods-use-this log(meta) { const { context = [], message, type } = meta; const consoleLogFunction = writeConsoleLogBasedOnLevel(type.level); consoleLogFunction(message, ...context); } } var __defProp$2 = Object.defineProperty; var __name$2 = (target, value) => __defProp$2(target, "name", { value, configurable: true }); const arrayify = /* @__PURE__ */ __name$2((x) => { if (x === void 0) { return []; } return Array.isArray(x) ? x : [x]; }, "arrayify"); var __defProp$1 = Object.defineProperty; var __name$1 = (target, value) => __defProp$1(target, "name", { value, configurable: true }); const mergeTypes = /* @__PURE__ */ __name$1((standard, custom) => { const types = { ...standard }; Object.keys(custom).forEach((type) => { types[type] = { ...types[type], ...custom[type] }; }); return types; }, "mergeTypes"); var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); class PailBrowserImpl { static { __name(this, "PailBrowserImpl"); } timersMap; countMap; seqTimers; lastLog; logLevels; disabled; scopeName; types; longestLabel; processors; generalLogLevel; reporters; throttle; throttleMin; stringify; groups; startTimerMessage; endTimerMessage; rawReporter; constructor(options) { this.throttle = options.throttle ?? 1e3; this.throttleMin = options.throttleMin ?? 5; this.stringify = configure({ strict: true }); this.startTimerMessage = options.messages?.timerStart ?? "Initialized timer..."; this.endTimerMessage = options.messages?.timerEnd ?? "Timer run for:"; this.types = mergeTypes(LOG_TYPES, options.types ?? {}); this.longestLabel = getLongestLabel(this.types); this.logLevels = { ...EXTENDED_RFC_5424_LOG_LEVELS, ...options.logLevels }; this.generalLogLevel = this._normalizeLogLevel(options.logLevel); this.reporters = /* @__PURE__ */ new Set(); this.processors = /* @__PURE__ */ new Set(); this.disabled = options.disabled ?? false; this.scopeName = arrayify(options.scope).filter(Boolean); this.timersMap = /* @__PURE__ */ new Map(); this.countMap = /* @__PURE__ */ new Map(); this.groups = []; this.seqTimers = /* @__PURE__ */ new Set(); for (const type in this.types) { this[type] = this._logger.bind(this, type, false); } this.lastLog = {}; if (Array.isArray(options.reporters)) { this.registerReporters(options.reporters); } this.rawReporter = this.extendReporter(options.rawReporter ?? new RawReporter()); if (Array.isArray(options.processors)) { this.registerProcessors(options.processors); } } wrapConsole() { for (const type in this.types) { if (!console["__" + type]) { console["__" + type] = console[type]; } console[type] = this[type]; } } restoreConsole() { for (const type in this.types) { if (console["__" + type]) { console[type] = console["__" + type]; delete console["__" + type]; } } } wrapException() { { process.on("uncaughtException", (error) => { this.error(error); }); process.on("unhandledRejection", (error) => { this.error(error); }); } } /** * Disables logging */ disable() { this.disabled = true; } /** * Enables logging */ enable() { this.disabled = false; } isEnabled() { return !this.disabled; } scope(...name) { if (name.length === 0) { throw new Error("No scope name was defined."); } this.scopeName = name.flat(); return this; } unscope() { this.scopeName = []; } time(label = "default") { if (this.seqTimers.has(label)) { this._logger("warn", false, { message: "Timer '" + label + "' already exists", prefix: label }); } else { this.seqTimers.add(label); this.timersMap.set(label, Date.now()); this._logger("start", false, { message: this.startTimerMessage, prefix: label }); } } timeLog(label, ...data) { if (!label && this.seqTimers.size > 0) { label = [...this.seqTimers].pop(); } if (label && this.timersMap.has(label)) { const span = Date.now() - this.timersMap.get(label); this._logger("info", false, { context: data, message: span < 1e3 ? span + " ms" : (span / 1e3).toFixed(2) + " s", prefix: label }); } else { this._logger("warn", false, { context: data, message: "Timer not found", prefix: label }); } } timeEnd(label) { if (!label && this.seqTimers.size > 0) { label = [...this.seqTimers].pop(); } if (label && this.timersMap.has(label)) { const span = Date.now() - this.timersMap.get(label); this.timersMap.delete(label); this._logger("stop", false, { message: this.endTimerMessage + " " + (span < 1e3 ? span + " ms" : (span / 1e3).toFixed(2) + " s"), prefix: label }); } else { this._logger("warn", false, { message: "Timer not found", prefix: label }); } } group(label = "console.group") { if (typeof window === "undefined") { this.groups.push(label); } else { console.group(label); } } groupEnd() { if (typeof window === "undefined") { this.groups.pop(); } else { console.groupEnd(); } } count(label = "default") { const current = this.countMap.get(label) ?? 0; this.countMap.set(label, current + 1); this._logger("log", false, { message: label + ": " + (current + 1), prefix: label }); } countReset(label = "default") { if (this.countMap.has(label)) { this.countMap.delete(label); } else { this._logger("warn", false, { message: "Count for " + label + " does not exist", prefix: label }); } } // eslint-disable-next-line class-methods-use-this clear() { console.clear(); } raw(message, ...arguments_) { if (this.disabled) { return; } this._logger("log", true, { context: arguments_, message }); } extendReporter(reporter) { if (typeof reporter.setLoggerTypes === "function") { reporter.setLoggerTypes(this.types); } if (typeof reporter.setStringify === "function") { reporter.setStringify(this.stringify); } return reporter; } registerReporters(reporters) { for (const reporter of reporters) { this.reporters.add(this.extendReporter(reporter)); } } _report(meta, raw) { if (raw) { this.rawReporter.log(Object.freeze(meta)); } else { for (const reporter of this.reporters) { reporter.log(Object.freeze(meta)); } } } registerProcessors(processors) { for (const processor of processors) { if (typeof processor.setStringify === "function") { processor.setStringify(this.stringify); } this.processors.add(processor); } } // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents _normalizeLogLevel(level) { return level && this.logLevels[level] ? level : "debug"; } // eslint-disable-next-line sonarjs/cognitive-complexity,@typescript-eslint/no-explicit-any _buildMeta(typeName, type, ...arguments_) { const meta = { badge: void 0, context: void 0, error: void 0, label: void 0, message: EMPTY_SYMBOL, prefix: void 0, repeated: void 0, scope: void 0, suffix: void 0 }; meta.type = { level: type.logLevel, name: typeName }; meta.groups = this.groups; meta.scope = this.scopeName; meta.date = /* @__PURE__ */ new Date(); if (arguments_.length === 1 && typeof arguments_[0] === "object" && arguments_[0] !== null) { if (arguments_[0] instanceof Error) { meta.error = arguments_[0]; } else if ("message" in arguments_[0]) { const { context, message, prefix, suffix } = arguments_[0]; if (context) { meta.context = context; } if (prefix) { meta.prefix = prefix; } if (suffix) { meta.suffix = suffix; } meta.message = message; } else { meta.message = arguments_[0]; } } else if (arguments_.length > 1 && typeof arguments_[0] === "string") { meta.message = arguments_[0]; meta.context = arguments_.slice(1); } else { meta.message = arguments_[0]; } if (type.logLevel === "trace") { meta.traceError = new Error("Trace"); } if (type.badge) { meta.badge = type.badge; } if (type.label) { meta.label = type.label; } return meta; } // eslint-disable-next-line sonarjs/cognitive-complexity,@typescript-eslint/no-explicit-any _logger(type, raw, ...messageObject) { if (this.disabled) { return; } const logLevel = this._normalizeLogLevel(this.types[type].logLevel); if (this.logLevels[logLevel] >= this.logLevels[this.generalLogLevel]) { let meta = this._buildMeta(type, this.types[type], ...messageObject); const resolveLog = /* @__PURE__ */ __name((newLog = false) => { const repeated = (this.lastLog.count || 0) - this.throttleMin; if (this.lastLog.object && repeated > 0) { const lastMeta = { ...this.lastLog.object }; if (repeated > 1) { lastMeta.repeated = repeated; } this._report(lastMeta, raw); this.lastLog.count = 1; } if (newLog) { for (const processor of this.processors) { meta = { ...processor.process(meta) }; } this.lastLog.object = meta; this._report(meta, raw); } }, "resolveLog"); clearTimeout(this.lastLog.timeout); const diffTime = this.lastLog.time && meta.date ? new Date(meta.date).getTime() - this.lastLog.time.getTime() : 0; this.lastLog.time = new Date(meta.date); if (diffTime < this.throttle) { try { const serializedLog = JSON.stringify([meta.label, meta.scope, meta.type, meta.message, meta.prefix, meta.suffix, meta.context]); const isSameLog = this.lastLog.serialized === serializedLog; this.lastLog.serialized = serializedLog; if (isSameLog) { this.lastLog.count = (this.lastLog.count || 0) + 1; if (this.lastLog.count > this.throttleMin) { this.lastLog.timeout = setTimeout(resolveLog, this.throttle); return; } } } catch { } } resolveLog(true); } } } const PailBrowser = PailBrowserImpl; export { PailBrowser as P, PailBrowserImpl as a };