backend-common: lazy root logger initialization

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-09-18 11:12:22 +02:00
parent 7f3adafa14
commit fd3fdd0e33
3 changed files with 58 additions and 8 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-common': patch
---
The root logger is now initialized lazily, fixing a circular dependency issue with `@backstage/backend-app-api` that would result in `Cannot read properties of undefined (reading 'redacter')`.
@@ -17,12 +17,26 @@
import { WinstonLogger } from '@backstage/backend-app-api';
import { merge } from 'lodash';
import * as winston from 'winston';
import { LoggerOptions } from 'winston';
import { format, LoggerOptions } from 'winston';
import { setRootLogger } from './globalLoggers';
import { TransformableInfo } from 'logform';
const redacter = WinstonLogger.redacter();
const getRedacter = (() => {
let redacter: ReturnType<typeof WinstonLogger.redacter> | undefined =
undefined;
return () => {
if (!redacter) {
redacter = WinstonLogger.redacter();
}
return redacter;
};
})();
export const setRootLoggerRedactionList = redacter.add;
export const setRootLoggerRedactionList = (
redactions: Iterable<string>,
): void => {
getRedacter().add(redactions);
};
/**
* A winston formatting function that finds occurrences of filteredKeys
@@ -33,15 +47,44 @@ export const setRootLoggerRedactionList = redacter.add;
export function redactWinstonLogLine(
info: winston.Logform.TransformableInfo,
): winston.Logform.TransformableInfo {
return redacter.format.transform(info) as winston.Logform.TransformableInfo;
return getRedacter().format.transform(
info,
) as winston.Logform.TransformableInfo;
}
const colorizer = format.colorize();
// NOTE: This is a copy of the WinstonLogger.colorFormat to avoid a circular dependency
/**
* Creates a pretty printed winston log formatter.
*
* @public
*/
export const coloredFormat = WinstonLogger.colorFormat();
export const coloredFormat = format.combine(
format.timestamp(),
format.colorize({
colors: {
timestamp: 'dim',
prefix: 'blue',
field: 'cyan',
debug: 'grey',
},
}),
format.printf((info: TransformableInfo) => {
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]) => `${colorizer.colorize('field', `${key}`)}=${value}`,
)
.join(' ');
return `${timestampColor} ${prefixColor} ${level} ${message} ${extraFields}`;
}),
);
/**
* Creates a default "root" logger. This also calls {@link setRootLogger} under
@@ -64,7 +107,7 @@ export function createRootLogger(
{
level: env.LOG_LEVEL || 'info',
format: winston.format.combine(
redacter.format,
getRedacter().format,
env.NODE_ENV === 'production'
? winston.format.json()
: WinstonLogger.colorFormat(),
@@ -84,5 +127,3 @@ export function createRootLogger(
return logger;
}
setRootLogger(createRootLogger());
@@ -15,6 +15,7 @@
*/
import * as winston from 'winston';
import { createRootLogger } from './createRootLogger';
/**
* A logger that just throws away all messages.
@@ -35,6 +36,9 @@ let rootLogger: winston.Logger;
* @public
*/
export function getRootLogger(): winston.Logger {
if (!rootLogger) {
rootLogger = createRootLogger();
}
return rootLogger;
}