UNPKG

loglayer

Version:

A modern logging library with a fluent API for specifying log messages, metadata and errors

1,264 lines (1,253 loc) 35.4 kB
// src/index.ts import { PluginCallbackType as PluginCallbackType4 } from "@loglayer/plugin"; import { LogLevel as LogLevel6 } from "@loglayer/shared"; // src/LogLayer.ts import { DefaultContextManager } from "@loglayer/context-manager"; import { PluginCallbackType as PluginCallbackType3 } from "@loglayer/plugin"; import { LogLevel as LogLevel2, LogLevelPriority } from "@loglayer/shared"; // src/LogBuilder.ts import { PluginCallbackType } from "@loglayer/plugin"; import { LogLevel } from "@loglayer/shared"; var LogBuilder = class { err; metadata; structuredLogger; hasMetadata; pluginManager; constructor(structuredLogger) { this.err = null; this.metadata = {}; this.structuredLogger = structuredLogger; this.hasMetadata = false; this.pluginManager = structuredLogger["pluginManager"]; } /** * Specifies metadata to include with the log message * * @see {@link https://loglayer.dev/logging-api/metadata.html | Metadata Docs} */ withMetadata(metadata) { const { pluginManager, structuredLogger: { _config: { consoleDebug } } } = this; if (!metadata) { if (consoleDebug) { console.debug("[LogLayer] withMetadata was called with no metadata; dropping."); } return this; } let data = metadata; if (pluginManager.hasPlugins(PluginCallbackType.onMetadataCalled)) { data = pluginManager.runOnMetadataCalled(metadata, this.structuredLogger); if (!data) { if (consoleDebug) { console.debug("[LogLayer] Metadata was dropped due to plugin returning falsy value."); } return this; } } this.metadata = { ...this.metadata, ...data }; this.hasMetadata = true; return this; } /** * Specifies an Error to include with the log message * * @see {@link https://loglayer.dev/logging-api/error-handling.html | Error Handling Docs} */ withError(error) { this.err = error; return this; } /** * Sends a log message to the logging library under an info log level. */ info(...messages) { if (!this.structuredLogger.isLevelEnabled(LogLevel.info)) return; this.structuredLogger._formatMessage(messages); this.formatLog(LogLevel.info, messages); } /** * Sends a log message to the logging library under the warn log level */ warn(...messages) { if (!this.structuredLogger.isLevelEnabled(LogLevel.warn)) return; this.structuredLogger._formatMessage(messages); this.formatLog(LogLevel.warn, messages); } /** * Sends a log message to the logging library under the error log level */ error(...messages) { if (!this.structuredLogger.isLevelEnabled(LogLevel.error)) return; this.structuredLogger._formatMessage(messages); this.formatLog(LogLevel.error, messages); } /** * Sends a log message to the logging library under the debug log level * * The logging library may or may not support multiple message parameters and only * the first parameter would be used. */ debug(...messages) { if (!this.structuredLogger.isLevelEnabled(LogLevel.debug)) return; this.structuredLogger._formatMessage(messages); this.formatLog(LogLevel.debug, messages); } /** * Sends a log message to the logging library under the trace log level * * The logging library may or may not support multiple message parameters and only * the first parameter would be used. */ trace(...messages) { if (!this.structuredLogger.isLevelEnabled(LogLevel.trace)) return; this.structuredLogger._formatMessage(messages); this.formatLog(LogLevel.trace, messages); } /** * Sends a log message to the logging library under the fatal log level * * The logging library may or may not support multiple message parameters and only * the first parameter would be used. */ fatal(...messages) { if (!this.structuredLogger.isLevelEnabled(LogLevel.fatal)) return; this.structuredLogger._formatMessage(messages); this.formatLog(LogLevel.fatal, messages); } /** * All logging inputs are dropped and stops sending logs to the logging library. */ disableLogging() { this.structuredLogger.disableLogging(); return this; } /** * Enable sending logs to the logging library. */ enableLogging() { this.structuredLogger.enableLogging(); return this; } formatLog(logLevel, params) { const { muteMetadata } = this.structuredLogger._config; const hasData = muteMetadata ? false : this.hasMetadata; this.structuredLogger._formatLog({ logLevel, params, metadata: hasData ? this.metadata : null, err: this.err }); } }; // src/PluginManager.ts import { PluginCallbackType as PluginCallbackType2 } from "@loglayer/plugin"; var CALLBACK_LIST = [ PluginCallbackType2.onBeforeDataOut, PluginCallbackType2.onMetadataCalled, PluginCallbackType2.shouldSendToLogger, PluginCallbackType2.onBeforeMessageOut, PluginCallbackType2.onContextCalled ]; var PluginManager = class { idToPlugin; // Indexes for each plugin type onBeforeDataOut = []; shouldSendToLogger = []; onMetadataCalled = []; onBeforeMessageOut = []; onContextCalled = []; constructor(plugins) { this.idToPlugin = {}; this.mapPlugins(plugins); this.indexPlugins(); } mapPlugins(plugins) { for (const plugin of plugins) { if (!plugin.id) { plugin.id = Date.now().toString() + Math.random().toString(); } if (this.idToPlugin[plugin.id]) { throw new Error(`[LogLayer] Plugin with id ${plugin.id} already exists.`); } plugin["registeredAt"] = Date.now(); this.idToPlugin[plugin.id] = plugin; } } indexPlugins() { this.onBeforeDataOut = []; this.shouldSendToLogger = []; this.onMetadataCalled = []; this.onBeforeMessageOut = []; this.onContextCalled = []; const pluginList = Object.values(this.idToPlugin).sort((a, b) => a.registeredAt - b.registeredAt); for (const plugin of pluginList) { if (plugin.disabled) { return; } for (const callback of CALLBACK_LIST) { if (plugin[callback] && plugin.id) { this[callback].push(plugin.id); } } } } hasPlugins(callbackType) { return this[callbackType].length > 0; } countPlugins(callbackType) { if (callbackType) { return this[callbackType].length; } return Object.keys(this.idToPlugin).length; } addPlugins(plugins) { this.mapPlugins(plugins); this.indexPlugins(); } enablePlugin(id) { const plugin = this.idToPlugin[id]; if (plugin) { plugin.disabled = false; } this.indexPlugins(); } disablePlugin(id) { const plugin = this.idToPlugin[id]; if (plugin) { plugin.disabled = true; } this.indexPlugins(); } removePlugin(id) { delete this.idToPlugin[id]; this.indexPlugins(); } /** * Runs plugins that defines onBeforeDataOut. */ runOnBeforeDataOut(params, loglayer) { const initialData = { ...params }; for (const pluginId of this.onBeforeDataOut) { const plugin = this.idToPlugin[pluginId]; if (plugin.onBeforeDataOut) { const result = plugin.onBeforeDataOut( { data: initialData.data, logLevel: initialData.logLevel }, loglayer ); if (result) { if (!initialData.data) { initialData.data = {}; } Object.assign(initialData.data, result); } } } return initialData.data; } /** * Runs plugins that define shouldSendToLogger. Any plugin that returns false will prevent the message from being sent to the transport. */ runShouldSendToLogger(params, loglayer) { return !this.shouldSendToLogger.some((pluginId) => { const plugin = this.idToPlugin[pluginId]; return !plugin.shouldSendToLogger?.(params, loglayer); }); } /** * Runs plugins that define onMetadataCalled. */ runOnMetadataCalled(metadata, loglayer) { let data = { ...metadata }; for (const pluginId of this.onMetadataCalled) { const plugin = this.idToPlugin[pluginId]; const result = plugin.onMetadataCalled?.(data, loglayer); if (result) { data = result; } else { return null; } } return data; } runOnBeforeMessageOut(params, loglayer) { let messages = [...params.messages]; for (const pluginId of this.onBeforeMessageOut) { const plugin = this.idToPlugin[pluginId]; const result = plugin.onBeforeMessageOut?.( { messages, logLevel: params.logLevel }, loglayer ); if (result) { messages = result; } } return messages; } /** * Runs plugins that define onContextCalled. */ runOnContextCalled(context, loglayer) { let data = { ...context }; for (const pluginId of this.onContextCalled) { const plugin = this.idToPlugin[pluginId]; const result = plugin.onContextCalled?.(data, loglayer); if (result) { data = result; } else { return null; } } return data; } }; // src/LogLayer.ts var LogLayer = class _LogLayer { pluginManager; idToTransport; hasMultipleTransports; singleTransport; contextManager; logLevelEnabledStatus = { info: true, warn: true, error: true, debug: true, trace: true, fatal: true }; /** * The configuration object used to initialize the logger. * This is for internal use only and should not be modified directly. */ _config; constructor(config) { this._config = { ...config, enabled: config.enabled ?? true }; if (!this._config.enabled) { this.disableLogging(); } this.contextManager = new DefaultContextManager(); this.pluginManager = new PluginManager(config.plugins || []); if (!this._config.errorFieldName) { this._config.errorFieldName = "err"; } if (!this._config.copyMsgOnOnlyError) { this._config.copyMsgOnOnlyError = false; } this._initializeTransports(this._config.transport); } /** * Sets the context manager to use for managing context data. */ withContextManager(contextManager) { if (this.contextManager && typeof this.contextManager[Symbol.dispose] === "function") { this.contextManager[Symbol.dispose](); } this.contextManager = contextManager; return this; } /** * Returns the context manager instance being used. */ getContextManager() { return this.contextManager; } _initializeTransports(transports) { if (this.idToTransport) { for (const id in this.idToTransport) { if (this.idToTransport[id] && typeof this.idToTransport[id][Symbol.dispose] === "function") { this.idToTransport[id][Symbol.dispose](); } } } this.hasMultipleTransports = Array.isArray(transports) && transports.length > 1; this.singleTransport = this.hasMultipleTransports ? null : Array.isArray(transports) ? transports[0] : transports; if (Array.isArray(transports)) { this.idToTransport = transports.reduce((acc, transport) => { acc[transport.id] = transport; return acc; }, {}); } else { this.idToTransport = { [transports.id]: transports }; } } /** * Calls child() and sets the prefix to be included with every log message. * * @see {@link https://loglayer.dev/logging-api/basic-logging.html#message-prefixing | Message Prefixing Docs} */ withPrefix(prefix) { const logger = this.child(); logger._config.prefix = prefix; return logger; } /** * Appends context data which will be included with * every log entry. * * Passing in an empty value / object will *not* clear the context. * * To clear the context, use {@link https://loglayer.dev/logging-api/context.html#clearing-context | clearContext()}. * * @see {@link https://loglayer.dev/logging-api/context.html | Context Docs} */ withContext(context) { let updatedContext = context; if (!context) { if (this._config.consoleDebug) { console.debug("[LogLayer] withContext was called with no context; dropping."); } return this; } if (this.pluginManager.hasPlugins(PluginCallbackType3.onContextCalled)) { updatedContext = this.pluginManager.runOnContextCalled(context, this); if (!updatedContext) { if (this._config.consoleDebug) { console.debug("[LogLayer] Context was dropped due to plugin returning falsy value."); } return this; } } this.contextManager.appendContext(updatedContext); return this; } /** * Clears the context data. */ clearContext() { this.contextManager.setContext(void 0); return this; } getContext() { return this.contextManager.getContext(); } /** * Add additional plugins. * * @see {@link https://loglayer.dev/plugins/ | Plugins Docs} */ addPlugins(plugins) { this.pluginManager.addPlugins(plugins); } /** * Enables a plugin by id. * * @see {@link https://loglayer.dev/plugins/ | Plugins Docs} */ enablePlugin(id) { this.pluginManager.enablePlugin(id); } /** * Disables a plugin by id. * * @see {@link https://loglayer.dev/plugins/ | Plugins Docs} */ disablePlugin(id) { this.pluginManager.disablePlugin(id); } /** * Removes a plugin by id. * * @see {@link https://loglayer.dev/plugins/ | Plugins Docs} */ removePlugin(id) { this.pluginManager.removePlugin(id); } /** * Specifies metadata to include with the log message * * @see {@link https://loglayer.dev/logging-api/metadata.html | Metadata Docs} */ withMetadata(metadata) { return new LogBuilder(this).withMetadata(metadata); } /** * Specifies an Error to include with the log message * * @see {@link https://loglayer.dev/logging-api/error-handling.html | Error Handling Docs} */ withError(error) { return new LogBuilder(this).withError(error); } /** * Creates a new instance of LogLayer but with the initialization * configuration and context copied over. * * @see {@link https://loglayer.dev/logging-api/child-loggers.html | Child Logging Docs} */ child() { const childConfig = { ...this._config, transport: Array.isArray(this._config.transport) ? [...this._config.transport] : this._config.transport }; const childLogger = new _LogLayer(childConfig).withPluginManager(this.pluginManager).withContextManager(this.contextManager.clone()); this.contextManager.onChildLoggerCreated({ parentContextManager: this.contextManager, childContextManager: childLogger.contextManager, parentLogger: this, childLogger }); return childLogger; } /** * Replaces all existing transports with new ones. * * When used with child loggers, it only affects the current logger instance * and does not modify the parent's transports. * * @see {@link https://loglayer.dev/logging-api/transport-management.html | Transport Management Docs} */ withFreshTransports(transports) { this._config.transport = transports; this._initializeTransports(transports); return this; } /** * Replaces all existing plugins with new ones. * * When used with child loggers, it only affects the current logger instance * and does not modify the parent's plugins. * * @see {@link https://loglayer.dev/plugins/ | Plugins Docs} */ withFreshPlugins(plugins) { this._config.plugins = plugins; this.pluginManager = new PluginManager(plugins); return this; } withPluginManager(pluginManager) { this.pluginManager = pluginManager; return this; } /** * Logs only the error object without a log message * * @see {@link https://loglayer.dev/logging-api/error-handling.html | Error Handling Docs} */ errorOnly(error, opts) { const logLevel = opts?.logLevel || LogLevel2.error; if (!this.isLevelEnabled(logLevel)) return; const { copyMsgOnOnlyError } = this._config; const formatLogConf = { logLevel, err: error }; if ((copyMsgOnOnlyError && opts?.copyMsg !== false || opts?.copyMsg === true) && error?.message) { formatLogConf.params = [error.message]; } this._formatLog(formatLogConf); } /** * Logs only metadata without a log message * * @see {@link https://loglayer.dev/logging-api/metadata.html | Metadata Docs} */ metadataOnly(metadata, logLevel = LogLevel2.info) { if (!this.isLevelEnabled(logLevel)) return; const { muteMetadata, consoleDebug } = this._config; if (muteMetadata) { return; } if (!metadata) { if (consoleDebug) { console.debug("[LogLayer] metadataOnly was called with no metadata; dropping."); } return; } let data = metadata; if (this.pluginManager.hasPlugins(PluginCallbackType3.onMetadataCalled)) { data = this.pluginManager.runOnMetadataCalled(metadata, this); if (!data) { if (consoleDebug) { console.debug("[LogLayer] Metadata was dropped due to plugin returning falsy value."); } return; } } const config = { logLevel, metadata: data }; this._formatLog(config); } /** * Sends a log message to the logging library under an info log level. * * The logging library may or may not support multiple message parameters and only * the first parameter would be used. * * @see {@link https://loglayer.dev/logging-api/basic-logging.html | Basic Logging Docs} */ info(...messages) { if (!this.isLevelEnabled(LogLevel2.info)) return; this._formatMessage(messages); this._formatLog({ logLevel: LogLevel2.info, params: messages }); } /** * Sends a log message to the logging library under the warn log level * * @see {@link https://loglayer.dev/logging-api/basic-logging.html | Basic Logging Docs} */ warn(...messages) { if (!this.isLevelEnabled(LogLevel2.warn)) return; this._formatMessage(messages); this._formatLog({ logLevel: LogLevel2.warn, params: messages }); } /** * Sends a log message to the logging library under the error log level * * @see {@link https://loglayer.dev/logging-api/basic-logging.html | Basic Logging Docs} */ error(...messages) { if (!this.isLevelEnabled(LogLevel2.error)) return; this._formatMessage(messages); this._formatLog({ logLevel: LogLevel2.error, params: messages }); } /** * Sends a log message to the logging library under the debug log level * * @see {@link https://loglayer.dev/logging-api/basic-logging.html | Basic Logging Docs} */ debug(...messages) { if (!this.isLevelEnabled(LogLevel2.debug)) return; this._formatMessage(messages); this._formatLog({ logLevel: LogLevel2.debug, params: messages }); } /** * Sends a log message to the logging library under the trace log level * * @see {@link https://loglayer.dev/logging-api/basic-logging.html | Basic Logging Docs} */ trace(...messages) { if (!this.isLevelEnabled(LogLevel2.trace)) return; this._formatMessage(messages); this._formatLog({ logLevel: LogLevel2.trace, params: messages }); } /** * Sends a log message to the logging library under the fatal log level * * @see {@link https://loglayer.dev/logging-api/basic-logging.html | Basic Logging Docs} */ fatal(...messages) { if (!this.isLevelEnabled(LogLevel2.fatal)) return; this._formatMessage(messages); this._formatLog({ logLevel: LogLevel2.fatal, params: messages }); } /** * All logging inputs are dropped and stops sending logs to the logging library. * * @see {@link https://loglayer.dev/logging-api/basic-logging.html#enabling-disabling-logging | Enabling/Disabling Logging Docs} */ disableLogging() { for (const level of Object.keys(this.logLevelEnabledStatus)) { this.logLevelEnabledStatus[level] = false; } return this; } /** * Enable sending logs to the logging library. * * @see {@link https://loglayer.dev/logging-api/basic-logging.html#enabling-disabling-logging | Enabling/Disabling Logging Docs} */ enableLogging() { for (const level of Object.keys(this.logLevelEnabledStatus)) { this.logLevelEnabledStatus[level] = true; } return this; } /** * Disables inclusion of context data in the print * * @see {@link https://loglayer.dev/logging-api/context.html#managing-context | Managing Context Docs} */ muteContext() { this._config.muteContext = true; return this; } /** * Enables inclusion of context data in the print * * @see {@link https://loglayer.dev/logging-api/context.html#managing-context | Managing Context Docs} */ unMuteContext() { this._config.muteContext = false; return this; } /** * Disables inclusion of metadata in the print * * @see {@link https://loglayer.dev/logging-api/metadata.html#controlling-metadata-output | Controlling Metadata Output Docs} */ muteMetadata() { this._config.muteMetadata = true; return this; } /** * Enables inclusion of metadata in the print * * @see {@link https://loglayer.dev/logging-api/metadata.html#controlling-metadata-output | Controlling Metadata Output Docs} */ unMuteMetadata() { this._config.muteMetadata = false; return this; } /** * Enables a specific log level * * @see {@link https://loglayer.dev/logging-api/basic-logging.html#enabling-disabling-logging | Enabling/Disabling Logging Docs} */ enableIndividualLevel(logLevel) { const level = logLevel; if (level in this.logLevelEnabledStatus) { this.logLevelEnabledStatus[level] = true; } return this; } /** * Disables a specific log level * * @see {@link https://loglayer.dev/logging-api/basic-logging.html#enabling-disabling-logging | Enabling/Disabling Logging Docs} */ disableIndividualLevel(logLevel) { const level = logLevel; if (level in this.logLevelEnabledStatus) { this.logLevelEnabledStatus[level] = false; } return this; } /** * Sets the minimum log level to be used by the logger. Only messages with * this level or higher severity will be logged. * * For example, if you setLevel(LogLevel.warn), this will: * Enable: * - warn * - error * - fatal * Disable: * - info * - debug * - trace * * @see {@link https://loglayer.dev/logging-api/basic-logging.html#enabling-disabling-logging | Enabling/Disabling Logging Docs} */ setLevel(logLevel) { const minLogValue = LogLevelPriority[logLevel]; for (const level of Object.values(LogLevel2)) { const levelKey = level; const levelValue = LogLevelPriority[level]; this.logLevelEnabledStatus[levelKey] = levelValue >= minLogValue; } return this; } /** * Checks if a specific log level is enabled * * @see {@link https://loglayer.dev/logging-api/basic-logging.html#checking-if-a-log-level-is-enabled | Checking if a Log Level is Enabled Docs} */ isLevelEnabled(logLevel) { const level = logLevel; return this.logLevelEnabledStatus[level]; } formatContext() { const { contextFieldName, muteContext } = this._config; const context = this.contextManager.getContext(); if (this.contextManager.hasContextData() && !muteContext) { if (contextFieldName) { return { [contextFieldName]: { ...context } }; } return { ...context }; } return {}; } formatMetadata(data = null) { const { metadataFieldName, muteMetadata } = this._config; if (data && !muteMetadata) { if (metadataFieldName) { return { [metadataFieldName]: { ...data } }; } return { ...data }; } return {}; } /** * Returns a logger instance for a specific transport * * @see {@link https://loglayer.dev/logging-api/transport-management.html | Transport Management Docs} */ getLoggerInstance(id) { const transport = this.idToTransport[id]; if (!transport) { return void 0; } return transport.getLoggerInstance(); } _formatMessage(messages = []) { const { prefix } = this._config; if (prefix && typeof messages[0] === "string") { messages[0] = `${prefix} ${messages[0]}`; } } _formatLog({ logLevel, params = [], metadata = null, err }) { const { errorSerializer, errorFieldInMetadata, muteContext, contextFieldName, metadataFieldName, errorFieldName } = this._config; let hasObjData = !!metadata || (muteContext ? false : this.contextManager.hasContextData()); let d = {}; if (hasObjData) { if (contextFieldName && contextFieldName === metadataFieldName) { const contextData = this.formatContext()[contextFieldName]; const updatedMetadata = this.formatMetadata(metadata)[metadataFieldName]; d = { [contextFieldName]: { ...contextData, ...updatedMetadata } }; } else { d = { ...this.formatContext(), ...this.formatMetadata(metadata) }; } } if (err) { const serializedError = errorSerializer ? errorSerializer(err) : err; if (errorFieldInMetadata && metadata) { metadata[errorFieldName] = serializedError; } else if (errorFieldInMetadata && !metadata && metadataFieldName) { d = { ...d, [metadataFieldName]: { [errorFieldName]: serializedError } }; } else { d = { ...d, [errorFieldName]: serializedError }; } hasObjData = true; } if (this.pluginManager.hasPlugins(PluginCallbackType3.onBeforeDataOut)) { d = this.pluginManager.runOnBeforeDataOut( { data: hasObjData ? d : void 0, logLevel }, this ); if (d && !hasObjData) { hasObjData = true; } } if (this.pluginManager.hasPlugins(PluginCallbackType3.onBeforeMessageOut)) { params = this.pluginManager.runOnBeforeMessageOut( { messages: [...params], logLevel }, this ); } if (this.hasMultipleTransports) { const transportPromises = this._config.transport.filter((transport) => transport.enabled).map(async (transport) => { if (this.pluginManager.hasPlugins(PluginCallbackType3.shouldSendToLogger)) { const shouldSend = this.pluginManager.runShouldSendToLogger( { messages: [...params], data: hasObjData ? d : void 0, logLevel, transportId: transport.id }, this ); if (!shouldSend) { return; } } return transport._sendToLogger({ logLevel, messages: [...params], data: hasObjData ? d : void 0, hasData: hasObjData }); }); Promise.all(transportPromises).catch((err2) => { if (this._config.consoleDebug) { console.error("[LogLayer] Error executing transports:", err2); } }); } else { if (!this.singleTransport?.enabled) { return; } if (this.pluginManager.hasPlugins(PluginCallbackType3.shouldSendToLogger)) { const shouldSend = this.pluginManager.runShouldSendToLogger( { messages: [...params], data: hasObjData ? d : void 0, logLevel, transportId: this.singleTransport.id }, this ); if (!shouldSend) { return; } } this.singleTransport._sendToLogger({ logLevel, messages: [...params], data: hasObjData ? d : void 0, hasData: hasObjData }); } } }; // src/MockLogBuilder.ts var MockLogBuilder = class { debug(..._messages) { } error(..._messages) { } info(..._messages) { } trace(..._messages) { } warn(..._messages) { } fatal(..._messages) { } enableLogging() { return this; } disableLogging() { return this; } withMetadata(_metadata) { return this; } withError(_error) { return this; } }; // src/MockLogLayer.ts var MockLogLayer = class { mockLogBuilder = new MockLogBuilder(); info(..._messages) { } warn(..._messages) { } error(..._messages) { } debug(..._messages) { } trace(..._messages) { } fatal(..._messages) { } getLoggerInstance(_id) { return void 0; } errorOnly(_error, _opts) { } metadataOnly(_metadata, _logLevel) { } addPlugins(_plugins) { } removePlugin(_id) { } enablePlugin(_id) { } disablePlugin(_id) { } withPrefix(_prefix) { return this; } withContext(_context) { return this; } withError(error) { this.mockLogBuilder.withError(error); return this.mockLogBuilder; } withMetadata(metadata) { this.mockLogBuilder.withMetadata(metadata); return this.mockLogBuilder; } getContext() { return {}; } clearContext() { return this; } enableLogging() { return this; } disableLogging() { return this; } child() { return this; } muteContext() { return this; } unMuteContext() { return this; } muteMetadata() { return this; } unMuteMetadata() { return this; } withFreshTransports(_transports) { return this; } withFreshPlugins(_plugins) { return this; } withContextManager(_contextManager) { return this; } getContextManager() { return void 0; } /** * Sets the mock log builder to use for testing. */ setMockLogBuilder(mockLogBuilder) { this.mockLogBuilder = mockLogBuilder; } enableIndividualLevel(_logLevel) { return this; } disableIndividualLevel(_logLevel) { return this; } setLevel(_logLevel) { return this; } isLevelEnabled(_logLevel) { return true; } /** * Returns the mock log builder used for testing. */ getMockLogBuilder() { return this.mockLogBuilder; } /** * Resets the mock log builder to a new instance of MockLogBuilder. */ resetMockLogBuilder() { this.mockLogBuilder = new MockLogBuilder(); } }; // src/TestLoggingLibrary.ts import { LogLevel as LogLevel3 } from "@loglayer/shared"; var TestLoggingLibrary = class { /** * An array of log lines that have been logged. */ lines; constructor() { this.lines = []; } info(...params) { this.addLine(LogLevel3.info, params); } warn(...params) { this.addLine(LogLevel3.warn, params); } error(...params) { this.addLine(LogLevel3.error, params); } debug(...params) { this.addLine(LogLevel3.debug, params); } trace(...params) { this.addLine(LogLevel3.trace, params); } fatal(...params) { this.addLine(LogLevel3.fatal, params); } addLine(logLevel, params) { this.lines.push({ level: logLevel, data: params }); } /** * Get the last line that was logged. Returns null if no lines have been logged. */ getLastLine() { if (!this.lines.length) { return null; } return this.lines[this.lines.length - 1]; } /** * Pops the last line that was logged. Returns null if no lines have been logged. */ popLine() { return this.lines.pop(); } /** * Clears all lines that have been logged. */ clearLines() { this.lines = []; } }; // src/transports/BlankTransport.ts import { LoggerlessTransport } from "@loglayer/transport"; var BlankTransport = class extends LoggerlessTransport { shipToLoggerFn; constructor(config) { super(config); this.shipToLoggerFn = config.shipToLogger; } shipToLogger(params) { return this.shipToLoggerFn(params); } }; // src/transports/ConsoleTransport.ts import { LogLevel as LogLevel4 } from "@loglayer/shared"; import { BaseTransport, LogLevelPriority as LogLevelPriority2 } from "@loglayer/transport"; var ConsoleTransport = class extends BaseTransport { appendObjectData; logLevel; messageField; dateField; levelField; dateFn; levelFn; constructor(params) { super(params); this.appendObjectData = params.appendObjectData || false; this.logLevel = params.level ?? "trace"; this.messageField = params.messageField; this.dateField = params.dateField; this.levelField = params.levelField; this.dateFn = params.dateFn; this.levelFn = params.levelFn; } shipToLogger({ logLevel, messages, data, hasData }) { if (LogLevelPriority2[logLevel] < LogLevelPriority2[this.logLevel]) { return; } if (this.messageField || this.dateField || this.levelField) { const messageText = this.messageField ? messages.join(" ") : void 0; const logObject = { ...data || {}, ...this.messageField && { [this.messageField]: messageText }, ...this.dateField && { [this.dateField]: this.dateFn ? this.dateFn() : (/* @__PURE__ */ new Date()).toISOString() }, ...this.levelField && { [this.levelField]: this.levelFn ? this.levelFn(logLevel) : logLevel } }; messages = [logObject]; } else if (data && hasData) { if (this.appendObjectData) { messages.push(data); } else { messages.unshift(data); } } switch (logLevel) { case LogLevel4.info: this.logger.info(...messages); break; case LogLevel4.warn: this.logger.warn(...messages); break; case LogLevel4.error: this.logger.error(...messages); break; case LogLevel4.trace: this.logger.trace(...messages); break; case LogLevel4.debug: this.logger.debug(...messages); break; case LogLevel4.fatal: this.logger.error(...messages); break; } return messages; } }; // src/transports/TestTransport.ts import { LogLevel as LogLevel5 } from "@loglayer/shared"; import { BaseTransport as BaseTransport2 } from "@loglayer/transport"; var TestTransport = class extends BaseTransport2 { shipToLogger({ logLevel, messages, data, hasData }) { if (data && hasData) { messages.unshift(data); } switch (logLevel) { case LogLevel5.info: this.logger.info(...messages); break; case LogLevel5.warn: this.logger.warn(...messages); break; case LogLevel5.error: this.logger.error(...messages); break; case LogLevel5.trace: this.logger.trace(...messages); break; case LogLevel5.debug: this.logger.debug(...messages); break; case LogLevel5.fatal: this.logger.fatal(...messages); break; } return messages; } }; export { BlankTransport, ConsoleTransport, LogLayer, LogLevel6 as LogLevel, MockLogBuilder, MockLogLayer, PluginCallbackType4 as PluginCallbackType, TestLoggingLibrary, TestTransport };