Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

logging-utils

Package Overview
Dependencies
Maintainers
1
Versions
54
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

logging-utils - npm Package Compare versions

Comparing version 3.0.12 to 4.0.0

copy.sh

550

logging.js

@@ -13,2 +13,35 @@ 'use strict';

*
* The default logging configuration uses the following settings:
* - Log level is set to logLevel from the local default-options.json file (if any); otherwise to defaults.logLevel (currently LogLevel.INFO)
* - Use level prefixes is set to useLevelPrefixes from the local default-options.json file (if any); otherwise to defaults.useLevelPrefixes (currently true)
* - The log level environment variable name is set to envLogLevelName from the local default-options.json file (if any); otherwise to defaults.envLogLevelName (currently 'LOG_LEVEL')
* - The underlying logger is set to console
* - Use console trace is set to useConsoleTrace from the local default-options.json file (if any); otherwise to defaults.useConsoleTrace (currently false)
*
* Primary usage:
* - First configure logging on an existing object (do this once, during start-up)
* const context = {...}; // an existing object to configure with logging functionality
* configureLogging(context, {logLevel: LogLevel.DEBUG});
*
* - Then later use the configured object to do logging, for example:
* let err = new Error('Some arbitrary error');
* context.error('Insert error message here', err.stack);
* if (context.warnEnabled) context.warn('Insert warning here');
* context.info('FYI');
* if (log.debugEnabled) context.debug('Insert debug message here');
* context.trace('Some detailed tracing message goes here');
*
* Alternative usage:
* - First configure logging on a new "logger" object (do this once, during start-up):
* const settings = {logLevel: LogLevel.WARN, useLevelPrefixes: true, underlyingLogger: console, useConsoleTrace: false};
* const log = configureLogging({}, settings, undefined, true);
*
* - Then later use the configured object to do logging, for example:
* let err = new Error('Some arbitrary error');
* log.error('Insert error message here', err.stack);
* log.warn('Insert warning here');
* if (log.infoEnabled) log.info('FYI');
* log.debug('Insert debug message here');
* if (log.traceEnabled) log.trace('Some detailed tracing message goes here');
*
* @module logging-utils/logging

@@ -19,6 +52,6 @@ * @author Byron du Preez

// Dependencies
const strings = require('core-functions/strings');
const isBlank = strings.isBlank;
const isString = strings.isString;
//const stringify = strings.stringify;
const Strings = require('core-functions/strings');
const isNotBlank = Strings.isNotBlank;
const isString = Strings.isString;
const stringify = Strings.stringify;

@@ -33,34 +66,53 @@ const Objects = require('core-functions/objects');

// Constants for log levels
const ERROR = 'error';
const WARN = 'warn';
const INFO = 'info';
const DEBUG = 'debug';
const TRACE = 'trace';
/**
* An enum for the various logging levels supported
* @enum {string}
* @readonly
*/
const LogLevel = {
ERROR: 'ERROR',
WARN: 'WARN',
INFO: 'INFO',
DEBUG: 'DEBUG',
TRACE: 'TRACE'
};
Object.freeze(LogLevel);
/**
* The last-resort, default options to fallback to during configuration to fill in any missing settings
* @type LoggingOptions
*/
const defaults = {
logLevel: LogLevel.INFO,
useLevelPrefixes: true,
envLogLevelName: 'LOG_LEVEL',
useConsoleTrace: false
};
// Exports
module.exports = {
// Functions to configure logging
/** Valid log levels */
LogLevel: LogLevel,
/** Returns true, if the given target already has logging functionality configured on it; otherwise returns false. */
isLoggingConfigured: isLoggingConfigured,
/** Configures a target object with logging functionality using given logging settings (if any) or using default logging settings partially overridden by given logging options (if any) */
configureLogging: configureLogging,
/** Configures a target object with logging functionality based on given logging settings */
configureLoggingWithSettings: configureLoggingWithSettings,
/** Configures a target object with default logging functionality partially overridden with given logging options */
configureDefaultLogging: configureDefaultLogging,
/** Returns a logging settings object constructed from given or default logging options and the given underlyingLogger */
getDefaultLoggingSettings: getDefaultLoggingSettings,
// Constants for Log Levels
/** Constant for the ERROR log level */
ERROR: ERROR,
/** Constant for the WARN log level */
WARN: WARN,
/** Constant for the INFO log level */
INFO: INFO,
/** Constant for the DEBUG log level */
DEBUG: DEBUG,
/** Constant for the TRACE log level */
TRACE: TRACE,
/** Returns a clean and complete copy of the default logging options */
getDefaultLoggingOptions: getDefaultLoggingOptions,
/** A convenience function that delegates the logging to the log method of the given logger or of console */
log: log,
isValidLogLevel: isValidLogLevel,
cleanLogLevel: cleanLogLevel,
isMinimumViableLogger: isMinimumViableLogger
// FOR_TESTING_ONLY: {
// /** Loads a clean, but potentially incomplete, copy of the default logging options from the local default-options.json file */
// loadDefaultLoggingOptions: loadDefaultLoggingOptions,
// toLoggingSettingsWithDefaults: toLoggingSettingsWithDefaults
// }
};

@@ -80,43 +132,15 @@

/**
* Configures the given target object with logging functionality using the given logging settings (if any) or using
* default logging settings partially overridden by the given logging options (if any), but ONLY if forceConfiguration
* is true or if there is no logging functionality already configured on the target object.
* @param {Object} target - the context to configure with logging
* @param {LoggingSettings|undefined} [settings] - optional logging settings to use
* @param {LoggingOptions|undefined} [options] - optional logging options to use if no logging settings provided
* @param {Object|undefined} [underlyingLogger] - the optional underlying logger to use to do the actual logging
* @param {boolean|undefined} [forceConfiguration] - whether or not to force configuration of the logging functionality,
* which will override any previously configured logging functionality on the target object
* @returns {Logging} the given target object with logging functionality configured
*/
function configureLogging(target, settings, options, underlyingLogger, forceConfiguration) {
// Check if logging was already configured
const loggingWasConfigured = isLoggingConfigured(target);
// Determine the logging settings to be used
const loggingSettingsAvailable = settings && typeof settings === 'object';
const loggingOptionsAvailable = options && typeof options === 'object';
const loggingSettings = loggingSettingsAvailable ?
loggingOptionsAvailable ? Objects.merge(options, settings, false, false) : settings :
getDefaultLoggingSettings(options, underlyingLogger);
// Configure logging with the given or derived logging settings
configureLoggingWithSettings(target, loggingSettings, forceConfiguration);
// Log a warning if no settings and no options were provided and the default settings were applied
if (!loggingSettingsAvailable && (!options || typeof options !== 'object') && (forceConfiguration || !loggingWasConfigured)) {
target.warn(`Logging was configured without settings or options - used default logging configuration (${JSON.stringify(loggingSettings)})`);
}
return target;
}
/**
* Configures logging functionality on the given target object, but ONLY if forceConfiguration is true or if there is no
* logging functionality already configured on the target, based on the given logging settings and returns the target
* updated with the following:
* Configures the given target object with logging functionality using the given logging settings (if any) and/or
* options (if any), preferring valid individual settings over valid options and using default settings to fill in any
* missing settings, but ONLY if forceConfiguration is true or if there is no logging functionality already configured
* on the target object.
*
* Returns the target object updated with the following:
* - Four enabled flags (warnEnabled, infoEnabled, debugEnabled and traceEnabled), which can be used to check whether
* warn, info, debug or trace level logging is enabled or not (and thus avoid the overhead of even building the
* message to be logged, if the level is not enabled); and
* - Five logging functions (error, warn, info, debug & trace), which simply delegate the actual logging to the
* - Five logging methods (error, warn, info, debug & trace), which simply delegate the actual logging to the
* underlying logger.
* - A convenience log method, which expects a log level as its first argument and delegates the logging to the
* appropriate one of the five logging method according to the log level
*

@@ -126,29 +150,10 @@ * Note that you can call any of the 5 logging functions without first checking the corresponding enabled flag and the

*
* Example 1 - primary usage (to configure logging on an existing object):
* const context = {...}; // an existing object on which to configure logging
* configureLoggingWithSettings(context, {logLevel: 'info'});
* let err = new Error('Some arbitrary error');
* context.error('Insert error message here', err.stack);
* if (context.warnEnabled) context.warn('Insert warning here');
* context.info('FYI');
* if (log.debugEnabled) context.debug('Insert debug message here');
* context.trace('Some detailed tracing message goes here');
*
* Example 2 - secondary usage (to configure logging on a new object):
* const settings = {logLevel: 'info', useLevelPrefixes: true, underlyingLogger: console, useConsoleTrace: false};
* const log = configureLoggingWithSettings({}, settings, true);
* let err = new Error('Some arbitrary error');
* log.error('Insert error message here', err.stack);
* log.warn('Insert warning here');
* if (log.infoEnabled) log.info('FYI');
* log.debug('Insert debug message here');
* if (log.traceEnabled) log.trace('Some detailed tracing message goes here');
*
* @param {Object} target the target object to which to add the logging functionality
* @param {LoggingSettings|undefined} [settings] - the optional logging settings to configure
* @param {Object|Logger} target - the target object to configure with logging functionality
* @param {LoggingSettings|LoggingOptions|undefined} [settings] - optional logging settings to use
* @param {LoggingOptions|undefined} [options] - optional logging options to use when no corresponding setting is provided
* @param {boolean|undefined} [forceConfiguration] - whether or not to force configuration of the logging functionality,
* which will override any previously configured logging functionality on the target object
* @return {Logging} the updated target object with logging functionality configured
* @returns {Logger} the given target object with logging functionality configured
*/
function configureLoggingWithSettings(target, settings, forceConfiguration) {
function configureLogging(target, settings, options, forceConfiguration) {
// If forceConfiguration is false check if the given target already has logging functionality configured on it

@@ -159,34 +164,103 @@ // and, if so, do nothing more and simply return the target as is (to prevent overriding an earlier configuration)

}
// Use the given settings (if any) or the default settings (if any missing)
const underlyingLogger = settings && typeof settings === 'object' ? settings.underlyingLogger : undefined;
const loggingSettings = getDefaultLoggingSettings(settings, underlyingLogger);
const logLevel = loggingSettings.logLevel;
const useLevelPrefixes = loggingSettings.useLevelPrefixes;
const useConsoleTrace = loggingSettings.useConsoleTrace;
const logger = loggingSettings.underlyingLogger;
// Ensure that any underlying logger to be configured is a minimum viable logger
//noinspection JSUnresolvedVariable
const logger = settings && settings.underlyingLogger ? settings.underlyingLogger :
options && options.underlyingLogger ? options.underlyingLogger : undefined;
if (logger && !isMinimumViableLogger(logger)) {
const errMsg = `FATAL - Cannot configure logging with a logger that is NOT a minimum viable logger - logger: ${stringify(logger)}`;
console.error(errMsg);
throw new Error(errMsg);
}
// Create clean copies of the given settings and options
settings = toCleanSettingsOrOptions(settings);
options = toCleanSettingsOrOptions(options);
// Resolve the logging settings to use by merging the clean options (if any) into the clean settings (if any) without
// replacing any existing clean settings
const loggingSettings = settings ? (options ? Objects.merge(options, settings) : settings) : options;
// Finalise the logging settings by using the default options to fill in any missing settings
const defaultOptions = getDefaultLoggingOptions();
const loggingSettingsWithDefaults = loggingSettings ?
Objects.merge(defaultOptions, loggingSettings) : defaultOptions;
// Configure logging with the finalised logging settings
_configureLogging(target, loggingSettingsWithDefaults);
return target;
}
/**
* Configures the given target object with logging functionality using the given logging settings.
* @param {Object} target the target object to which to add the logging functionality
* @param {LoggingSettings} settings - the logging settings to configure
* @returns {Logger} the updated target object with logging functionality configured
* @private
*/
function _configureLogging(target, settings) {
const envLogLevelName = settings.envLogLevelName;
// If a logLevel is configured in the named environment variable then use it instead
const envLogLevel = process.env[envLogLevelName];
const logLevel = isValidLogLevel(envLogLevel) ? cleanLogLevel(envLogLevel) : settings.logLevel;
const useLevelPrefixes = settings.useLevelPrefixes;
const useConsoleTrace = settings.useConsoleTrace;
const logger = isMinimumViableLogger(settings.underlyingLogger) ? settings.underlyingLogger : console;
// Finalise the underlying logging methods to be used
const loggerInfo = logger === console ? console.log : logger.info;
const loggerDebug = logger === console ? console.log : logger.debug;
const usingConsole = logger === console;
const hasInfoMethod = usingConsole || typeof logger.info === 'function';
const hasLogMethod = usingConsole || typeof logger.log === 'function';
const loggerTrace = logger === console ? useConsoleTrace ? console.trace : console.log : logger.trace;
const usingConsoleTrace = logger === console && useConsoleTrace;
if (!hasLogMethod && !hasInfoMethod) {
throw new Error(`FATAL: Cannot configure logging with an underlying logger that has neither a log method nor an info method - logger (${stringify(logger)})`);
}
if (!hasLogMethod) {
console.warn('WARNING - The configured underlying logger has NO log method - falling back to using its info method, which is not a complete replacement!');
}
if (!hasInfoMethod) {
console.warn('WARNING - The configured underlying logger has NO info method - falling back to using its log method');
}
// Resolve logger's info method, but fallback to using logger.log if it has no logger.info
const loggerInfo = usingConsole ? console.info : hasInfoMethod ? logger.info : logger.log; //hasLogMethod ? logger.log : undefined;
// Resolve logger's warn method, but fallback to using logger.error if it has no logger.warn method
const loggerWarn = usingConsole ? console.warn : typeof logger.warn === 'function' ? logger.warn : logger.error;
// Resolve logger's debug method, but fallback to using loggerInfo if it has no logger.debug method
const loggerDebug = usingConsole ? console.info : typeof logger.debug === 'function' ? logger.debug : loggerInfo;
// Resolve logger's trace method, but fallback to using loggerDebug if it has no logger.trace method
const loggerTrace = usingConsole ? useConsoleTrace ? console.trace : console.info :
typeof logger.trace === "function" ? logger.trace : loggerDebug;
// Resolve logger's log method, but fallback to using loggerInfo if it has no logger.log method, which is NOT technically a
// proper replacement for a log method, but nevertheless ...
const loggerLog = hasLogMethod ? logger.log : loggerInfo;
const usingConsoleTrace = usingConsole && useConsoleTrace;
// Use log level to determine which levels are enabled
const traceEnabled = logLevel === TRACE;
const debugEnabled = traceEnabled || logLevel === DEBUG;
const infoEnabled = debugEnabled || logLevel === INFO;
const warnEnabled = infoEnabled || logLevel === WARN;
const traceEnabled = logLevel === LogLevel.TRACE;
const debugEnabled = traceEnabled || logLevel === LogLevel.DEBUG;
const infoEnabled = debugEnabled || logLevel === LogLevel.INFO;
const warnEnabled = infoEnabled || logLevel === LogLevel.WARN;
// Set up the appropriate function to use for logging at each level
const error = useLevelPrefixes ? withPrefix(logger.error, 'ERROR') : logger.error;
const warn = warnEnabled ? useLevelPrefixes ? withPrefix(logger.warn, 'WARN') : logger.warn : noop;
const info = infoEnabled ? useLevelPrefixes ? withPrefix(loggerInfo, 'INFO') : loggerInfo : noop;
const debug = debugEnabled ? useLevelPrefixes ? withPrefix(loggerDebug, 'DEBUG') : loggerDebug : noop;
const error = useLevelPrefixes ? withPrefix(logger.error, 'ERROR', logger) : logger.error;
const warn = warnEnabled ? useLevelPrefixes ? withPrefix(loggerWarn, 'WARN', logger) : loggerWarn : noop;
const info = infoEnabled ? useLevelPrefixes ? withPrefix(loggerInfo, 'INFO', logger) : loggerInfo : noop;
const debug = debugEnabled ? useLevelPrefixes ? withPrefix(loggerDebug, 'DEBUG', logger) : loggerDebug : noop;
// Note that we skip adding a prefix when using console.trace, since it already includes its own prefix 'Trace: '
const trace = traceEnabled ? useLevelPrefixes && !usingConsoleTrace ? withPrefix(loggerTrace, 'TRACE') : loggerTrace : noop;
const trace = traceEnabled ? useLevelPrefixes && !usingConsoleTrace ? withPrefix(loggerTrace, 'TRACE', logger) : loggerTrace : noop;
// To enable the underlying logger's log method's output to ALSO be suppressed, treat it as if it logs at INFO level
// (i.e. it will be suppressed if infoEnabled is false), but prefix it with 'LOG' instead of 'INFO' (to distinguish it
// from INFO logging output) when useLevelPrefixes is true
const log = infoEnabled ? useLevelPrefixes ? withPrefix(loggerLog, 'LOG', logger) : loggerLog : noop;
// Add the logging functionality to the given target object
target.logLevel = logLevel; // for info and testing purposes
target._underlyingLogger = logger; // for testing purposes ONLY
target.warnEnabled = warnEnabled;

@@ -201,4 +275,5 @@ target.infoEnabled = infoEnabled;

target.trace = trace;
target.log = generateLogFunction(log, logger);
target.info(`Logging configured with level ${logLevel.toUpperCase()}, with${useLevelPrefixes ? '' : 'out'} level prefixes & with${useConsoleTrace ? '' : 'out'} console.trace`);
target.info(`Logging configured with level ${logLevel}, with${useLevelPrefixes ? '' : 'out'} prefixes, with env log level name '${envLogLevelName}' & with${useConsoleTrace ? '' : 'out'} console.trace`);

@@ -209,93 +284,51 @@ return target;

/**
* Configures the default logging functionality on the given target object partially overridden by the given logging
* options (if any), but ONLY if no logging functionality is already configured on the target.
*
* The default logging configuration uses the following settings:
* - Log level is set to the local config.loggingOptions.logLevel (if any) or INFO.
* - Use level prefixes is set to the local config.loggingOptions.useLevelPrefixes (if any) or true.
* - The underlying logger is set to the given underlyingLogger (if valid) otherwise to console.
* - Use console trace is set to the local config.loggingOptions.useConsoleTrace (if any) or false.
*
* @param {Object} target - the target object to which to add default logging functionality
* @param {LoggingOptions|undefined} [options] - optional logging options to use to override the default options
* @param {Object|undefined} [underlyingLogger] - the optional underlying logger to use to do the actual logging
* @param {boolean|undefined} [forceConfiguration] - whether or not to force configuration of the default logging
* functionality, which will override any previously configured logging functionality on the target object
* @return {Logging} the updated target object with logging functionality configured
* Loads a clean, but potentially incomplete, copy of the default logging options from the local default-options.json file.
* @returns {LoggingOptions|undefined} clean (potentially incomplete) copy of default options loaded from the local file
*/
function configureDefaultLogging(target, options, underlyingLogger, forceConfiguration) {
const settings = getDefaultLoggingSettings(options, underlyingLogger);
return configureLoggingWithSettings(target, settings, forceConfiguration);
function loadDefaultLoggingOptions() {
return toCleanSettingsOrOptions(require('./default-options.json'));
}
/**
* Returns the default logging settings either partially or fully overridden by the given logging options (if any) and
* the given underlyingLogger (if any).
*
* This function is used internally by {@linkcode configureLogging}, {@linkcode configureLoggingWithSettings} and
* {@linkcode configureDefaultLogging}, but could also be used in custom configurations to get the default settings as a
* base to be overridden with your custom settings before calling {@linkcode configureLogging}.
*
* @param {LoggingOptions|undefined} [options] - optional logging options to use to override the default options
* @param {Object|undefined} [underlyingLogger] - the optional underlying logger to use to do the actual logging
* @returns {LoggingSettings} a logging settings object
* Returns a clean and complete copy of the default logging options, which are a combination of the options loaded from
* the local default-options.json file and the static defaults, which are used to fill in any missing options.
* @returns {LoggingOptions} the complete and clean default options
*/
function getDefaultLoggingSettings(options, underlyingLogger) {
const logger = isValidLogger(underlyingLogger) ? underlyingLogger : console;
// Check if all of the options were provided, and if so use them instead of looking up defaults
const optionsAvailable = options && typeof options === 'object';
if (optionsAvailable && isValidLogLevel(options.logLevel) && isBoolean(options.useLevelPrefixes)
&& isBoolean(options.useConsoleTrace)) {
return {
logLevel: options.logLevel.trim().toLowerCase(),
useLevelPrefixes: options.useLevelPrefixes,
useConsoleTrace: options.useConsoleTrace,
underlyingLogger: logger
};
}
// Either no options are available or missing some options, so load local default logging options
const config = require('./config.json');
const defaultLogLevel = toValidLogLevelOrDefault(config.loggingOptions.logLevel, INFO);
const defaultUseLevelPrefixes = isBoolean(config.loggingOptions.useLevelPrefixes) ?
config.loggingOptions.useLevelPrefixes : true;
const defaultUseConsoleTrace = isBoolean(config.loggingOptions.useConsoleTrace) ?
config.loggingOptions.useConsoleTrace : false;
// If no options are available, then return the default logging options
if (!optionsAvailable) {
return {
logLevel: defaultLogLevel,
useLevelPrefixes: defaultUseLevelPrefixes,
useConsoleTrace: defaultUseConsoleTrace,
underlyingLogger: logger
}
}
// Some options are available, so return a combination of the available options and the default options (where missing)
return {
logLevel: toValidLogLevelOrDefault(options.logLevel, defaultLogLevel),
useLevelPrefixes: isBoolean(options.useLevelPrefixes) ? options.useLevelPrefixes : defaultUseLevelPrefixes,
useConsoleTrace: isBoolean(options.useConsoleTrace) ? options.useConsoleTrace : defaultUseConsoleTrace,
underlyingLogger: logger
};
function getDefaultLoggingOptions() {
const defaultOptions = loadDefaultLoggingOptions();
return defaultOptions ? Objects.merge(defaults, defaultOptions) : Objects.copy(defaults);
}
/**
* Cleans up and attempts to match the given log level against a valid logging level and if it succeeds returns the
* corresponding logging level; otherwise returns the given default logging level.
* @param {string|undefined} [logLevel] - the optional log level to validate
* @param {string} defaultLogLevel
* @returns {string} the corresponding logging level (if valid); otherwise the given default logging level
* Returns a clean copy of the given logging options or settings WITHOUT any invalid properties and with a clean
* logLevel (if it has a valid logLevel) if optionsOrSettings is a non-null object; otherwise returns undefined.
* @param {LoggingOptions|LoggingSettings|undefined|*} [optionsOrSettings] - optional logging options or settings
* @returns {LoggingOptions|LoggingSettings|undefined} a clean copy of the given logging options or settings (if any) or undefined
*/
function toValidLogLevelOrDefault(logLevel, defaultLogLevel) {
if (isString(logLevel) && !isBlank(logLevel)) {
if (isValidLogLevel(logLevel)) {
return logLevel.trim().toLowerCase();
}
console.warn(`Unexpected logging level (${logLevel}) - defaulting to (${defaultLogLevel}) level logging`);
return defaultLogLevel;
function toCleanSettingsOrOptions(optionsOrSettings) {
if (!optionsOrSettings || typeof optionsOrSettings !== 'object') return undefined;
const cleaned = optionsOrSettings ? Objects.copy(optionsOrSettings) : {};
if (isValidLogLevel(cleaned.logLevel)) {
cleaned.logLevel = cleanLogLevel(cleaned.logLevel);
} else {
delete cleaned.logLevel;
}
return defaultLogLevel;
if (!isBoolean(cleaned.useLevelPrefixes)) {
delete cleaned.useLevelPrefixes;
}
if (isNotBlank(cleaned.envLogLevelName)) {
cleaned.envLogLevelName = cleaned.envLogLevelName.trim();
} else {
delete cleaned.envLogLevelName;
}
if (!isBoolean(cleaned.useConsoleTrace)) {
delete cleaned.useConsoleTrace;
}
if (cleaned.underlyingLogger && !isMinimumViableLogger(cleaned.underlyingLogger)) {
console.warn('Skipping configured underlying logger, since it is NOT a minimum viable logger');
delete cleaned.underlyingLogger;
}
return cleaned;
}

@@ -305,33 +338,39 @@

* Returns true if the given log level is a valid logging level; otherwise returns false.
* @param {string|undefined} [logLevel] - the optional log level to validate
* @param {LogLevel|string|undefined} [logLevel] - the optional log level to validate
* @returns {boolean} true if a valid logging level; false otherwise
*/
function isValidLogLevel(logLevel) {
if (isString(logLevel) && !isBlank(logLevel)) {
const level = logLevel.trim().toLowerCase();
switch (level) {
case ERROR:
case WARN:
case INFO:
case DEBUG:
case TRACE:
return true;
default:
return false;
}
const level = cleanLogLevel(logLevel);
switch (level) {
case LogLevel.ERROR:
case LogLevel.WARN:
case LogLevel.INFO:
case LogLevel.DEBUG:
case LogLevel.TRACE:
return true;
default:
return false;
}
return false;
}
/**
* Checks whether the given logger is either console or has error, warn, info, debug and trace methods.
* @param logger the underlying logger to be checked
* @returns {boolean} true if console or valid; false otherwise
* Cleans the given log level (if any) by trimming it and converting it to uppercase.
* @param {LogLevel} logLevel
* @returns {LogLevel} the cleaned log level
*/
function isValidLogger(logger) {
return logger === console || (logger && typeof logger.error === 'function' && typeof logger.warn === 'function'
&& typeof logger.info === 'function' && typeof logger.debug === 'function' && typeof logger.trace === 'function');
function cleanLogLevel(logLevel) {
return logLevel && logLevel.trim ? logLevel.trim().toUpperCase() : logLevel;
}
/**
* Checks whether the given logger is either console or a minimum viable logger-like object, which means that it must
* have AT LEAST a `log` method and an `error` method.
* @param {Logger|BasicLogger|*} logger - the logger to be checked
* @returns {boolean} true if console or a valid (minimum viable) logger-like object; false otherwise
*/
function isMinimumViableLogger(logger) {
return logger === console || (logger && typeof logger.log === 'function' && typeof logger.error === 'function');
}
/**
* Returns a function which wraps the given logFn in order to prepend the given level prefix to its first argument when

@@ -341,5 +380,6 @@ * invoked.

* @param {string} logLevelPrefix the prefix to prepend
* @param {Logger|BasicLogger} logger - the underlying logger from which the logFn originates
* @return {logWithPrefix} a prefix-prepending function that delegates to the given logFn
*/
function withPrefix(logFn, logLevelPrefix) {
function withPrefix(logFn, logLevelPrefix, logger) {
function logWithPrefix() {

@@ -352,6 +392,90 @@ if (arguments && arguments.length > 0) {

}
return logFn.apply(console, arguments);
return logFn.apply(logger, arguments);
}
return logWithPrefix;
}
/**
* A convenience function that delegates the logging to the log method of either the given logger (if its defined and
* has a log or info method) or to console (if not)
* @param {Logger|BasicLogger|undefined} [logger] - the optional logger to use
* @param {...*} data - zero or more data items to be logged
*/
function log(logger, data) {
// Collect all arguments other than logger
const len = arguments.length;
const args = new Array(len - 1);
for (let i = 1; i < len; ++i) {
args[i - 1] = arguments[i];
}
// If a logger was provided & it has a log method, then use it
if (logger && typeof logger.log === 'function') {
logger.log.apply(logger, args);
} else if (logger && typeof logger.info === 'function') {
// If a logger was provided & it has a log method, then use it
logger.info.apply(logger, args);
} else {
// otherwise use console
console.log.apply(console, args);
}
}
/**
* Generates a log function that will delegate the logging to the appropriate logging function based on a given log
* level (if its valid) and otherwise default to using the given conventional logger log function.
* @param {function(...*)} loggerLog - the potentially wrapped underlying logger's log method (if any) or info method (if none)
* @param {Logger|BasicLogger|undefined} logger - the logger from which the log method originated
* @returns {function(...data)} a modified version of the given log function
*/
function generateLogFunction(loggerLog, logger) {
/**
* An extension of the conventional log method that first checks if the first argument is a valid log level and if so
* instead delegates the call to the appropriate logging function for the specified log level (passing any and all
* arguments after the first argument to it); and otherwise simply delegates the log call to the underlying logger's
* log method (if any) or info method (if none) passing ALL of the original arguments to it.
* @param {...*} data - zero or more data items to be logged - with special meaning assigned to the first argument
* both by this function and by the underlying logger's log method (e.g. see console.log)
*/
function log(data) {
// If NO arguments were passed, then delegate a no-arg call to the given logger log function
const len = arguments.length;
if (len <= 0) {
loggerLog();
return;
}
const logLevel = cleanLogLevel(arguments[0]);
let logFn = undefined;
switch (logLevel) {
case LogLevel.ERROR:
logFn = this.error;
break;
case LogLevel.WARN:
logFn = this.warn;
break;
case LogLevel.INFO:
logFn = this.info;
break;
case LogLevel.DEBUG:
logFn = this.debug;
break;
case LogLevel.TRACE:
logFn = this.trace;
break;
default:
// If no valid log level was provided as a first argument then default to calling the given logger log function
// using ALL of the arguments as data
loggerLog.apply(logger, arguments);
return;
}
// Collect all arguments other than logLevel
const args = new Array(len - 1);
for (let i = 1; i < len; ++i) {
args[i - 1] = arguments[i];
}
logFn.apply(logger, args);
}
return log;
}
{
"name": "logging-utils",
"description": "Utilities for configuring simple log level based logging functionality on an object",
"version": "3.0.12",
"version": "4.0.0",
"author": "Byron du Preez",

@@ -16,4 +16,4 @@ "license": "Apache-2.0",

"dependencies": {
"core-functions": "^2.0.14"
"core-functions": "^3.0.0"
}
}

@@ -1,2 +0,2 @@

# logging-utils v3.0.12
# logging-utils v4.0.0
Utilities for configuring simple log level based logging functionality on an object.

@@ -29,82 +29,74 @@

```js
// To use the logging utilties
// To use the logging utilities
const logging = require('logging-utils');
// Valid logging levels
const LogLevel = logging.LogLevel;
// Logging configuration functions
const isLoggingConfigured = logging.isLoggingConfigured;
const configureLoggingWithSettings = logging.configureLoggingWithSettings;
const getDefaultLoggingSettings = logging.getDefaultLoggingSettings;
const configureDefaultLogging = logging.configureDefaultLogging;
const configureLogging = logging.configureLogging;
// Log level constants
const ERROR = logging.ERROR;
const WARN = logging.WARN;
const INFO = logging.INFO;
const DEBUG = logging.DEBUG;
const TRACE = logging.TRACE;
// Convenience logging function
const log = logging.log;
```
2. Provide a context object on which to configure logging, e.g:
```js
const context = { a: 1, b: 2, c: 3 }; // replace with your own target object to be configured
const context = {}; // replace with your own target object to be configured
```
3. Configure logging on the context object
* To configure default logging on an existing object:
* To configure default logging on an existing object (WITHOUT overriding any existing logging on context)
```js
configureDefaultLogging(context);
configureLogging(context);
// which is equivalent to:
configureLogging(context, {logLevel: LogLevel.INFO});
```
* To configure WARN level logging on an existing object
* To configure WARN level logging on an existing object (WITHOUT overriding any existing logging on context)
```js
configureLoggingWithSettings(context, {logLevel: WARN});
configureLogging(context, {logLevel: LogLevel.WARN});
```
* To configure specific logging (WITHOUT overriding any existing logging on context)
```js
const settings = {logLevel: DEBUG, useLevelPrefixes: false, useConsoleTrace: false, underlyingLogger: console};
configureLoggingWithSettings(context, settings, false);
const settings = {logLevel: LogLevel.DEBUG, useLevelPrefixes: false, useConsoleTrace: false, underlyingLogger: console}; // or your own settings
configureLogging(context, settings);
// OR with explicit forceConfiguration false
configureLogging(context, settings, undefined, false);
```
* To configure specific logging (OVERRIDING any existing logging on context!)
```js
configureLoggingWithSettings(context, settings, true);
configureLogging(context, settings, undefined, true);
```
* To configure simple default logging on a new object
* To configure default logging on a new object
```js
const log = configureDefaultLogging({});
const log = configureLogging({});
```
* To configure default logging on an existing object with overriding options and forceConfiguration true
```js
configureLogging(context, undefined, options, true);
// Alternatively ...
configureLogging(context, options, undefined, true);
```
* To configure default logging on an existing object with overriding options, an explicit logger and forceConfiguration true
```js
const options = undefined; // ... or any LoggingOptions you want to use to partially or fully override the default logging settings
configureDefaultLogging(context, options, console, true);
// Alternatives specifying only underlying logger or forceConfiguration
configureDefaultLogging(context, options, console);
configureDefaultLogging(context, options, undefined, true);
configureLogging(context, {underlyingLogger: console}, options);
const CustomLogger = {/* ... */}; // implement your own custom logger if required
configureLogging(context, {underlyingLogger: CustomLogger}, options, true);
```
* To configure logging from a config object (or file) with logging options under config.loggingOptions
* To configure logging from options
```js
const options = { loggingOptions: { logLevel: DEBUG, useLevelPrefixes: true, useConsoleTrace: false } }; // replace with your own config object
const loggingSettings = getDefaultLoggingSettings(options.loggingOptions);
configureLoggingWithSettings(context, loggingSettings);
// or as an alternative to the above 2 lines, just use the following:
configureDefaultLogging(context, config.loggingOptions);
// Alternatives specifying only optional underlying logger or forceConfiguration
configureLoggingWithSettings(context, loggingSettings, console);
configureLoggingWithSettings(context, loggingSettings, undefined, true);
const options = { logLevel: LogLevel.DEBUG, useLevelPrefixes: true, useConsoleTrace: false }; // replace with your own options
configureLogging(context, undefined, options);
// OR just ...
configureLogging(context, options);
```
* To configure logging from logging options
```js
const options = { logLevel: DEBUG, useLevelPrefixes: true, useConsoleTrace: false }; // replace with your own config object
const loggingSettings = getDefaultLoggingSettings(options);
configureLoggingWithSettings(context, loggingSettings);
// or as an alternative to the above 2 lines, just use the following:
configureDefaultLogging(context, options);
```
* To configure logging from EITHER logging settings OR logging options (OR defaults if neither) - WITHOUT overriding any existing logging on context
```js
configureLogging(context, loggingSettings, loggingOptions, underlyingLogger, false);
configureLogging(context, settings, options);
// OR with explicit forceConfiguration false ...
configureLogging(context, settings, options, false);
```

@@ -114,5 +106,18 @@

```js
configureLogging(context, loggingSettings, loggingOptions, underlyingLogger, true);
configureLogging(context, settings, options, true);
```
* To **OVERRIDE** any pre-configured `logLevel` setting or option during runtime configuration, set a logging level on
the environment variable named by the `envLogLevelName` setting, which is also configurable and defaults to `'LOG_LEVEL'`.
Any valid `logLevel` found with `process.env[envLogLevelName]` will take precedence over any other `logLevel` setting or option.
```js
// For unit testing, set the `LOG_LEVEL` environment variable programmatically
process.env.LOG_LEVEL = LogLevel.DEBUG;
// Alternatively, if you configured your own `envLogLevelName` as 'MyLogLevel', e.g.
configureLogging(context, {envLogLevelName: 'MyLogLevel'});
// then for unit testing, set your `MyLogLevel` environment variable programmatically
process.env.MyLogLevel = LogLevel.TRACE;
```
### 2. Log messages

@@ -161,2 +166,21 @@

* To log messages at a specified log level (using the `log` method):
```js
// To log a message at LogLevel.TRACE (or do nothing when trace messages are disabled)
context.log(LogLevel.ERROR, 'Error message 1', new Error('Boom').stack);
// Note that this will also work with console, but you won't get any suppression according to log level
console.log(LogLevel.TRACE, 'Trace message 1');
```
* To log messages at a specified log level (using the `log` function):
```js
// Alternatively using log function
log(context, LogLevel.DEBUG, 'Debug message 1');
// Note that this will also work with console (and undefined), but you won't get any suppression according to log level
log(console, LogLevel.WARN, 'Warn message 1');
log(undefined, LogLevel.ERROR, 'Error message 1', new Error('Boom 2').stack);
```
## Unit tests

@@ -169,2 +193,20 @@ This module's unit tests were developed with and must be run with [tape](https://www.npmjs.com/package/tape). The unit tests have been tested on [Node.js v4.3.2](https://nodejs.org/en/blog/release/v4.3.2/).

### 4.0.0
- Major changes to and simplification of `logging.js` API (NOT BACKWARD COMPATIBLE!):
- Removed `underlyingLogger` parameter from `configureLogging` function, which was ignored when `settings` were
provided and was also redundant, since it can be set via the `settings` parameter
- Removed redundant `configureLoggingWithSettings`, `configureDefaultLogging` and `getDefaultLoggingSettings` functions
- Replaced `ERROR`, `WARN`, `INFO`, `DEBUG` and `TRACE` constants with properties in new `LogLevel` constant to
simplify import & usage and changed their values to uppercase for consistency
- Removed `toValidLogLevelOrDefault` function
- Renamed `Logging` typedef to `Logger`
- Added additional `log` method to the target object during `configureLogging` to enable logging at a specified level
- Added `log` function, which delegates to new `log` method to enable logging at a specified level
- Exported `isValidLogLevel` and new `cleanLogLevel` functions
- Added an `envLogLevelName` setting to enable configuration of the name of the environment variable in which to look
for a logLevel on `process.env` (defaults to 'LOG_LEVEL' if undefined)
- Enabled overriding of configured logLevel via `process.env[envLogLevelName]`, where `envLogLevelName` refers to the
configured name of the environment variable in which to look for a logLevel on `process.env`
- Updated `core-functions` dependency to version 3.0.0
### 3.0.12

@@ -171,0 +213,0 @@ - Updated `core-functions` dependency to version 2.0.14

@@ -12,14 +12,11 @@ 'use strict';

const logging = require('../logging.js');
// Logging utils Constants
const ERROR = logging.ERROR;
const WARN = logging.WARN;
const INFO = logging.INFO;
const DEBUG = logging.DEBUG;
const TRACE = logging.TRACE;
// Valid logging levels
const LogLevel = logging.LogLevel;
// Logging utils functions
const isLoggingConfigured = logging.isLoggingConfigured;
const configureLoggingWithSettings = logging.configureLoggingWithSettings;
const configureDefaultLogging = logging.configureDefaultLogging;
const getDefaultLoggingSettings = logging.getDefaultLoggingSettings;
const configureLogging = logging.configureLogging;
const getDefaultLoggingOptions = logging.getDefaultLoggingOptions;
const log = logging.log;
const isMinimumViableLogger = logging.isMinimumViableLogger;

@@ -29,7 +26,15 @@ const booleans = require('core-functions/booleans');

const defaultSettings = logging.getDefaultLoggingSettings();
const strings = require('core-functions/strings');
const isNotBlank = strings.isNotBlank;
function testLogger(logLevel, useConsole, t) {
const defaultOptions = getDefaultLoggingOptions();
let loggerCount = 0;
function testLogger(logLevel, useConsole, testPrefix, t) {
++loggerCount;
const prefix = isNotBlank(testPrefix) ? `${testPrefix}${loggerCount}` : '';
function error() {
//console.log(`IN error() with level (${logLevel.toUpperCase()})`);
if (prefix && arguments.length > 0) arguments[0] = `${prefix} ${arguments[0]}`;
console.error.apply(console, arguments);

@@ -40,4 +45,5 @@ }

//console.log(`IN warn() with level (${logLevel.toUpperCase()})`);
if (prefix && arguments.length > 0) arguments[0] = `${prefix} ${arguments[0]}`;
console.warn.apply(console, arguments);
if (logLevel === ERROR) t.fail('warn not enabled');
if (logLevel === LogLevel.ERROR) t.fail('warn not enabled');
}

@@ -47,4 +53,5 @@

//console.log(`IN info() with level (${logLevel.toUpperCase()})`);
console.log.apply(console, arguments);
if (logLevel === ERROR || logLevel === WARN) t.fail('info not enabled');
if (prefix && arguments.length > 0) arguments[0] = `${prefix} ${arguments[0]}`;
console.info.apply(console, arguments);
if (logLevel === LogLevel.ERROR || logLevel === LogLevel.WARN) t.fail('info not enabled');
}

@@ -54,4 +61,5 @@

//console.log(`IN debug() with level (${logLevel.toUpperCase()})`);
console.log.apply(console, arguments);
if (logLevel !== DEBUG && logLevel !== TRACE) t.fail('debug not enabled');
if (prefix && arguments.length > 0) arguments[0] = `${prefix} ${arguments[0]}`;
console.info.apply(console, arguments);
if (logLevel !== LogLevel.DEBUG && logLevel !== LogLevel.TRACE) t.fail('debug not enabled');
}

@@ -61,13 +69,22 @@

//console.log(`IN trace() with level (${logLevel.toUpperCase()})`);
if (prefix && arguments.length > 0) arguments[0] = `${prefix} ${arguments[0]}`;
console.info.apply(console, arguments);
if (logLevel !== LogLevel.TRACE) t.fail('trace not enabled');
}
function log() {
//console.log(`IN info() with level (${logLevel.toUpperCase()})`);
if (prefix && arguments.length > 0) arguments[0] = `${prefix} ${arguments[0]}`;
console.log.apply(console, arguments);
if (logLevel !== TRACE) t.fail('trace not enabled');
if (logLevel === LogLevel.ERROR || logLevel === LogLevel.WARN) t.fail('info not enabled');
}
return useConsole ? console : {
error: error,
warn: warn,
info: info,
debug: debug,
trace: trace
};
error: error,
warn: warn,
info: info,
debug: debug,
trace: trace,
log: log
};
}

@@ -77,20 +94,41 @@

function logOneOfEach(log, logLevel) {
log.error(`*** Error message ${counter} (at level ${logLevel.toUpperCase()})`, '***'); //, new Error('Boom').stack);
log.warn(`*** Warn message ${counter} (at level ${logLevel.toUpperCase()})`, '***');
log.info(`*** Info message ${counter} (at level ${logLevel.toUpperCase()})`, '***');
log.debug(`*** Debug message ${counter} (at level ${logLevel.toUpperCase()})`, '***');
log.trace(`*** Trace message ${counter} (at level ${logLevel.toUpperCase()})`, '***');
function logOneOfEach(logger, logLevel) {
logger.error(`*** Error message ${counter} (at level ${logLevel})`, '***'); //, new Error('Boom').stack);
logger.warn(`*** Warn message ${counter} (at level ${logLevel})`, '***');
logger.info(`*** Info message ${counter} (at level ${logLevel})`, '***');
logger.debug(`*** Debug message ${counter} (at level ${logLevel})`, '***');
logger.trace(`*** Trace message ${counter} (at level ${logLevel})`, '***');
logOneOfEachUsingLogMethod(logger, logLevel);
//++counter;
}
function logOneOfEachUsingLogMethod(logger, logLevel) {
logger.log(LogLevel.ERROR, `*** Log ERROR message ${counter} (at level ${logLevel})`, '***');
logger.log(LogLevel.WARN, `*** Log WARN message ${counter} (at level ${logLevel})`, '***');
logger.log(LogLevel.INFO, `*** Log INFO message ${counter} (at level ${logLevel})`, '***');
logger.log(LogLevel.DEBUG, `*** Log DEBUG message ${counter} (at level ${logLevel})`, '***');
logger.log(LogLevel.TRACE, `*** Log TRACE message ${counter} (at level ${logLevel})`, '***');
logger.log('<<< %s %s >>>', `*** Log "<<< %s %s >>>" message ${counter} (at level ${logLevel})`, '***');
++counter;
}
function logOneOfEachUsingLogFunction(logger, logLevel, loggerDesc) {
log(logger, LogLevel.ERROR, `*** log(${loggerDesc}, ERROR) message ${counter} (at level ${logLevel})`, '***');
log(logger, LogLevel.WARN, `*** log(${loggerDesc}, WARN) message ${counter} (at level ${logLevel})`, '***');
log(logger, LogLevel.INFO, `*** log(${loggerDesc}, INFO) message ${counter} (at level ${logLevel})`, '***');
log(logger, LogLevel.DEBUG, `*** log(${loggerDesc}, DEBUG) message ${counter} (at level ${logLevel})`, '***');
log(logger, LogLevel.TRACE, `*** log(${loggerDesc}, TRACE) message ${counter} (at level ${logLevel})`, '***');
log(logger, '<<< %s %s >>>', `*** log(${loggerDesc}, "<<< %s %s >>>") message ${counter} (at level ${logLevel})`, '***');
++counter;
}
function checkEnabledsBasedOnLogLevel(t, context, logLevel) {
switch (logLevel) {
case ERROR:
case LogLevel.ERROR:
t.notOk(context.warnEnabled, 'warn must not be enabled'); // fallthrough
case WARN:
case LogLevel.WARN:
t.notOk(context.infoEnabled, 'info must not be enabled'); // fallthrough
case INFO:
case LogLevel.INFO:
t.notOk(context.debugEnabled, 'debug must not be enabled'); // fallthrough
case DEBUG:
case LogLevel.DEBUG:
t.notOk(context.traceEnabled, 'trace must not be enabled');

@@ -100,9 +138,9 @@ break;

switch (logLevel) {
case TRACE:
case LogLevel.TRACE:
t.ok(context.traceEnabled, 'trace must be enabled'); // fallthrough
case DEBUG:
case LogLevel.DEBUG:
t.ok(context.debugEnabled, 'debug must be enabled'); // fallthrough
case INFO:
case LogLevel.INFO:
t.ok(context.infoEnabled, 'info must be enabled'); // fallthrough
case WARN:
case LogLevel.WARN:
t.ok(context.warnEnabled, 'warn must be enabled');

@@ -121,3 +159,3 @@ break;

const settings = {
logLevel: ERROR,
logLevel: LogLevel.ERROR,
useLevelPrefixes: true,

@@ -127,3 +165,3 @@ useConsoleTrace: false,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);

@@ -135,11 +173,11 @@ t.equal(isLoggingConfigured(log), true, 'logging must be configured');

// =====================================================================================================================
// Test configureLoggingWithSettings on existing object with test logger to validate methods
// Test configureLogging on existing object with test logger to validate methods
// =====================================================================================================================
test('configureLoggingWithSettings on existing object with TRACE level with test logger & prefixes', t => {
const logLevel = TRACE;
test('configureLogging on existing object with TRACE level with test logger & prefixes', t => {
const logLevel = LogLevel.TRACE;
const useLevelPrefixes = true;
const useConsole = false;
const logger = testLogger(logLevel, useConsole, t);
const logger = testLogger(logLevel, useConsole, '', t);

@@ -153,6 +191,6 @@ const context = {abc: 123};

};
configureLoggingWithSettings(context, settings, false);
configureLogging(context, settings, undefined, false);
t.equal(context.abc, 123, 'context must still be intact');
checkEnabledsBasedOnLogLevel(t, context, TRACE);
checkEnabledsBasedOnLogLevel(t, context, LogLevel.TRACE);

@@ -164,8 +202,8 @@ logOneOfEach(context, logLevel);

test('configureLoggingWithSettings on existing object with DEBUG level with test logger & prefixes', t => {
const logLevel = DEBUG;
test('configureLogging on existing object with DEBUG level with test logger & prefixes', t => {
const logLevel = LogLevel.DEBUG;
const useLevelPrefixes = true;
const useConsole = false;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useLevelPrefixes, '', t);

@@ -179,6 +217,6 @@ const context = {abc: 123};

};
configureLoggingWithSettings(context, settings, false);
configureLogging(context, settings, undefined, false);
t.equal(context.abc, 123, 'context must still be intact');
checkEnabledsBasedOnLogLevel(t, context, DEBUG);
checkEnabledsBasedOnLogLevel(t, context, LogLevel.DEBUG);

@@ -190,8 +228,8 @@ logOneOfEach(context, logLevel);

test('configureLoggingWithSettings on existing object with INFO level with test logger & prefixes', t => {
const logLevel = INFO;
test('configureLogging on existing object with INFO level with test logger & prefixes', t => {
const logLevel = LogLevel.INFO;
const useLevelPrefixes = true;
const useConsole = false;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useLevelPrefixes, '', t);

@@ -205,6 +243,6 @@ const context = {abc: 123};

};
configureLoggingWithSettings(context, settings, false);
configureLogging(context, settings, undefined, false);
t.equal(context.abc, 123, 'context must still be intact');
checkEnabledsBasedOnLogLevel(t, context, INFO);
checkEnabledsBasedOnLogLevel(t, context, LogLevel.INFO);

@@ -216,8 +254,8 @@ logOneOfEach(context, logLevel);

test('configureLoggingWithSettings on existing object with WARN level with test logger & prefixes', t => {
const logLevel = WARN;
test('configureLogging on existing object with WARN level with test logger & prefixes', t => {
const logLevel = LogLevel.WARN;
const useLevelPrefixes = true;
const useConsole = false;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useLevelPrefixes, '', t);

@@ -231,6 +269,6 @@ const context = {abc: 123};

};
configureLoggingWithSettings(context, settings, false);
configureLogging(context, settings, undefined, false);
t.equal(context.abc, 123, 'context must still be intact');
checkEnabledsBasedOnLogLevel(t, context, WARN);
checkEnabledsBasedOnLogLevel(t, context, LogLevel.WARN);

@@ -242,8 +280,8 @@ logOneOfEach(context, logLevel);

test('configureLoggingWithSettings on existing object with ERROR level with test logger & prefixes', t => {
const logLevel = ERROR;
test('configureLogging on existing object with ERROR level with test logger & prefixes', t => {
const logLevel = LogLevel.ERROR;
const useLevelPrefixes = true;
const useConsole = false;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useLevelPrefixes, '', t);

@@ -257,6 +295,6 @@ const context = {abc: 123};

};
configureLoggingWithSettings(context, settings, false);
configureLogging(context, settings, undefined, false);
t.equal(context.abc, 123, 'context must still be intact');
checkEnabledsBasedOnLogLevel(t, context, ERROR);
checkEnabledsBasedOnLogLevel(t, context, LogLevel.ERROR);

@@ -269,11 +307,11 @@ logOneOfEach(context, logLevel);

// =====================================================================================================================
// Test configureLoggingWithSettings on new object with test logger to validate methods
// Test configureLogging on new object with test logger to validate methods
// =====================================================================================================================
test('configureLoggingWithSettings on new object with TRACE level with test logger & prefixes', t => {
const logLevel = TRACE;
test('configureLogging on new object with TRACE level with test logger & prefixes', t => {
const logLevel = LogLevel.TRACE;
const useLevelPrefixes = false;
const useConsole = false;
const logger = testLogger(logLevel, useConsole, t);
const logger = testLogger(logLevel, useConsole, '', t);
const settings = {

@@ -285,5 +323,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, TRACE);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.TRACE);

@@ -295,8 +333,8 @@ logOneOfEach(log, logLevel);

test('configureLoggingWithSettings on new object with DEBUG level with test logger & prefixes', t => {
const logLevel = DEBUG;
test('configureLogging on new object with DEBUG level with test logger & prefixes', t => {
const logLevel = LogLevel.DEBUG;
const useLevelPrefixes = true;
const useConsole = false;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useLevelPrefixes, '', t);
const settings = {

@@ -308,5 +346,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, DEBUG);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.DEBUG);

@@ -318,8 +356,8 @@ logOneOfEach(log, logLevel);

test('configureLoggingWithSettings on new object with INFO level with test logger & prefixes', t => {
const logLevel = INFO;
test('configureLogging on new object with INFO level with test logger & prefixes', t => {
const logLevel = LogLevel.INFO;
const useLevelPrefixes = true;
const useConsole = false;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useLevelPrefixes, '', t);
const settings = {

@@ -331,5 +369,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, INFO);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.INFO);

@@ -341,8 +379,8 @@ logOneOfEach(log, logLevel);

test('configureLoggingWithSettings on new object with WARN level with test logger & prefixes', t => {
const logLevel = WARN;
test('configureLogging on new object with WARN level with test logger & prefixes', t => {
const logLevel = LogLevel.WARN;
const useLevelPrefixes = true;
const useConsole = false;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useLevelPrefixes, '', t);
const settings = {

@@ -354,5 +392,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, WARN);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.WARN);

@@ -364,8 +402,8 @@ logOneOfEach(log, logLevel);

test('configureLoggingWithSettings on new object with ERROR level with test logger & prefixes', t => {
const logLevel = ERROR;
test('configureLogging on new object with ERROR level with test logger & prefixes', t => {
const logLevel = LogLevel.ERROR;
const useLevelPrefixes = true;
const useConsole = false;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useLevelPrefixes, '', t);
const settings = {

@@ -377,5 +415,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, ERROR);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.ERROR);

@@ -388,12 +426,12 @@ logOneOfEach(log, logLevel);

// =====================================================================================================================
// Test configureLoggingWithSettings on new object with console (i.e. test real usage for Lambdas) and useLevelPrefixes true
// Test configureLogging on new object with console (i.e. test real usage for Lambdas) and useLevelPrefixes true
// =====================================================================================================================
const useConsoleTrace = false;
test('configureLoggingWithSettings on new object with TRACE level with console & prefixes', t => {
const logLevel = TRACE;
test('configureLogging on new object with TRACE level with console & prefixes', t => {
const logLevel = LogLevel.TRACE;
const useLevelPrefixes = true;
const useConsole = true;
const logger = testLogger(logLevel, useConsole, t);
const logger = testLogger(logLevel, useConsole, '', t);
const settings = {

@@ -405,5 +443,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, TRACE);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.TRACE);

@@ -415,8 +453,8 @@ logOneOfEach(log, logLevel);

test('configureLoggingWithSettings on new object with DEBUG level with console & prefixes', t => {
const logLevel = DEBUG;
test('configureLogging on new object with DEBUG level with console & prefixes', t => {
const logLevel = LogLevel.DEBUG;
const useLevelPrefixes = true;
const useConsole = true;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useConsole, '', t);
const settings = {

@@ -428,5 +466,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, DEBUG);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.DEBUG);

@@ -438,8 +476,8 @@ logOneOfEach(log, logLevel);

test('configureLoggingWithSettings on new object with INFO level with console & prefixes', t => {
const logLevel = INFO;
test('configureLogging on new object with INFO level with console & prefixes', t => {
const logLevel = LogLevel.INFO;
const useLevelPrefixes = true;
const useConsole = true;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useConsole, '', t);
const settings = {

@@ -451,5 +489,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, INFO);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.INFO);

@@ -461,8 +499,8 @@ logOneOfEach(log, logLevel);

test('configureLoggingWithSettings on new object with WARN level with console & prefixes', t => {
const logLevel = WARN;
test('configureLogging on new object with WARN level with console & prefixes', t => {
const logLevel = LogLevel.WARN;
const useLevelPrefixes = true;
const useConsole = true;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useConsole, '', t);
const settings = {

@@ -474,5 +512,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, WARN);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.WARN);

@@ -484,8 +522,8 @@ logOneOfEach(log, logLevel);

test('configureLoggingWithSettings on new object with ERROR level with console & prefixes', t => {
const logLevel = ERROR;
test('configureLogging on new object with ERROR level with console & prefixes', t => {
const logLevel = LogLevel.ERROR;
const useLevelPrefixes = true;
const useConsole = true;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useConsole, '', t);
const settings = {

@@ -497,5 +535,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, ERROR);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.ERROR);

@@ -509,11 +547,11 @@ logOneOfEach(log, logLevel);

// =====================================================================================================================
// Test configureLoggingWithSettings on new object with console (i.e. test real usage for Lambdas) and useLevelPrefixes false
// Test configureLogging on new object with console (i.e. test real usage for Lambdas) and useLevelPrefixes false
// =====================================================================================================================
test('configureLoggingWithSettings on new object with TRACE level with console & no prefixes', t => {
const logLevel = TRACE;
test('configureLogging on new object with TRACE level with console & no prefixes', t => {
const logLevel = LogLevel.TRACE;
const useLevelPrefixes = false;
const useConsole = true;
const logger = testLogger(logLevel, useConsole, t);
const logger = testLogger(logLevel, useConsole, '', t);
const settings = {

@@ -525,5 +563,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, TRACE);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.TRACE);

@@ -535,8 +573,8 @@ logOneOfEach(log, logLevel);

test('configureLoggingWithSettings on new object with DEBUG level with console & no prefixes', t => {
const logLevel = DEBUG;
test('configureLogging on new object with DEBUG level with console & no prefixes', t => {
const logLevel = LogLevel.DEBUG;
const useLevelPrefixes = false;
const useConsole = true;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useConsole, '', t);
const settings = {

@@ -548,5 +586,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, DEBUG);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.DEBUG);

@@ -558,8 +596,8 @@ logOneOfEach(log, logLevel);

test('configureLoggingWithSettings on new object with INFO level with console & no prefixes', t => {
const logLevel = INFO;
test('configureLogging on new object with INFO level with console & no prefixes', t => {
const logLevel = LogLevel.INFO;
const useLevelPrefixes = false;
const useConsole = true;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useConsole, '', t);
const settings = {

@@ -571,5 +609,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, INFO);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.INFO);

@@ -581,8 +619,8 @@ logOneOfEach(log, logLevel);

test('configureLoggingWithSettings on new object with WARN level with console & no prefixes', t => {
const logLevel = WARN;
test('configureLogging on new object with WARN level with console & no prefixes', t => {
const logLevel = LogLevel.WARN;
const useLevelPrefixes = false;
const useConsole = true;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useConsole, '', t);
const settings = {

@@ -594,5 +632,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, WARN);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.WARN);

@@ -604,8 +642,8 @@ logOneOfEach(log, logLevel);

test('configureLoggingWithSettings on new object with ERROR level with console & no prefixes', t => {
const logLevel = ERROR;
test('configureLogging on new object with ERROR level with console & no prefixes', t => {
const logLevel = LogLevel.ERROR;
const useLevelPrefixes = false;
const useConsole = true;
const logger = testLogger(logLevel, useLevelPrefixes, useConsole, t);
const logger = testLogger(logLevel, useConsole, '', t);
const settings = {

@@ -617,5 +655,5 @@ logLevel: logLevel,

};
const log = configureLoggingWithSettings({}, settings, true);
const log = configureLogging({}, settings, undefined, true);
checkEnabledsBasedOnLogLevel(t, log, ERROR);
checkEnabledsBasedOnLogLevel(t, log, LogLevel.ERROR);

@@ -628,6 +666,6 @@ logOneOfEach(log, logLevel);

// =====================================================================================================================
// Ensure that configureLoggingWithSettings on existing object does NOT override previously configured logging if not forced
// Ensure that configureLogging on existing object does NOT override previously configured logging if not forced
// =====================================================================================================================
test('configureLoggingWithSettings on existing object MUST NOT override previously configured logging if not forced', t => {
test('configureLogging on existing object MUST NOT override previously configured logging if not forced', t => {
const useLevelPrefixes = true;

@@ -637,25 +675,25 @@ const useConsole = false;

const settings = {
logLevel: TRACE,
logLevel: LogLevel.TRACE,
useLevelPrefixes: useLevelPrefixes,
useConsoleTrace: useConsoleTrace,
underlyingLogger: testLogger(TRACE, useConsole, t)
underlyingLogger: testLogger(LogLevel.TRACE, useConsole, '', t)
};
const context = configureLoggingWithSettings({}, settings, true);
const context = configureLogging({}, settings, undefined, true);
context.abc = 123;
t.equal(context.logLevel, TRACE, 'logLevel must be TRACE');
checkEnabledsBasedOnLogLevel(t, context, TRACE);
t.equal(context.logLevel, LogLevel.TRACE, 'logLevel must be LogLevel.TRACE');
checkEnabledsBasedOnLogLevel(t, context, LogLevel.TRACE);
// Now attempt to override
const overrideSettings = {
logLevel: ERROR,
logLevel: LogLevel.ERROR,
useLevelPrefixes: useLevelPrefixes,
useConsoleTrace: useConsole,
underlyingLogger: testLogger(ERROR, useConsole, t)
underlyingLogger: testLogger(LogLevel.ERROR, useConsole, '', t)
};
configureLoggingWithSettings(context, overrideSettings, false);
configureLogging(context, overrideSettings, undefined, false);
t.equal(context.abc, 123, 'context must still be intact');
t.equal(context.logLevel, TRACE, 'logLevel must still be TRACE');
checkEnabledsBasedOnLogLevel(t, context, TRACE);
t.equal(context.logLevel, LogLevel.TRACE, 'logLevel must still be LogLevel.TRACE');
checkEnabledsBasedOnLogLevel(t, context, LogLevel.TRACE);

@@ -668,6 +706,6 @@ logOneOfEach(context, context.logLevel);

// =====================================================================================================================
// Ensure that configureLoggingWithSettings on existing object does override previously configured logging if forced
// Ensure that configureLogging on existing object does override previously configured logging if forced
// =====================================================================================================================
test('configureLoggingWithSettings on existing object MUST override previously configured logging if forced', t => {
test('configureLogging on existing object MUST override previously configured logging if forced', t => {
const useLevelPrefixes = true;

@@ -678,25 +716,25 @@ const useConsole = false;

const settings = {
logLevel: TRACE,
logLevel: LogLevel.TRACE,
useLevelPrefixes: useLevelPrefixes,
useConsoleTrace: useConsoleTrace,
underlyingLogger: testLogger(TRACE, useConsole, t)
underlyingLogger: testLogger(LogLevel.TRACE, useConsole, '', t)
};
const context = configureLoggingWithSettings({}, settings, true);
const context = configureLogging({}, settings, undefined, true);
context.abc = 123;
t.equal(context.logLevel, TRACE, 'logLevel must be TRACE');
checkEnabledsBasedOnLogLevel(t, context, TRACE);
t.equal(context.logLevel, LogLevel.TRACE, 'logLevel must be LogLevel.TRACE');
checkEnabledsBasedOnLogLevel(t, context, LogLevel.TRACE);
// Now attempt to override with ERROR level logging (by using forceConfiguration option)
const overrideSettings = {
logLevel: ERROR,
logLevel: LogLevel.ERROR,
useLevelPrefixes: useLevelPrefixes,
useConsoleTrace: useConsole,
underlyingLogger: testLogger(ERROR, useConsole, t)
underlyingLogger: testLogger(LogLevel.ERROR, useConsole, '', t)
};
configureLoggingWithSettings(context, overrideSettings, true);
configureLogging(context, overrideSettings, undefined, true);
t.equal(context.abc, 123, 'context must still be intact');
t.equal(context.logLevel, ERROR, 'logLevel must now be ERROR');
checkEnabledsBasedOnLogLevel(t, context, ERROR);
t.equal(context.logLevel, LogLevel.ERROR, 'logLevel must now be LogLevel.ERROR');
checkEnabledsBasedOnLogLevel(t, context, LogLevel.ERROR);

@@ -709,13 +747,13 @@ logOneOfEach(context, context.logLevel);

// =====================================================================================================================
// Test configureDefaultLogging without options on existing object with test logger to validate methods
// Test configureLogging without options on existing object with test logger to validate methods
// =====================================================================================================================
test('configureDefaultLogging without options on existing object with test logger & defaults', t => {
const options = undefined;
const logLevel = defaultSettings.logLevel;
const logger = testLogger(logLevel, false, t);
test('configureLogging without options on existing object with test logger & defaults', t => {
const logLevel = defaultOptions.logLevel;
const logger = testLogger(logLevel, false, '', t);
// Configure default logging when no logging configured yet (without force)
const context = {abc: 123};
configureDefaultLogging(context, options, logger, false);
const onlyLogger = {underlyingLogger: logger};
configureLogging(context, onlyLogger, undefined, false);

@@ -727,13 +765,13 @@ t.equal(context.abc, 123, 'context must still be intact');

// Now override with something else entirely using force (to change away from previous config settings)
const overrideLogLevel = logLevel !== ERROR ? ERROR : TRACE;
const overrideLogLevel = logLevel !== LogLevel.ERROR ? LogLevel.ERROR : LogLevel.TRACE;
const overrideSettings = {
logLevel: overrideLogLevel,
useLevelPrefixes: !defaultSettings.useLevelPrefixes,
useConsoleTrace: !defaultSettings.useConsoleTrace,
underlyingLogger: testLogger(overrideLogLevel, false, t)
useLevelPrefixes: !defaultOptions.useLevelPrefixes,
useConsoleTrace: !defaultOptions.useConsoleTrace,
underlyingLogger: testLogger(overrideLogLevel, false, '', t)
};
configureLoggingWithSettings(context, overrideSettings, true);
configureLogging(context, overrideSettings, undefined, true);
// Now do NOT override with default logging configuration when NOT using force
configureDefaultLogging(context, options, logger, false);
configureLogging(context, onlyLogger, undefined, false);

@@ -744,3 +782,3 @@ checkEnabledsBasedOnLogLevel(t, context, overrideLogLevel);

// Now override with default logging configuration using force
configureDefaultLogging(context, options, logger, true);
configureLogging(context, onlyLogger, undefined, true);

@@ -755,15 +793,16 @@ t.equal(context.abc, 123, 'context must still be intact');

// =====================================================================================================================
// Test configureDefaultLogging with overridden options on existing object with test logger to validate methods
// Test configureLogging with overridden options on existing object with test logger to validate methods
// =====================================================================================================================
test('configureDefaultLogging with overridden options on existing object with test logger & defaults', t => {
const logLevel = defaultSettings.logLevel !== TRACE ? TRACE : ERROR;
test('configureLogging with overridden options on existing object with test logger & defaults', t => {
const logLevel = defaultOptions.logLevel !== LogLevel.TRACE ? LogLevel.TRACE : LogLevel.ERROR;
const options = {logLevel: logLevel};
t.notEqual(options.logLevel, defaultSettings.logLevel, `options logLevel (${options.logLevel}) must differ from default (${defaultSettings.logLevel})`);
t.notEqual(options.logLevel, defaultOptions.logLevel, `options logLevel (${options.logLevel}) must differ from default (${defaultOptions.logLevel})`);
const logger = testLogger(logLevel, false, t);
const logger = testLogger(logLevel, false, '', t);
// Configure default logging when no logging configured yet (without force)
const context = {abc: 123};
configureDefaultLogging(context, options, logger, false);
const onlyLogger = {underlyingLogger: logger};
configureLogging(context, onlyLogger, options, false);

@@ -775,13 +814,13 @@ t.equal(context.abc, 123, 'context must still be intact');

// Now override with something else entirely using force (to change away from previous config settings)
const overrideLogLevel = logLevel !== ERROR ? ERROR : TRACE;
const overrideLogLevel = logLevel !== LogLevel.ERROR ? LogLevel.ERROR : LogLevel.TRACE;
const overrideSettings = {
logLevel: overrideLogLevel,
useLevelPrefixes: !defaultSettings.useLevelPrefixes,
useConsoleTrace: !defaultSettings.useConsoleTrace,
underlyingLogger: testLogger(overrideLogLevel, false, t)
useLevelPrefixes: !defaultOptions.useLevelPrefixes,
useConsoleTrace: !defaultOptions.useConsoleTrace,
underlyingLogger: testLogger(overrideLogLevel, false, '', t)
};
configureLoggingWithSettings(context, overrideSettings, true);
configureLogging(context, overrideSettings, undefined, true);
// Now do NOT override with default logging configuration when NOT using force
configureDefaultLogging(context, options, logger, false);
configureLogging(context, onlyLogger, options, false);

@@ -792,3 +831,3 @@ checkEnabledsBasedOnLogLevel(t, context, overrideLogLevel);

// Now override with default logging configuration using force
configureDefaultLogging(context, options, logger, true);
configureLogging(context, onlyLogger, options, true);

@@ -803,8 +842,8 @@ t.equal(context.abc, 123, 'context must still be intact');

// =====================================================================================================================
// Test configureLoggingWithSettings on existing object with test logger to validate methods
// Test configureLogging on existing object with test logger to validate methods
// =====================================================================================================================
test('configureLoggingWithSettings on existing object with test logger & config.logLevel etc.', t => {
const logLevel = defaultSettings.logLevel !== TRACE ? TRACE : ERROR;
const logger = testLogger(logLevel, false, t);
test('configureLogging on existing object with test logger & config.logLevel etc.', t => {
const logLevel = defaultOptions.logLevel !== LogLevel.TRACE ? LogLevel.TRACE : LogLevel.ERROR;
const logger = testLogger(logLevel, false, '', t);

@@ -815,7 +854,7 @@ // Configure logging from config when no logging configured yet (without force)

logLevel: logLevel,
useLevelPrefixes: !defaultSettings.useLevelPrefixes,
useConsoleTrace: !defaultSettings.useConsoleTrace,
useLevelPrefixes: !defaultOptions.useLevelPrefixes,
useConsoleTrace: !defaultOptions.useConsoleTrace,
underlyingLogger: logger
};
configureLoggingWithSettings(context, settings, false);
configureLogging(context, settings, undefined, false);

@@ -827,13 +866,13 @@ t.equal(context.abc, 123, 'context must still be intact');

// Now override with something else entirely using force (to change away from previous config settings)
const overrideLogLevel = logLevel !== ERROR ? ERROR : TRACE;
const overrideLogLevel = logLevel !== LogLevel.ERROR ? LogLevel.ERROR : LogLevel.TRACE;
const overrideSettings = {
logLevel: overrideLogLevel,
useLevelPrefixes: defaultSettings.useLevelPrefixes,
useConsoleTrace: defaultSettings.useConsoleTrace,
underlyingLogger: testLogger(overrideLogLevel, false, t)
useLevelPrefixes: defaultOptions.useLevelPrefixes,
useConsoleTrace: defaultOptions.useConsoleTrace,
underlyingLogger: testLogger(overrideLogLevel, false, '', t)
};
configureLoggingWithSettings(context, overrideSettings, true);
configureLogging(context, overrideSettings, undefined, true);
// Now do NOT override with logging configuration again when NOT using force
configureLoggingWithSettings(context, settings, false);
configureLogging(context, settings, undefined, false);

@@ -844,3 +883,3 @@ checkEnabledsBasedOnLogLevel(t, context, overrideLogLevel);

// Now override with logging configuration using force
configureLoggingWithSettings(context, settings, true);
configureLogging(context, settings, undefined, true);

@@ -855,13 +894,13 @@ t.equal(context.abc, 123, 'context must still be intact');

// =====================================================================================================================
// Test configureLoggingWithSettings with default getDefaultLoggingSettings
// Test configureLogging with default settings
// =====================================================================================================================
test('configureLoggingWithSettings with default getDefaultLoggingSettings on existing object with test logger & defaults', t => {
const logLevel = defaultSettings.logLevel;
const logger = testLogger(logLevel, false, t);
test('configureLogging with default settings on existing object with test logger & defaults', t => {
const logLevel = defaultOptions.logLevel;
const logger = testLogger(logLevel, false, '', t);
// Configure default logging when no logging configured yet (without force)
const context = {abc: 123};
const defaults = getDefaultLoggingSettings(undefined, logger);
configureLoggingWithSettings(context, defaults, false);
const onlyLogger = {underlyingLogger: logger};
configureLogging(context, onlyLogger, undefined, false);

@@ -873,13 +912,13 @@ t.equal(context.abc, 123, 'context must still be intact');

// Now override with something else entirely using force (to change away from previous config settings)
const overrideLogLevel = logLevel !== ERROR ? ERROR : TRACE;
const overrideLogLevel = logLevel !== LogLevel.ERROR ? LogLevel.ERROR : LogLevel.TRACE;
const overrideSettings = {
logLevel: overrideLogLevel,
useLevelPrefixes: !defaultSettings.useLevelPrefixes,
useConsoleTrace: !defaultSettings.useConsoleTrace,
underlyingLogger: testLogger(overrideLogLevel, false, t)
useLevelPrefixes: !defaultOptions.useLevelPrefixes,
useConsoleTrace: !defaultOptions.useConsoleTrace,
underlyingLogger: testLogger(overrideLogLevel, false, '', t)
};
configureLoggingWithSettings(context, overrideSettings, true);
configureLogging(context, overrideSettings, undefined, true);
// Now do NOT override with default logging configuration when NOT using force
configureLoggingWithSettings(context, defaults, false);
configureLogging(context, onlyLogger, undefined, false);

@@ -890,3 +929,3 @@ checkEnabledsBasedOnLogLevel(t, context, overrideLogLevel);

// Now override with default logging configuration using force
configureLoggingWithSettings(context, defaults, true);
configureLogging(context, onlyLogger, undefined, true);

@@ -901,18 +940,18 @@ t.equal(context.abc, 123, 'context must still be intact');

// =====================================================================================================================
// Test configureLoggingWithSettings with non-default getDefaultLoggingSettings
// Test configureLogging with non-default settings
// =====================================================================================================================
test('configureLoggingWithSettings with getDefaultLoggingSettings on existing object with test logger & config.logLevel etc.', t => {
const logLevel = defaultSettings.logLevel !== TRACE ? TRACE : ERROR;
const logger = testLogger(logLevel, false, t);
test('configureLogging with settings on existing object with test logger & config.logLevel etc.', t => {
const logLevel = defaultOptions.logLevel !== LogLevel.TRACE ? LogLevel.TRACE : LogLevel.ERROR;
const logger = testLogger(logLevel, false, '', t);
// Configure logging from config when no logging configured yet (without force)
const context = {abc: 123};
const options = {
const settings = {
logLevel: logLevel,
useLevelPrefixes: !defaultSettings.useLevelPrefixes,
useConsoleTrace: !defaultSettings.useConsoleTrace
useLevelPrefixes: !defaultOptions.useLevelPrefixes,
useConsoleTrace: !defaultOptions.useConsoleTrace,
underlyingLogger: logger
};
const settings = getDefaultLoggingSettings(options, logger);
configureLoggingWithSettings(context, settings, false);
configureLogging(context, settings, undefined, false);

@@ -924,13 +963,14 @@ t.equal(context.abc, 123, 'context must still be intact');

// Now override with something else entirely using force (to change away from previous config settings)
const overrideLogLevel = logLevel !== ERROR ? ERROR : TRACE;
const overrideOptions = {
const overrideLogLevel = logLevel !== LogLevel.ERROR ? LogLevel.ERROR : LogLevel.TRACE;
const overrideSettings = {
logLevel: overrideLogLevel,
useLevelPrefixes: defaultSettings.useLevelPrefixes,
useConsoleTrace: defaultSettings.useConsoleTrace,
useLevelPrefixes: defaultOptions.useLevelPrefixes,
useConsoleTrace: defaultOptions.useConsoleTrace,
underlyingLogger: testLogger(overrideLogLevel, false, '', t)
};
const overrideSettings = getDefaultLoggingSettings(overrideOptions, testLogger(overrideLogLevel, false, t));
configureLoggingWithSettings(context, overrideSettings, true);
configureLogging(context, overrideSettings, undefined, true);
// Now do NOT override with logging configuration again when NOT using force
configureLoggingWithSettings(context, settings, false);
configureLogging(context, settings, undefined, false);

@@ -941,3 +981,3 @@ checkEnabledsBasedOnLogLevel(t, context, overrideLogLevel);

// Now override with logging configuration using force
configureLoggingWithSettings(context, settings, true);
configureLogging(context, settings, undefined, true);

@@ -956,11 +996,16 @@ t.equal(context.abc, 123, 'context must still be intact');

test('configureLogging with settings', t => {
const logLevel = defaultSettings.logLevel;
const logger = testLogger(logLevel, false, t);
const logLevel = defaultOptions.logLevel;
const logger = testLogger(logLevel, false, '', t);
// Configure default logging when no logging configured yet (without force)
const context = {abc: 123};
const settings = getDefaultLoggingSettings(undefined, logger);
//const settings = {underlyingLogger: logger};
const settings = getDefaultLoggingOptions();
settings.underlyingLogger = logger;
const options = undefined;
configureLogging(context, settings, options, logger, false);
configureLogging(context, settings, options, false);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must be test logger');
t.equal(context.abc, 123, 'context must still be intact');

@@ -971,14 +1016,19 @@ checkEnabledsBasedOnLogLevel(t, context, logLevel);

// Now override with something else entirely using force (to change away from previous config settings)
const overrideLogLevel = logLevel !== ERROR ? ERROR : TRACE;
const overrideLogLevel = logLevel !== LogLevel.ERROR ? LogLevel.ERROR : LogLevel.TRACE;
const overrideLogger = testLogger(overrideLogLevel, false, '', t);
const overrideSettings = {
logLevel: overrideLogLevel,
useLevelPrefixes: !defaultSettings.useLevelPrefixes,
useConsoleTrace: !defaultSettings.useConsoleTrace,
underlyingLogger: testLogger(overrideLogLevel, false, t)
useLevelPrefixes: !defaultOptions.useLevelPrefixes,
useConsoleTrace: !defaultOptions.useConsoleTrace,
underlyingLogger: overrideLogger
};
configureLoggingWithSettings(context, overrideSettings, true);
configureLogging(context, overrideSettings, undefined, true);
t.equal(context._underlyingLogger, overrideLogger, 'context._underlyingLogger must be override test logger');
// Now do NOT override with default logging configuration
configureLogging(context, settings, options, logger, false);
configureLogging(context, settings, options, false);
t.equal(context._underlyingLogger, overrideLogger, 'context._underlyingLogger must still be override test logger');
checkEnabledsBasedOnLogLevel(t, context, overrideLogLevel);

@@ -988,4 +1038,6 @@ logOneOfEach(context, overrideLogLevel);

// Now override with default logging configuration
configureLogging(context, settings, options, logger, true);
configureLogging(context, settings, options, true);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must now be original test logger');
t.equal(context.abc, 123, 'context must still be intact');

@@ -1002,16 +1054,18 @@ checkEnabledsBasedOnLogLevel(t, context, logLevel);

test('configureLogging with getDefaultLoggingSettings on existing object with test logger & config.logLevel etc.', t => {
const logLevel = defaultSettings.logLevel !== TRACE ? TRACE : ERROR;
const logger = testLogger(logLevel, false, t);
test('configureLogging with default options on existing object with test logger & config.logLevel etc.', t => {
const logLevel = defaultOptions.logLevel !== LogLevel.TRACE ? LogLevel.TRACE : LogLevel.ERROR;
const logger = testLogger(logLevel, false, '', t);
// Configure logging from config when no logging configured yet (without force)
const context = {abc: 123};
const settings = undefined;
const onlyLogger = {underlyingLogger: logger};
const options = {
logLevel: logLevel,
useLevelPrefixes: !defaultSettings.useLevelPrefixes,
useConsoleTrace: !defaultSettings.useConsoleTrace
useLevelPrefixes: !defaultOptions.useLevelPrefixes,
useConsoleTrace: !defaultOptions.useConsoleTrace
};
configureLogging(context, settings, options, logger, false);
configureLogging(context, onlyLogger, options, false);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must be test logger');
t.equal(context.abc, 123, 'context must still be intact');

@@ -1022,14 +1076,20 @@ checkEnabledsBasedOnLogLevel(t, context, logLevel);

// Now override with something else entirely using force (to change away from previous config settings)
const overrideLogLevel = logLevel !== ERROR ? ERROR : TRACE;
const overrideLogLevel = logLevel !== LogLevel.ERROR ? LogLevel.ERROR : LogLevel.TRACE;
const overrideOptions = {
logLevel: overrideLogLevel,
useLevelPrefixes: defaultSettings.useLevelPrefixes,
useConsoleTrace: defaultSettings.useConsoleTrace,
useLevelPrefixes: defaultOptions.useLevelPrefixes,
useConsoleTrace: defaultOptions.useConsoleTrace
};
const overrideSettings = getDefaultLoggingSettings(overrideOptions, testLogger(overrideLogLevel, false, t));
configureLoggingWithSettings(context, overrideSettings, true);
const overrideLogger = testLogger(overrideLogLevel, false, '', t);
const onlyOverrideLogger = {underlyingLogger: overrideLogger};
configureLogging(context, onlyOverrideLogger, overrideOptions, true);
t.equal(context._underlyingLogger, overrideLogger, 'context._underlyingLogger must now be override test logger');
// Now do NOT override with logging configuration again
configureLogging(context, settings, options, logger, false);
configureLogging(context, onlyLogger, options, false);
t.equal(context._underlyingLogger, overrideLogger, 'context._underlyingLogger must still be override test logger');
checkEnabledsBasedOnLogLevel(t, context, overrideLogLevel);

@@ -1039,4 +1099,6 @@ logOneOfEach(context, overrideLogLevel);

// Now override with logging configuration using force
configureLogging(context, settings, options, logger, true);
configureLogging(context, onlyLogger, options, true);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must now be original test logger');
t.equal(context.abc, 123, 'context must still be intact');

@@ -1054,4 +1116,4 @@ checkEnabledsBasedOnLogLevel(t, context, logLevel);

test('configureLogging with settings AND options', t => {
const logLevel = TRACE;
const logger = testLogger(logLevel, false, t);
const logLevel = LogLevel.TRACE;
const logger = testLogger(logLevel, false, '', t);

@@ -1061,7 +1123,9 @@ // Configure default logging when no logging configured yet (without force)

const settings = {logLevel: TRACE, underlyingLogger: logger};
const options = getDefaultLoggingSettings(undefined, undefined);
const settings = {logLevel: LogLevel.TRACE, underlyingLogger: logger};
const options = getDefaultLoggingOptions();
configureLogging(context, settings, options, undefined, false);
configureLogging(context, settings, options, false);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must be test logger');
t.equal(context.abc, 123, 'context must still be intact');

@@ -1072,14 +1136,19 @@ checkEnabledsBasedOnLogLevel(t, context, logLevel);

// Now override with something else entirely using force (to change away from previous config settings)
const overrideLogLevel = logLevel !== ERROR ? ERROR : TRACE;
const overrideLogLevel = logLevel !== LogLevel.ERROR ? LogLevel.ERROR : LogLevel.TRACE;
const overrideLogger = testLogger(overrideLogLevel, false, '', t);
const overrideSettings = {
logLevel: overrideLogLevel,
useLevelPrefixes: !defaultSettings.useLevelPrefixes,
useConsoleTrace: !defaultSettings.useConsoleTrace,
underlyingLogger: testLogger(overrideLogLevel, false, t)
useLevelPrefixes: !defaultOptions.useLevelPrefixes,
useConsoleTrace: !defaultOptions.useConsoleTrace,
underlyingLogger: overrideLogger
};
configureLoggingWithSettings(context, overrideSettings, true);
configureLogging(context, overrideSettings, undefined, true);
t.equal(context._underlyingLogger, overrideLogger, 'context._underlyingLogger must now be override test logger');
// Now do NOT override with default logging configuration
configureLogging(context, settings, options, logger, false);
configureLogging(context, settings, options, false);
t.equal(context._underlyingLogger, overrideLogger, 'context._underlyingLogger must still be override test logger');
checkEnabledsBasedOnLogLevel(t, context, overrideLogLevel);

@@ -1089,4 +1158,6 @@ logOneOfEach(context, overrideLogLevel);

// Now override with default logging configuration
configureLogging(context, settings, options, logger, true);
configureLogging(context, settings, options, true);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must now be original test logger');
t.equal(context.abc, 123, 'context must still be intact');

@@ -1098,1 +1169,335 @@ checkEnabledsBasedOnLogLevel(t, context, logLevel);

});
// =====================================================================================================================
// Test configureLogging with settings AND options AND default envLogLevelName AND process.env.LOG_LEVEL
// =====================================================================================================================
test('configureLogging with settings AND options AND default envLogLevelName AND process.env.LOG_LEVEL', t => {
try {
// Configure logLevel as an environment variable
process.env.LOG_LEVEL = LogLevel.TRACE;
const expectedLogLevel = LogLevel.TRACE;
const logger = testLogger(expectedLogLevel, false, '', t);
// Configure default logging when no logging configured yet (without force)
const context = {abc: 123};
const settings = {logLevel: LogLevel.INFO, underlyingLogger: logger};
const options = getDefaultLoggingOptions();
configureLogging(context, settings, options, false);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must be test logger');
t.equal(context.abc, 123, 'context must still be intact');
checkEnabledsBasedOnLogLevel(t, context, expectedLogLevel);
logOneOfEach(context, expectedLogLevel);
// Now attempt to override override with something else entirely using force (to change away from previous config settings)
const overrideLogLevel = LogLevel.DEBUG;
const overrideLogger = testLogger(expectedLogLevel, false, '', t);
const overrideSettings = {
logLevel: overrideLogLevel,
useLevelPrefixes: !defaultOptions.useLevelPrefixes,
useConsoleTrace: !defaultOptions.useConsoleTrace,
underlyingLogger: overrideLogger
};
configureLogging(context, overrideSettings, undefined, true);
t.equal(context._underlyingLogger, overrideLogger, 'context._underlyingLogger must now be override test logger');
t.equal(context.logLevel, expectedLogLevel, `logLevel must STILL be ${expectedLogLevel}`);
// Now do NOT override with default logging configuration
configureLogging(context, settings, options, false);
t.equal(context._underlyingLogger, overrideLogger, 'context._underlyingLogger must still be override test logger');
// Makes NO difference, because environment setting takes precedence over any other setting or option regardless of forceConfiguration
checkEnabledsBasedOnLogLevel(t, context, expectedLogLevel);
logOneOfEach(context, expectedLogLevel);
t.equal(context.logLevel, expectedLogLevel, `logLevel must STILL be ${expectedLogLevel}`);
// Now attempt to override with default logging configuration
configureLogging(context, settings, options, true);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must now be original test logger');
t.equal(context.abc, 123, 'context must still be intact');
checkEnabledsBasedOnLogLevel(t, context, expectedLogLevel);
logOneOfEach(context, expectedLogLevel);
t.equal(context.logLevel, expectedLogLevel, `logLevel must STILL be ${expectedLogLevel}`);
t.end();
} finally {
process.env.LOG_LEVEL = undefined;
}
});
// =====================================================================================================================
// Test configureLogging with settings AND options AND envLogLevelName set to "logLevel" AND process.env.logLevel
// =====================================================================================================================
test('configureLogging with settings AND options AND envLogLevelName set to "logLevel" AND process.env.logLevel', t => {
try {
// Configure logLevel as an environment variable
process.env.logLevel = LogLevel.WARN;
const expectedLogLevel = LogLevel.WARN;
const logger = testLogger(expectedLogLevel, false, '', t);
// Configure default logging when no logging configured yet (without force)
const context = {abc: 123};
const settings = {logLevel: LogLevel.TRACE, envLogLevelName: 'logLevel', underlyingLogger: logger};
const options = getDefaultLoggingOptions();
configureLogging(context, settings, options, false);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must be test logger');
t.equal(context.abc, 123, 'context must still be intact');
checkEnabledsBasedOnLogLevel(t, context, expectedLogLevel);
logOneOfEach(context, expectedLogLevel);
// Now attempt to override override with something else entirely using force (to change away from previous config settings)
const overrideLogLevel = expectedLogLevel !== LogLevel.ERROR ? LogLevel.ERROR : LogLevel.TRACE;
const overrideLogger = testLogger(expectedLogLevel, false, '', t);
const overrideSettings = {
logLevel: overrideLogLevel,
useLevelPrefixes: !defaultOptions.useLevelPrefixes,
envLogLevelName: 'logLevel',
useConsoleTrace: !defaultOptions.useConsoleTrace,
underlyingLogger: overrideLogger
};
configureLogging(context, overrideSettings, undefined, true);
t.equal(context._underlyingLogger, overrideLogger, 'context._underlyingLogger must be override test logger');
t.equal(context.logLevel, expectedLogLevel, `logLevel must STILL be ${expectedLogLevel}`);
// Now do NOT override with default logging configuration
configureLogging(context, settings, options, false);
t.equal(context._underlyingLogger, overrideLogger, 'context._underlyingLogger must still be override test logger');
// Makes NO difference, because environment setting takes precedence over any other setting or option regardless of forceConfiguration
checkEnabledsBasedOnLogLevel(t, context, expectedLogLevel);
logOneOfEach(context, expectedLogLevel);
t.equal(context.logLevel, expectedLogLevel, `logLevel must STILL be ${expectedLogLevel}`);
// Now attempt to override with default logging configuration
configureLogging(context, settings, options, true);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must now be original test logger');
t.equal(context.abc, 123, 'context must still be intact');
checkEnabledsBasedOnLogLevel(t, context, expectedLogLevel);
logOneOfEach(context, expectedLogLevel);
t.equal(context.logLevel, expectedLogLevel, `logLevel must STILL be ${expectedLogLevel}`);
t.end();
} finally {
process.env.logLevel = undefined;
}
});
// =====================================================================================================================
// log method and log function
// =====================================================================================================================
test('log method and log function', t => {
const context = {abc: 123};
const logLevelNames = Object.getOwnPropertyNames(LogLevel);
for (let i = 0; i < logLevelNames.length; ++i) {
const logLevel = LogLevel[logLevelNames[i]];
const logger = testLogger(logLevel, false, 'TEST', t);
// Configure default logging when no logging configured yet (without force)
const settings = {logLevel: logLevel, underlyingLogger: logger};
configureLogging(context, settings, undefined, true);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must be test logger');
checkEnabledsBasedOnLogLevel(t, context, logLevel);
// Use log method to log a message at each level
logOneOfEachUsingLogMethod(context, logLevel);
// Use log function on context to log a message at each level
logOneOfEachUsingLogFunction(context, logLevel, 'context');
// Use log function on console to log a message at each level
logOneOfEachUsingLogFunction(console, logLevel, 'console');
// Use log function on undefined to log a message at each level
logOneOfEachUsingLogFunction(undefined, logLevel, 'undefined');
}
// Check log method & log function with no log levels
context.log('PINK', '*** Log "PINK" message ***');
context.log('%s PINK', '*** Log "%s PINK" message ***');
context.log('Blue', '*** Log "Blue" message ***');
context.log('%s Blue', '*** Log "%s Blue" message ***');
context.log('*** Log message without level ***');
context.log();
log(context, 'RED', '*** log(context, "RED") message ***');
log(context, '%s RED', '*** log(context, "%s RED") message ***');
log(context, 'Green', '*** log(context, "Green") message ***');
log(context, '%s Green', '*** log(context, "%s Green") message ***');
log(context, '*** log(context, ...) message without level ***');
log(context);
log(console, 'RED', '*** log(console, "RED") message ***');
log(console, '%s RED', '*** log(console, "%s RED") message ***');
log(undefined, 'Green', '*** log(undefined, "Green") message ***');
log(undefined, '%s Green', '*** log(undefined, "%s Green") message ***');
log(console, '*** log(console, ...) message without level ***');
log(undefined);
t.end();
});
test('Minimum viable loggers', t => {
const logLevelNames = Object.getOwnPropertyNames(LogLevel);
for (let i = 0; i < logLevelNames.length; ++i) {
const logLevel = LogLevel[logLevelNames[i]];
// Logger with ALL methods
let prefix = 'AllOK ';
let logger = testLogger(LogLevel.TRACE, false, prefix, t);
t.ok(isMinimumViableLogger(logger), 'test logger is a minimum viable logger');
let context = {};
let settings = {logLevel: logLevel, underlyingLogger: logger};
configureLogging(context, settings, undefined, true);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must be test logger');
logOneOfEachUsingLogMethod(context, logLevel);
// Logger without log method - is NOT viable!
prefix = 'NoLog ';
logger = testLogger(LogLevel.TRACE, false, prefix, t);
delete logger.log;
t.notOk(isMinimumViableLogger(logger), 'test logger without a log method is NOT a minimum viable logger');
context = {};
settings = {logLevel: logLevel, underlyingLogger: logger};
t.throws(() => configureLogging(context, settings, undefined, true), Error, 'configureLogging must fail without log method');
// Logger without error method - is NOT viable!
prefix = 'NoError ';
logger = testLogger(LogLevel.TRACE, false, prefix, t);
delete logger.error;
t.notOk(isMinimumViableLogger(logger), 'test logger without error is NOT a minimum viable logger');
context = {};
settings = {logLevel: logLevel, underlyingLogger: logger};
t.throws(() => configureLogging(context, settings, undefined, true), Error, 'configureLogging must fail without error method');
// Logger without warn method
prefix = 'NoWarn ';
logger = testLogger(LogLevel.TRACE, false, prefix, t);
delete logger.warn;
t.ok(isMinimumViableLogger(logger), 'test logger without warn is still a minimum viable logger');
context = {};
settings = {logLevel: logLevel, underlyingLogger: logger};
configureLogging(context, settings, undefined, true);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must be test logger');
logOneOfEachUsingLogMethod(context, logLevel);
// Logger without info method
prefix = 'NoInfo ';
logger = testLogger(LogLevel.TRACE, false, prefix, t);
delete logger.info;
t.ok(isMinimumViableLogger(logger), 'test logger without info is still a minimum viable logger');
context = {};
settings = {logLevel: logLevel, underlyingLogger: logger};
configureLogging(context, settings, undefined, true);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must be test logger');
logOneOfEachUsingLogMethod(context, logLevel);
// Logger without debug method
prefix = 'NoDebug ';
logger = testLogger(LogLevel.TRACE, false, prefix, t);
delete logger.debug;
t.ok(isMinimumViableLogger(logger), 'test logger without debug is still a minimum viable logger');
context = {};
settings = {logLevel: logLevel, underlyingLogger: logger};
configureLogging(context, settings, undefined, true);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must be test logger');
logOneOfEachUsingLogMethod(context, logLevel);
// Logger without trace method
prefix = 'NoTrace ';
logger = testLogger(LogLevel.TRACE, false, prefix, t);
delete logger.trace;
t.ok(isMinimumViableLogger(logger), 'test logger without trace is still a minimum viable logger');
context = {};
settings = {logLevel: logLevel, underlyingLogger: logger};
configureLogging(context, settings, undefined, true);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must be test logger');
logOneOfEachUsingLogMethod(context, logLevel);
// Logger without debug and trace methods
prefix = 'NoDebugTrace ';
logger = testLogger(LogLevel.TRACE, false, prefix, t);
delete logger.debug;
delete logger.trace;
t.ok(isMinimumViableLogger(logger), 'test logger without debug & trace is still a minimum viable logger');
context = {};
settings = {logLevel: logLevel, underlyingLogger: logger};
configureLogging(context, settings, undefined, true);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must be test logger');
logOneOfEachUsingLogMethod(context, logLevel);
// Logger without info, debug and trace methods
prefix = 'NoInfoDebugTrace ';
logger = testLogger(LogLevel.TRACE, false, prefix, t);
delete logger.info;
delete logger.debug;
delete logger.trace;
t.ok(isMinimumViableLogger(logger), 'test logger without info, debug & trace is still a minimum viable logger');
context = {};
settings = {logLevel: logLevel, underlyingLogger: logger};
configureLogging(context, settings, undefined, true);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must be test logger');
logOneOfEachUsingLogMethod(context, logLevel);
// Logger without warn, debug and trace methods
prefix = 'NoWarnInfoDebugTrace ';
logger = testLogger(LogLevel.TRACE, false, prefix, t);
delete logger.warn;
delete logger.info;
delete logger.debug;
delete logger.trace;
t.ok(isMinimumViableLogger(logger), 'test logger without warn, info, debug & trace is still a minimum viable logger');
context = {};
settings = {logLevel: logLevel, underlyingLogger: logger};
configureLogging(context, settings, undefined, true);
t.equal(context._underlyingLogger, logger, 'context._underlyingLogger must be test logger');
logOneOfEachUsingLogMethod(context, logLevel);
// Console
t.ok(isMinimumViableLogger(console), 'console is a minimum viable logger');
context = {};
settings = {logLevel: logLevel, underlyingLogger: console};
configureLogging(context, settings, undefined, true);
t.equal(context._underlyingLogger, console, 'context._underlyingLogger must be console');
logOneOfEachUsingLogMethod(context, logLevel);
}
t.end();
});
{
"name": "logging-utils-tests",
"description": "Unit tests for logging-utils",
"version": "3.0.12",
"version": "4.0.0",
"author": "Byron du Preez",

@@ -6,0 +6,0 @@ "license": "Apache-2.0",

'use strict';
/**
* @typedef {Object} Logging - logging functionality
* @property {Function} error - an error-level logging function
* @property {Function} warn - a warn-level logging function
* @property {Function} info - an info-level logging function
* @property {Function} debug - an debug-level logging function
* @property {Function} trace - a trace-level logging function
* @typedef {Object} Logger - a logger object with logging functionality
* @property {function(data: ...*)} error - an error-level logging method
* @property {function(data: ...*)} warn - a warn-level logging method
* @property {function(data: ...*)} info - an info-level logging method
* @property {function(data: ...*)} debug - an debug-level logging method
* @property {function(data: ...*)} trace - a trace-level logging method
* @property {function(data: ...*)} log - a logging method that delegates to the others if given a valid logLevel as first argument; otherwise uses its underlying logger's log method (if any) or info method (if none)
* @property {boolean} warnEnabled - whether warn-level logging is enabled or not

@@ -21,3 +22,5 @@ * @property {boolean} infoEnabled - whether info-level logging is enabled or not

* The optional underlyingLogger, if defined, determines the underlying logger that will be used to do the actual
* logging. If defined, the underlyingLogger must have error, warn, info, debug & trace methods; otherwise console will
* logging. If defined, the underlyingLogger must be either console or a minimum viable logger-like object, which means
* that it must have
* an error method and a warn methods and must have EITHER an info method OR a log method OR both.have error, warn, info, debug & trace methods; otherwise console will
* be used as the underlying logger. For AWS Lambdas, only console will be used and the underlyingLogger is only

@@ -28,25 +31,24 @@ * currently used for testing the logging functionality.

/**
* @typedef {Object} LoggingOptions - Logging options are a subset of the full (@linkcode LoggingSettings}, which are
* used to configure ONLY the simple property logging settings (i.e. all except underlyingLogger)
* @property {string|undefined} [logLevel] - the level of logging to use ('error', 'warn', 'info', 'debug' or 'trace')
* @typedef {Object} LoggingOptions - Logging options are a subset of the full LoggingSettings, which are used to
* configure ONLY the simple property logging settings (i.e. all except underlyingLogger)
* @property {LogLevel|undefined} [logLevel] - the level of logging to use (see LogLevel enum)
* @property {boolean|undefined} [useLevelPrefixes] - whether to prepend level prefixes to logged messages or not
* @property {string|undefined} [envLogLevelName] - the name of the environment variable in which to look for a configured log level (e.g. 'LOG_LEVEL')
* @property {boolean|undefined} [useConsoleTrace] - whether to use console.trace or console.log for trace level logging
*
* The optional logLevel, if defined and valid, sets the level of logging to be used. If undefined or invalid, the
* defaultLogLevel will be used instead.
* The logLevel option sets the level of logging to be used. If undefined or invalid, the default logLevel (currently
* LogLevel.INFO) will be used instead.
*
* Log levels:
* - error - only logs at error level
* - warn - only logs at warn & error levels
* - info - logs at info, warn & error levels
* - debug - logs at debug, info, warn & error levels
* - trace - logs at trace, debug, info, warn & error levels
* - ERROR - only logs on error calls (i.e. suppresses warn, info, debug & trace calls)
* - WARN - only logs on warn & error calls (i.e. suppresses info, debug & trace calls)
* - INFO - logs on info, warn & error calls (i.e. suppresses only debug & trace calls)
* - DEBUG - logs on debug, info, warn & error levels (i.e. suppresses only trace calls)
* - TRACE - logs on trace, debug, info, warn & error calls (i.e. does NOT suppress any logging calls)
*
* The optional useLevelPrefixes, if defined and either true or false, indicates whether or not to prepend log level
* prefixes to logged messages.
* The useLevelPrefixes option indicates whether or not to prepend log level prefixes to logged messages.
*
* The optional useConsoleTrace, if defined and either true or false, indicates whether to use console.trace (true) or
* console.log (false) for trace level logging. However, before setting this to true, be warned that console.trace logs
* to standard error and ALSO outputs the stack trace, which is generally NOT what you want for the most detailed level
* of logging.
* The useConsoleTrace option indicates whether to use console.trace (true) or console.log (false) for trace level
* logging. However, before setting this to true, be warned that console.trace logs to standard error and ALSO outputs
* the stack trace, which is generally NOT what you want for the most detailed level of logging.
*/
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc