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
JavaScript
// 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
};