@backstage/backend-defaults
Version:
Backend defaults used by Backstage backend apps
169 lines (165 loc) • 5.36 kB
JavaScript
;
var winston = require('winston');
var tripleBeam = require('triple-beam');
var escapeRegExp = require('../../lib/escapeRegExp.cjs.js');
var types = require('./types.cjs.js');
var utils = require('./utils.cjs.js');
class WinstonLogger {
#winston;
#addRedactions;
#setLevelOverrides;
/**
* Creates a {@link WinstonLogger} instance.
*/
static create(options) {
const defaultLogLevel = process.env.LOG_LEVEL || options.level || "info";
const redacter = WinstonLogger.redacter();
const logLevelFilter = WinstonLogger.logLevelFilter(defaultLogLevel);
const defaultFormatter = process.env.NODE_ENV === "production" ? winston.format.json() : WinstonLogger.colorFormat();
let logger = winston.createLogger({
// Lowest level possible as we let the logLevelFilter do the filtering
level: "silly",
format: winston.format.combine(
logLevelFilter.format,
options.format ?? defaultFormatter,
redacter.format
),
transports: options.transports ?? new winston.transports.Console()
});
if (options.meta) {
logger = logger.child(options.meta);
}
return new WinstonLogger(logger, redacter.add, logLevelFilter.setOverrides);
}
/**
* Creates a winston log formatter for redacting secrets.
*/
static redacter() {
const redactionSet = /* @__PURE__ */ new Set();
let redactionPattern = void 0;
return {
format: winston.format((obj) => {
if (!redactionPattern || !obj) {
return obj;
}
if (typeof obj[tripleBeam.MESSAGE] === "string") {
obj[tripleBeam.MESSAGE] = obj[tripleBeam.MESSAGE].replace(redactionPattern, "***");
}
return obj;
})(),
add(newRedactions) {
let added = 0;
for (const redactionToTrim of newRedactions) {
if (redactionToTrim === null || redactionToTrim === void 0) {
continue;
}
const redaction = redactionToTrim.trim();
if (redaction.length <= 1) {
continue;
}
if (!redactionSet.has(redaction)) {
redactionSet.add(redaction);
added += 1;
}
}
if (added > 0) {
const redactions = Array.from(redactionSet).map((r) => escapeRegExp.escapeRegExp(r)).join("|");
redactionPattern = new RegExp(`(${redactions})`, "g");
}
}
};
}
/**
* Creates a pretty printed winston log formatter.
*/
static colorFormat() {
const colorizer = winston.format.colorize();
return winston.format.combine(
winston.format.timestamp(),
winston.format.colorize({
colors: {
timestamp: "dim",
prefix: "blue",
field: "cyan",
debug: "grey"
}
}),
winston.format.printf((info) => {
const { timestamp, level, message, plugin, service, ...fields } = info;
const prefix = plugin || service;
const timestampColor = colorizer.colorize(
"timestamp",
String(timestamp)
);
const prefixColor = colorizer.colorize("prefix", String(prefix));
const extraFields = Object.entries(fields).map(([key, value]) => {
let stringValue = "";
try {
stringValue = JSON.stringify(value);
} catch (e) {
stringValue = "[field value not castable to string]";
}
return `${colorizer.colorize("field", `${key}`)}=${stringValue}`;
}).join(" ");
return `${timestampColor} ${prefixColor} ${level} ${message} ${extraFields}`;
})
);
}
/**
* Formatter that filters log levels using overrides, falling back to the default level when no criteria match.
*/
static logLevelFilter(defaultLogLevel) {
const overrides = [];
return {
format: winston.format((log) => {
for (const override of overrides) {
if (override.predicate(log)) {
if (types.winstonLevels[log.level] > types.winstonLevels[override.level]) {
return false;
}
return log;
}
}
if (types.winstonLevels[log.level] > types.winstonLevels[defaultLogLevel]) {
return false;
}
return log;
})(),
setOverrides: (newOverrides) => {
const newOverridesPredicates = newOverrides.map((o) => ({
predicate: utils.createLogMatcher(o.matchers),
level: o.level
}));
overrides.splice(0, overrides.length, ...newOverridesPredicates);
}
};
}
constructor(winston, addRedactions, setLevelOverrides) {
this.#winston = winston;
this.#addRedactions = addRedactions;
this.#setLevelOverrides = setLevelOverrides;
}
error(message, meta) {
this.#winston.error(message, meta);
}
warn(message, meta) {
this.#winston.warn(message, meta);
}
info(message, meta) {
this.#winston.info(message, meta);
}
debug(message, meta) {
this.#winston.debug(message, meta);
}
child(meta) {
return new WinstonLogger(this.#winston.child(meta));
}
addRedactions(redactions) {
this.#addRedactions?.(redactions);
}
setLevelOverrides(overrides) {
this.#setLevelOverrides?.(overrides);
}
}
exports.WinstonLogger = WinstonLogger;
//# sourceMappingURL=WinstonLogger.cjs.js.map