Skip to content

Commit 8c26a4c

Browse files
authored
Fb/env log level (#29)
* env log level 1 * env log level 2 * env log level 3 * go with undefined and null as states for Logger.__envMaxLevelNumber * remove unused variable
1 parent bfbd6ae commit 8c26a4c

File tree

3 files changed

+79
-13
lines changed

3 files changed

+79
-13
lines changed

src/logger.js

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const util = require("util");
33
const VError = require("verror");
44

55
const { cfEnv } = require("./env");
6-
const { tryRequire } = require("./shared/static");
6+
const { ENV, tryRequire } = require("./shared/static");
77
const cds = tryRequire("@sap/cds");
88

99
// NOTE: logger levels are tricky. looking at console, npm, winston, and cap there is no real consistency. we will
@@ -87,6 +87,24 @@ const cfAppData = cfEnv.isOnCf
8787
: undefined;
8888

8989
class Logger {
90+
static get envMaxLevelNumber() {
91+
if (Logger.__envMaxLevelNumber === undefined) {
92+
Logger.__envMaxLevelNumber = null;
93+
let envLogLevel = process.env[ENV.LOG_LEVEL]?.trim().toUpperCase();
94+
if (envLogLevel) {
95+
const level = Object.values(LEVEL).find((level) => level.startsWith(envLogLevel));
96+
if (level) {
97+
Logger.__envMaxLevelNumber = LEVEL_NUMBER[level];
98+
}
99+
}
100+
}
101+
return Logger.__envMaxLevelNumber;
102+
}
103+
104+
static _reset() {
105+
Reflect.deleteProperty(Logger, "__envMaxLevelNumber");
106+
}
107+
90108
constructor(
91109
layer = undefined,
92110
{
@@ -119,7 +137,6 @@ class Logger {
119137

120138
_logData(level, args) {
121139
let message;
122-
let invocationErrorData;
123140
if (args.length > 0) {
124141
const firstArg = args[0];
125142

@@ -165,15 +182,7 @@ class Logger {
165182
[FIELD.WRITTEN_TIME]: nowNanos,
166183
[FIELD.MESSAGE]: message ?? "",
167184
};
168-
return Object.assign(
169-
{},
170-
cfAppData,
171-
...this.__dataList,
172-
invocationErrorData,
173-
invocationData,
174-
this.__baseData,
175-
cdsData
176-
);
185+
return Object.assign({}, cfAppData, ...this.__dataList, invocationData, this.__baseData, cdsData);
177186
}
178187

179188
static _readableOutput(data) {
@@ -193,7 +202,13 @@ class Logger {
193202
}
194203

195204
_log(level, args) {
196-
if (this.__maxLevelNumber < LEVEL_NUMBER[level]) {
205+
const levelNumber = LEVEL_NUMBER[level];
206+
if (
207+
(Logger.envMaxLevelNumber !== undefined &&
208+
Logger.envMaxLevelNumber !== null &&
209+
Logger.envMaxLevelNumber < levelNumber) ||
210+
this.__maxLevelNumber < levelNumber
211+
) {
197212
return;
198213
}
199214
const streamOut = level === LEVEL.ERROR ? process.stderr : process.stdout;

src/shared/static.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const ENV = Object.freeze({
1010
UNIQUE_NAME: "BTP_FEATURES_UNIQUE_NAME",
1111
REDIS_KEY: "BTP_FEATURES_REDIS_KEY",
1212
REDIS_CHANNEL: "BTP_FEATURES_REDIS_CHANNEL",
13+
LOG_LEVEL: "BTP_FEATURES_LOG_LEVEL",
1314
});
1415

1516
const isNull = (...args) => args.reduce((result, arg) => result || arg === undefined || arg === null, false);

test/logger.test.js

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
const VError = require("verror");
44
const featureTogglesModule = require("../src/featureToggles");
55
const { FeatureToggles } = featureTogglesModule;
6-
const { FORMAT, Logger } = require("../src/logger");
6+
const { ENV } = require("../src/shared/static");
7+
const { LEVEL, FORMAT, Logger } = require("../src/logger");
78

89
const redisWrapperMock = require("../src/redisWrapper");
910
jest.mock("../src/redisWrapper", () => require("./__mocks__/redisWrapper"));
@@ -57,6 +58,7 @@ let layer = "/test";
5758

5859
describe("logger test", () => {
5960
beforeEach(() => {
61+
Logger._reset();
6062
redisWrapperMock._reset();
6163
envMock._reset();
6264
featureToggles = new FeatureToggles({ redisKey, redisChannel, refreshMessage });
@@ -181,6 +183,54 @@ caused by: Error: bad validator
181183
expect(processStreamSpy.stdout.mock.calls.length).toBe(1);
182184
});
183185

186+
it("make sure env log level WARN is respected", async () => {
187+
process.env[ENV.LOG_LEVEL] = " warn ";
188+
logger = new Logger(layer, { maxLevel: LEVEL.TRACE });
189+
logger.trace("some trace");
190+
logger.debug("some debug");
191+
logger.info("some info");
192+
expect(processStreamSpy.stdout.mock.calls.length).toBe(0);
193+
expect(processStreamSpy.stderr.mock.calls.length).toBe(0);
194+
logger.warning("some warning");
195+
expect(processStreamSpy.stdout.mock.calls.map(cleanupTextLogCalls)[0]).toMatchInlineSnapshot(`
196+
[
197+
"88:88:88.888 | WARN | /test | some warning",
198+
]
199+
`);
200+
expect(processStreamSpy.stdout.mock.calls.length).toBe(1);
201+
expect(processStreamSpy.stderr.mock.calls.length).toBe(0);
202+
processStreamSpy.stdout.mockClear();
203+
logger.error("some error");
204+
expect(processStreamSpy.stderr.mock.calls.map(cleanupTextLogCalls)[0]).toMatchInlineSnapshot(`
205+
[
206+
"88:88:88.888 | ERROR | /test | some error",
207+
]
208+
`);
209+
expect(processStreamSpy.stdout.mock.calls.length).toBe(0);
210+
expect(processStreamSpy.stderr.mock.calls.length).toBe(1);
211+
Reflect.deleteProperty(process.env, ENV.LOG_LEVEL);
212+
});
213+
214+
it("make sure env log level ERROR is respected", async () => {
215+
process.env[ENV.LOG_LEVEL] = " err ";
216+
logger = new Logger(layer, { maxLevel: LEVEL.TRACE });
217+
logger.trace("some trace");
218+
logger.debug("some debug");
219+
logger.info("some info");
220+
logger.warning("some warning");
221+
expect(processStreamSpy.stdout.mock.calls.length).toBe(0);
222+
expect(processStreamSpy.stderr.mock.calls.length).toBe(0);
223+
logger.error("some error");
224+
expect(processStreamSpy.stderr.mock.calls.map(cleanupTextLogCalls)[0]).toMatchInlineSnapshot(`
225+
[
226+
"88:88:88.888 | ERROR | /test | some error",
227+
]
228+
`);
229+
expect(processStreamSpy.stdout.mock.calls.length).toBe(0);
230+
expect(processStreamSpy.stderr.mock.calls.length).toBe(1);
231+
Reflect.deleteProperty(process.env, ENV.LOG_LEVEL);
232+
});
233+
184234
it("error basic usage", async () => {
185235
logger = new Logger(layer, { format: FORMAT.JSON });
186236
logger.error(new VError("bla error"));

0 commit comments

Comments
 (0)