@visulima/pail
Version:
Highly configurable Logger for Node.js, Edge and Browser.
385 lines (379 loc) • 11.4 kB
JavaScript
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 };