@ibm-cloud/openapi-ruleset
Version:
Spectral ruleset for validating IBM Cloud services
138 lines (123 loc) • 4.42 kB
JavaScript
/**
* Copyright 2017 - 2023 IBM Corporation.
* SPDX-License-Identifier: Apache2.0
*/
const log = require('loglevel');
const minimatch = require('minimatch');
const prefix = require('loglevel-plugin-prefix');
const chalk = require('chalk');
const colors = {
TRACE: chalk.magenta,
DEBUG: chalk.cyan,
INFO: chalk.green,
WARN: chalk.yellow,
ERROR: chalk.red,
};
/**
* This class serves as a factory for creating loggers implemented by the 'loglevel' package.
* The primary benefit provided by this factory class is the ability to honor logging-level-related
* command-line options for loggers that haven't yet been created.
*/
module.exports = class LoggerFactory {
constructor() {
this.rootLogger = log;
this.loggerSettings = [];
// Register the prefix handler with the loglevel.
// This will control the [<level>] message prefixes.
prefix.reg(log);
prefix.apply(log, {
levelFormatter(level) {
return level.toUpperCase();
},
format(level) {
return `${colors[level](`[${level}]`)}`;
},
});
}
/**
* @returns a single instance of our factory.
*/
static getInstance() {
if (!global.__ibm_openapi_validator_logger_factory) {
global.__ibm_openapi_validator_logger_factory = new LoggerFactory();
}
return global.__ibm_openapi_validator_logger_factory;
}
/**
* A logger setting consists of a logger name (a glob-like string,
* e.g. 'my-*-logger' or 'my-first-logger') and a log level
* (e.g. 'error', 'warn', 'info', 'debug', or 'trace').
* This function adds the logger setting specified by "name" and
* "logLevel" to the current array of logger settings.
* @param {*} name the name of the logger (glob-like string)
* @param {*} logLevel the log level to set on the logger
*/
addLoggerSetting(name, logLevel) {
checkLevel(logLevel);
this.loggerSettings.push({
loggerName: name,
logLevel,
});
this.applySettingsToAllLoggers();
}
/**
* Returns the logger with name "<name>".
* If "name" is falsy or the string "root", then the root logger is returned.
* The resulting logger will have the current logger settings applied to it, which
* might affect the logging level.
* @param {*} name the name of the logger to be retrieved
* @returns the logger with the specified name
*/
getLogger(name) {
const logger =
name && name !== 'root'
? this.rootLogger.getLogger(name)
: this.rootLogger;
// If the root logger already has a loglevel set on it
// that is different from the default ("warn"), then any
// new loggers created from the root logger will also have
// that same level set on it automatically.
// So, to avoid that, we'll set the new logger's level
// immediately to the default ("warn"), then let the
// "applyLoggerSettings()" method potentially set it to the
// correct level per user-supplied command-line options.
logger.setLevel('warn');
this.applyLoggerSettings(name, logger);
return logger;
}
/**
* Applies the currently-defined logger settings to the specified logger with name "<name>".
* @param {*} name the name of the logger
* @param {*} logger the logger to apply logger settings to
*/
applyLoggerSettings(name, logger) {
if (!name) {
name = 'root';
}
for (const setting of this.loggerSettings) {
// If the name of the logger matches the (potential) glob-pattern
// previously-specified via the command-line, then apply the
// specified log level to that logger.
if (minimatch(name, setting.loggerName)) {
logger.setLevel(setting.logLevel);
}
}
}
/**
* Visits all existing loggers and applies the currently-defined logger settings
* to each one. This is useful in situations where some loggers might already exist
* prior to the command-line arguments being processed.
*/
applySettingsToAllLoggers() {
this.applyLoggerSettings('root', this.rootLogger);
for (const key in this.rootLogger.getLoggers()) {
this.applyLoggerSettings(key, this.rootLogger.getLogger(key));
}
}
};
const validLevels = ['error', 'warn', 'info', 'debug', 'trace'];
function checkLevel(logLevel) {
if (!validLevels.includes(logLevel.toLowerCase())) {
throw `Invalid log level '${logLevel}'. Valid log levels: ${validLevels}`;
}
}