From 85cf82e79d924a943944bcb6cd8298829af8544d Mon Sep 17 00:00:00 2001
From: Hasan Awad <90554456+hasanwhitesource@users.noreply.github.com>
Date: Mon, 7 Feb 2022 10:44:44 +0200
Subject: [PATCH] fix(logging): Added check for log level value (#13941)

---
 lib/logger/index.ts      |  6 +++++-
 lib/logger/utils.spec.ts | 33 +++++++++++++++++++++++++++++++++
 lib/logger/utils.ts      | 37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 lib/logger/utils.spec.ts

diff --git a/lib/logger/index.ts b/lib/logger/index.ts
index 66f91378fd..ceee032d87 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<string, unknown> = {};
 
 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 0000000000..ad2af427f9
--- /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 cb0de0a395..8d290268d0 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);
+}
-- 
GitLab