@linkedmink/node-route53-dynamic-dns
Version:
Background process that updates AWS Route 53 DNS address records whenever the public IP of the hosting environment changes
107 lines • 4.38 kB
JavaScript
import path from "node:path";
import { fileURLToPath } from "node:url";
import * as winston from "winston";
import { ConfigKey } from "../constants/config.mjs";
import { DEFAULT_LOGGER_LABEL, DEFAULT_LOG_LEVEL, LogLevel } from "../constants/logging.mjs";
import { getEnumKeys } from "../functions/convert.mjs";
import { formatError } from "../functions/format.mjs";
const getDefaultFormat = (label) => {
return winston.format.combine(winston.format.errors({ stack: true }), winston.format.colorize(), winston.format.label({ label, message: false }), winston.format.timestamp(), winston.format.printf(info => {
const label = typeof info.label === "string" ? ` ${info.label}` : "";
const message = typeof info.stack === "string" ? info.stack : info.message;
return `${info.timestamp} ${info.level}${label}: ${message}`;
}));
};
const getDefaultOptions = (label) => {
const options = {
levels: winston.config.npm.levels,
level: DEFAULT_LOG_LEVEL,
transports: [
new winston.transports.Console({
format: getDefaultFormat(label),
}),
],
};
return options;
};
/**
* Change the options before constructing a logger. A logger will use the options
* set at the time the first get() is called for a specific label
*/
let loggerOptionsFunc = getDefaultOptions;
/**
* Wrap the Winston logger container, so we can get the same logger for each module.
* @param label The label of the module we're logging
* @return An instance of the logger
*/
export const loggerForLabel = (label = DEFAULT_LOGGER_LABEL) => {
if (!winston.loggers.has(label)) {
return winston.loggers.add(label, loggerOptionsFunc(label));
}
return winston.loggers.get(label);
};
/**
* @param moduleUrl Use {@link ImportMeta.url import.meta.url} for ESM modules to generate label
* @return An instance of the logger
*/
export const loggerForModuleUrl = (moduleUrl) => {
const moduleFilename = path.basename(fileURLToPath(moduleUrl));
const moduleName = moduleFilename.substring(0, moduleFilename.length - path.extname(moduleFilename).length);
return loggerForLabel(moduleName);
};
/**
* Wrap expensive operations, so we don't perform them for logging unless logging for the level is enabled
* @param logger
* @param level
* @param messageFunc
*/
export const logWhenEnabled = (logger, level, messageFunc) => {
const loggerLevel = LogLevel[logger.level];
if (level <= loggerLevel) {
logger.log(LogLevel[level], messageFunc(loggerLevel));
}
};
/**
* Sets the options to construct winston loggers and configures logging for unhandled errors
* @param config Configuration determines the output transport streams
* @returns The default global logger
*/
export const initializeLogging = (config) => {
const getLoggerOptions = (label) => {
const format = getDefaultFormat(label);
const outputs = [new winston.transports.Console({ format })];
const logFilePath = config.getStringOrNull(ConfigKey.LogFile);
if (logFilePath && !config.isEnvironmentContainerized) {
outputs.push(new winston.transports.File({
filename: logFilePath,
format,
}));
}
const logLevel = config.getString(ConfigKey.LogLevel);
const numericLogLevel = LogLevel[logLevel];
if (numericLogLevel === undefined || isNaN(numericLogLevel)) {
const allowed = getEnumKeys(LogLevel).toString();
throw new Error(`Log level is invalid: value=${logLevel}, allowed=${allowed}`);
}
const options = {
level: logLevel,
transports: outputs,
};
return options;
};
loggerOptionsFunc = getLoggerOptions;
const logger = loggerForLabel();
if (process.listenerCount("uncaughtException") <= 0) {
process.on("uncaughtException", (error, _origin) => {
logger.error(`uncaughtException: ${formatError(error)}`);
});
}
if (process.listenerCount("unhandledRejection") <= 0) {
process.on("unhandledRejection", (error, _rejected) => {
logger.error(`unhandledRejection: ${formatError(error)}`);
});
}
logger.verbose(`${initializeLogging.name}: Logger Initialized`);
return logger;
};
//# sourceMappingURL=logger.mjs.map