@backstage/backend-defaults
Version:
Backend defaults used by Backstage backend apps
124 lines (120 loc) • 3.8 kB
JavaScript
;
var winston = require('winston');
var tripleBeam = require('triple-beam');
var escapeRegExp = require('../../lib/escapeRegExp.cjs.js');
class WinstonLogger {
#winston;
#addRedactions;
/**
* Creates a {@link WinstonLogger} instance.
*/
static create(options) {
const redacter = WinstonLogger.redacter();
const defaultFormatter = process.env.NODE_ENV === "production" ? winston.format.json() : WinstonLogger.colorFormat();
let logger = winston.createLogger({
level: process.env.LOG_LEVEL || options.level || "info",
format: winston.format.combine(
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);
}
/**
* 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;
}
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", timestamp);
const prefixColor = colorizer.colorize("prefix", 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}`;
})
);
}
constructor(winston, addRedactions) {
this.#winston = winston;
this.#addRedactions = addRedactions;
}
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);
}
}
exports.WinstonLogger = WinstonLogger;
//# sourceMappingURL=WinstonLogger.cjs.js.map