@stryker-mutator/core
Version:
The extendable JavaScript mutation testing framework
129 lines • 6.61 kB
JavaScript
import { fileURLToPath, URL } from 'url';
import log4js from 'log4js';
import { netUtils } from '../utils/net-utils.js';
import { minLevel } from './log-utils.js';
const layouts = {
color: {
pattern: '%[%r (%z) %p %c%] %m',
type: 'pattern',
},
noColor: {
pattern: '%r (%z) %p %c %m',
type: 'pattern',
},
};
const LOG_FILE_NAME = 'stryker.log';
export class LogConfigurator {
static createMainProcessAppenders(consoleLogLevel, fileLogLevel, allowConsoleColors) {
// Add the custom "multiAppender": https://log4js-node.github.io/log4js-node/appenders.html#other-appenders
const multiAppender = {
type: fileURLToPath(new URL('./multi-appender.cjs', import.meta.url)),
appenders: ["filterLevelConsole" /* AppenderName.FilterLevelConsole */],
};
const consoleLayout = allowConsoleColors ? layouts.color : layouts.noColor;
let allAppenders = {
["console" /* AppenderName.Console */]: { type: 'stdout', layout: consoleLayout },
// Exclude messages like: "ERROR log4js A worker log process hung up unexpectedly" #1245
["filterLog4jsCategoryConsole" /* AppenderName.FilterLog4jsCategoryConsole */]: { type: 'categoryFilter', appender: "console" /* AppenderName.Console */, exclude: 'log4js' },
["filterLevelConsole" /* AppenderName.FilterLevelConsole */]: { type: 'logLevelFilter', appender: "filterLog4jsCategoryConsole" /* AppenderName.FilterLog4jsCategoryConsole */, level: consoleLogLevel },
["all" /* AppenderName.All */]: multiAppender,
};
// only add file if it is needed. Otherwise log4js will create the file directly, pretty annoying.
if (fileLogLevel.toUpperCase() !== "off" /* LogLevel.Off */.toUpperCase()) {
// Add the custom "multiAppender": https://log4js-node.github.io/log4js-node/appenders.html#other-appenders
const stripAnsiAppender = {
type: fileURLToPath(new URL('./strip-ansi-appender.cjs', import.meta.url)),
appender: "file" /* AppenderName.File */,
};
const fileAppender = { type: 'file', filename: LOG_FILE_NAME, layout: layouts.noColor };
const filterLog4sCategory = { type: 'categoryFilter', appender: "stripAnsi" /* AppenderName.StripAnsi */, exclude: 'log4js' };
const filterFileAppender = {
type: 'logLevelFilter',
appender: "filterLog4jsCategoryFile" /* AppenderName.FilterLog4jsCategoryFile */,
level: fileLogLevel,
};
// Don't simply add the appenders, instead actually make sure they are ordinal "before" the others.
// See https://github.com/log4js-node/log4js-node/issues/746
allAppenders = {
...allAppenders,
["file" /* AppenderName.File */]: fileAppender,
["stripAnsi" /* AppenderName.StripAnsi */]: stripAnsiAppender,
["filterLog4jsCategoryFile" /* AppenderName.FilterLog4jsCategoryFile */]: filterLog4sCategory,
["filterLevelFile" /* AppenderName.FilterLevelFile */]: filterFileAppender,
};
multiAppender.appenders.push("filterLevelFile" /* AppenderName.FilterLevelFile */);
}
return allAppenders;
}
static createLog4jsConfig(defaultLogLevel, appenders) {
return {
appenders,
categories: {
default: {
appenders: ["all" /* AppenderName.All */],
level: defaultLogLevel,
},
},
};
}
/**
* Configure logging for the master process. Either call this method or `configureChildProcess` before any `getLogger` calls.
* @param consoleLogLevel The log level to configure for the console
* @param fileLogLevel The log level to configure for the "stryker.log" file
*/
static configureMainProcess(consoleLogLevel = "info" /* LogLevel.Information */, fileLogLevel = "off" /* LogLevel.Off */, allowConsoleColors = true) {
const appenders = this.createMainProcessAppenders(consoleLogLevel, fileLogLevel, allowConsoleColors);
log4js.configure(this.createLog4jsConfig(minLevel(consoleLogLevel, fileLogLevel), appenders));
}
/**
* Configure the logging for the server. Includes the master configuration.
* This method should only be called ONCE, as it starts the log4js server to listen for log events.
* It returns the logging client context that should be used to configure the child processes.
*
* @param consoleLogLevel the console log level
* @param fileLogLevel the file log level
* @returns the context
*/
static async configureLoggingServer(consoleLogLevel, fileLogLevel, allowConsoleColors) {
const loggerPort = await netUtils.getFreePort();
// Include the appenders for the main Stryker process, as log4js has only one single `configure` method.
const appenders = this.createMainProcessAppenders(consoleLogLevel, fileLogLevel, allowConsoleColors);
const multiProcessAppender = {
appender: "all" /* AppenderName.All */,
loggerPort,
mode: 'master',
type: 'multiprocess',
};
appenders["server" /* AppenderName.Server */] = multiProcessAppender;
const defaultLogLevel = minLevel(consoleLogLevel, fileLogLevel);
log4js.configure(this.createLog4jsConfig(defaultLogLevel, appenders));
const context = {
level: defaultLogLevel,
port: loggerPort,
};
return context;
}
/**
* Configures the logging for a worker process. Sends all logging to the master process.
* Either call this method or `configureMainProcess` before any `getLogger` calls.
* @param context the logging client context used to configure the logging client
*/
static configureChildProcess(context) {
const clientAppender = { type: 'multiprocess', mode: 'worker', loggerPort: context.port };
const appenders = { ["all" /* AppenderName.All */]: clientAppender };
log4js.configure(this.createLog4jsConfig(context.level, appenders));
}
static shutdown() {
return new Promise((res, rej) => {
log4js.shutdown((err) => {
if (err) {
rej(err);
}
else {
res();
}
});
});
}
}
//# sourceMappingURL=log-configurator.js.map