logging-utils
Advanced tools
Comparing version 3.0.12 to 4.0.0
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" | ||
} | ||
} |
136
README.md
@@ -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. | ||
*/ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
108659
10
1570
309
6
1
+ Addedcore-functions@3.0.25(transitive)
- Removedcore-functions@2.0.18(transitive)
Updatedcore-functions@^3.0.0