From 42b448b0e5f7d3fc3ff12bf8d00ab95710f60a03 Mon Sep 17 00:00:00 2001 From: Michael Kriese Date: Wed, 13 Nov 2024 18:58:19 +0100 Subject: [PATCH] feat(logger): prefix log env settings with `RENOVATE_` (#32499) Co-authored-by: Rhys Arkins --- lib/logger/index.spec.ts | 3 ++ lib/logger/index.ts | 48 ++++++++++++++++++++++---------- lib/logger/utils.ts | 6 ++++ lib/workers/global/index.spec.ts | 1 + lib/workers/global/index.ts | 7 ++--- 5 files changed, 46 insertions(+), 19 deletions(-) diff --git a/lib/logger/index.spec.ts b/lib/logger/index.spec.ts index 3fa2fbd10aa2e1..a2eb3e3beb19c3 100644 --- a/lib/logger/index.spec.ts +++ b/lib/logger/index.spec.ts @@ -10,6 +10,7 @@ import { getContext, getProblems, levels, + logLevel, logger, removeMeta, setContext, @@ -53,7 +54,9 @@ describe('logger/index', () => { }); it('sets level', () => { + expect(logLevel()).toBeDefined(); // depends on passed env expect(() => levels('stdout', 'debug')).not.toThrow(); + expect(logLevel()).toBe('debug'); }); it('saves problems', () => { diff --git a/lib/logger/index.ts b/lib/logger/index.ts index 504e9b1a2c97e8..f066e05f97b22e 100644 --- a/lib/logger/index.ts +++ b/lib/logger/index.ts @@ -10,26 +10,31 @@ import { once, reset as onceReset } from './once'; import { RenovateStream } from './pretty-stdout'; import { getRemappedLevel } from './remap'; import type { BunyanRecord, Logger } from './types'; -import { ProblemStream, validateLogLevel, withSanitizer } from './utils'; - -let logContext: string = process.env.LOG_CONTEXT ?? nanoid(); +import { + ProblemStream, + getEnv, + validateLogLevel, + withSanitizer, +} from './utils'; + +let logContext: string = getEnv('LOG_CONTEXT') ?? nanoid(); let curMeta: Record = {}; const problems = new ProblemStream(); -// istanbul ignore if: not easily testable -if (is.string(process.env.LOG_LEVEL)) { - process.env.LOG_LEVEL = process.env.LOG_LEVEL.toLowerCase().trim(); -} - +let stdoutLevel = validateLogLevel(getEnv('LOG_LEVEL'), 'info'); const stdout: bunyan.Stream = { name: 'stdout', - level: validateLogLevel(process.env.LOG_LEVEL, 'info'), + level: stdoutLevel, stream: process.stdout, }; +export function logLevel(): bunyan.LogLevelString { + return stdoutLevel; +} + // istanbul ignore if: not testable -if (process.env.LOG_FORMAT !== 'json') { +if (getEnv('LOG_FORMAT') !== 'json') { // TODO: typings (#9615) const prettyStdOut = new RenovateStream() as any; prettyStdOut.pipe(process.stdout); @@ -122,16 +127,17 @@ loggerLevels.forEach((loggerLevel) => { logger.once[loggerLevel] = logOnceFn as never; }); +const logFile = getEnv('LOG_FILE'); // istanbul ignore if: not easily testable -if (is.string(process.env.LOG_FILE)) { +if (is.string(logFile)) { // ensure log file directory exists - const directoryName = upath.dirname(process.env.LOG_FILE); + const directoryName = upath.dirname(logFile); fs.ensureDirSync(directoryName); addStream({ name: 'logfile', - path: process.env.LOG_FILE, - level: validateLogLevel(process.env.LOG_FILE_LEVEL, 'debug'), + path: logFile, + level: validateLogLevel(getEnv('LOG_FILE_LEVEL'), 'debug'), }); } @@ -168,8 +174,20 @@ export /* istanbul ignore next */ function addStream( bunyanLogger.addStream(withSanitizer(stream)); } -export function levels(name: string, level: bunyan.LogLevel): void { +/** + * For testing purposes only + * @param name stream name + * @param level log level + * @private + */ +export function levels( + name: 'stdout' | 'logfile', + level: bunyan.LogLevelString, +): void { bunyanLogger.levels(name, level); + if (name === 'stdout') { + stdoutLevel = level; + } } export function getProblems(): BunyanRecord[] { diff --git a/lib/logger/utils.ts b/lib/logger/utils.ts index f04c0f8132ad9e..5b2d512601ac71 100644 --- a/lib/logger/utils.ts +++ b/lib/logger/utils.ts @@ -333,3 +333,9 @@ export function sanitizeUrls(text: string): string { }) .replace(dataUriCredRe, '$1**redacted**'); } + +export function getEnv(key: string): string | undefined { + return [process.env[`RENOVATE_${key}`], process.env[key]] + .map((v) => v?.toLowerCase().trim()) + .find(is.nonEmptyStringAndNotWhitespace); +} diff --git a/lib/workers/global/index.spec.ts b/lib/workers/global/index.spec.ts index dd9c31464eb07b..9348676f0d5322 100644 --- a/lib/workers/global/index.spec.ts +++ b/lib/workers/global/index.spec.ts @@ -43,6 +43,7 @@ const initPlatform = jest.spyOn(platform, 'initPlatform'); describe('workers/global/index', () => { beforeEach(() => { logger.getProblems.mockImplementation(() => []); + logger.logLevel.mockImplementation(() => 'info'); initPlatform.mockImplementation((input) => Promise.resolve(input)); delete process.env.AWS_SECRET_ACCESS_KEY; delete process.env.AWS_SESSION_TOKEN; diff --git a/lib/workers/global/index.ts b/lib/workers/global/index.ts index fd233ecb61a81f..0ef5d1c870d29f 100644 --- a/lib/workers/global/index.ts +++ b/lib/workers/global/index.ts @@ -17,7 +17,7 @@ import { CONFIG_PRESETS_INVALID } from '../../constants/error-messages'; import { pkg } from '../../expose.cjs'; import { instrument } from '../../instrumentation'; import { exportStats, finalizeReport } from '../../instrumentation/reporting'; -import { getProblems, logger, setMeta } from '../../logger'; +import { getProblems, logLevel, logger, setMeta } from '../../logger'; import { setGlobalLogLevelRemaps } from '../../logger/remap'; import * as hostRules from '../../util/host-rules'; import * as queue from '../../util/http/queue'; @@ -228,10 +228,9 @@ export async function start(): Promise { } } finally { await globalFinalize(config!); - const logLevel = process.env.LOG_LEVEL ?? 'info'; - if (logLevel === 'info') { + if (logLevel() === 'info') { logger.info( - `Renovate was run at log level "${logLevel}". Set LOG_LEVEL=debug in environment variables to see extended debug logs.`, + `Renovate was run at log level "${logLevel()}". Set LOG_LEVEL=debug in environment variables to see extended debug logs.`, ); } }