diff --git a/lib/logger/index.ts b/lib/logger/index.ts index 66f91378fdc236..ceee032d872cf8 100644 --- a/lib/logger/index.ts +++ b/lib/logger/index.ts @@ -6,13 +6,17 @@ import configSerializer from './config-serializer'; import errSerializer from './err-serializer'; import { RenovateStream } from './pretty-stdout'; import type { BunyanRecord, Logger } from './types'; -import { ProblemStream, withSanitizer } from './utils'; +import { ProblemStream, validateLogLevel, withSanitizer } from './utils'; let logContext: string = process.env.LOG_CONTEXT ?? nanoid(); let curMeta: Record = {}; const problems = new ProblemStream(); +if (is.string(process.env.LOG_LEVEL)) { + process.env.LOG_LEVEL = process.env.LOG_LEVEL.toLowerCase().trim(); +} +validateLogLevel(process.env.LOG_LEVEL); const stdout: bunyan.Stream = { name: 'stdout', level: diff --git a/lib/logger/utils.spec.ts b/lib/logger/utils.spec.ts new file mode 100644 index 00000000000000..ad2af427f99881 --- /dev/null +++ b/lib/logger/utils.spec.ts @@ -0,0 +1,33 @@ +import { validateLogLevel } from './utils'; + +describe('logger/utils', () => { + afterEach(() => { + jest.restoreAllMocks(); + }); + + it('checks for valid log levels', () => { + expect(validateLogLevel(undefined)).toBeUndefined(); + expect(validateLogLevel('warn')).toBeUndefined(); + expect(validateLogLevel('debug')).toBeUndefined(); + expect(validateLogLevel('trace')).toBeUndefined(); + expect(validateLogLevel('info')).toBeUndefined(); + }); + + it.each` + input + ${'warning'} + ${'100'} + ${''} + ${' '} + `('checks for invalid log level: $input', (input) => { + // Mock when the function exits + const mockExit = jest.spyOn(process, 'exit'); + mockExit.mockImplementationOnce((number) => { + throw new Error(`process.exit: ${number}`); + }); + expect(() => { + validateLogLevel(input); + }).toThrow(); + expect(mockExit).toHaveBeenCalledWith(1); + }); +}); diff --git a/lib/logger/utils.ts b/lib/logger/utils.ts index cb0de0a395ba7d..8d290268d02e6c 100644 --- a/lib/logger/utils.ts +++ b/lib/logger/utils.ts @@ -206,3 +206,40 @@ export function withSanitizer(streamConfig: bunyan.Stream): bunyan.Stream { throw new Error("Missing 'stream' or 'path' for bunyan stream"); } + +/** + * A function that terminates exeution if the log level that was entered is + * not a valid value for the Bunyan logger. + * @param logLevelToCheck + * @returns returns undefined when the logLevelToCheck is valid. Else it stops execution. + */ +export function validateLogLevel(logLevelToCheck: string | undefined): void { + const allowedValues: bunyan.LogLevel[] = [ + 'trace', + 'debug', + 'info', + 'warn', + 'error', + 'fatal', + ]; + if ( + is.undefined(logLevelToCheck) || + (is.string(logLevelToCheck) && + allowedValues.includes(logLevelToCheck as bunyan.LogLevel)) + ) { + // log level is in the allowed values or its undefined + return; + } + + const logger = bunyan.createLogger({ + name: 'renovate', + streams: [ + { + level: 'fatal', + stream: process.stdout, + }, + ], + }); + logger.fatal(`${logLevelToCheck} is not a valid log level. terminating...`); + process.exit(1); +}