1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

feat: Implement automatic Feature-specific prefixing for logging

Co-authored-by: Janne Savolainen <janne.savolainen@live.fi>
Signed-off-by: Iku-turso <mikko.aspiala@gmail.com>
This commit is contained in:
Iku-turso 2023-05-16 15:15:31 +03:00
parent 2e4aba735f
commit f9e5f9bf43
2 changed files with 89 additions and 10 deletions

View File

@ -2,9 +2,16 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable"; import { kebabCase, toUpper } from "lodash/fp";
import {
DiContainerForInjection,
getInjectable,
getInjectionToken,
lifecycleEnum,
} from "@ogre-tools/injectable";
import type { Logger } from "./logger"; import type { Logger } from "./logger";
import { winstonLoggerInjectable } from "./winston-logger.injectable"; import { winstonLoggerInjectable } from "./winston-logger.injectable";
import { pipeline } from "@ogre-tools/fp";
export const loggerInjectionToken = getInjectionToken<Logger>({ export const loggerInjectionToken = getInjectionToken<Logger>({
id: "logger-injection-token", id: "logger-injection-token",
@ -46,32 +53,64 @@ export const logSillyInjectionToken = getInjectionToken<LogFunction>({
id: "log-silly-injection-token", id: "log-silly-injection-token",
}); });
const screamingKebabCase = (str: string) => pipeline(str, kebabCase, toUpper);
const getLogFunctionFor =
(scenario: keyof Logger) =>
(di: DiContainerForInjection): LogFunction => {
const winstonLogger = di.inject(winstonLoggerInjectable);
return (message, ...data) => {
winstonLogger[scenario](
di.sourceNamespace
? `[${screamingKebabCase(di.sourceNamespace)}]: ${message}`
: message,
...data
);
};
};
export const logDebugInjectable = getInjectable({ export const logDebugInjectable = getInjectable({
id: "log-debug", id: "log-debug",
instantiate: (di): LogFunction => di.inject(winstonLoggerInjectable).debug, instantiate: getLogFunctionFor("debug"),
injectionToken: logDebugInjectionToken, injectionToken: logDebugInjectionToken,
lifecycle: lifecycleEnum.keyedSingleton({
getInstanceKey: (di) => di.sourceNamespace,
}),
}); });
export const logInfoInjectable = getInjectable({ export const logInfoInjectable = getInjectable({
id: "log-info", id: "log-info",
instantiate: (di): LogFunction => di.inject(winstonLoggerInjectable).info, instantiate: getLogFunctionFor("info"),
injectionToken: logInfoInjectionToken, injectionToken: logInfoInjectionToken,
lifecycle: lifecycleEnum.keyedSingleton({
getInstanceKey: (di) => di.sourceNamespace,
}),
}); });
export const logWarningInjectable = getInjectable({ export const logWarningInjectable = getInjectable({
id: "log-warning", id: "log-warning",
instantiate: (di): LogFunction => di.inject(winstonLoggerInjectable).warn, instantiate: getLogFunctionFor("warn"),
injectionToken: logWarningInjectionToken, injectionToken: logWarningInjectionToken,
lifecycle: lifecycleEnum.keyedSingleton({
getInstanceKey: (di) => di.sourceNamespace,
}),
}); });
export const logErrorInjectable = getInjectable({ export const logErrorInjectable = getInjectable({
id: "log-error", id: "log-error",
instantiate: (di): LogFunction => di.inject(winstonLoggerInjectable).error, instantiate: getLogFunctionFor("error"),
injectionToken: logErrorInjectionToken, injectionToken: logErrorInjectionToken,
lifecycle: lifecycleEnum.keyedSingleton({
getInstanceKey: (di) => di.sourceNamespace,
}),
}); });
export const logSillyInjectable = getInjectable({ export const logSillyInjectable = getInjectable({
id: "log-silly", id: "log-silly",
instantiate: (di): LogFunction => di.inject(winstonLoggerInjectable).silly, instantiate: getLogFunctionFor("silly"),
injectionToken: logSillyInjectionToken, injectionToken: logSillyInjectionToken,
lifecycle: lifecycleEnum.keyedSingleton({
getInstanceKey: (di) => di.sourceNamespace,
}),
}); });

View File

@ -1,13 +1,18 @@
import { createContainer } from "@ogre-tools/injectable"; import { createContainer, getInjectable } from "@ogre-tools/injectable";
import { registerFeature } from "@k8slens/feature-core"; import { registerFeature } from "@k8slens/feature-core";
import { loggerFeature } from "./feature"; import { loggerFeature } from "./feature";
import { winstonLoggerInjectable } from "./winston-logger.injectable"; import { winstonLoggerInjectable } from "./winston-logger.injectable";
import { import {
logDebugInjectionToken, logErrorInjectionToken, logDebugInjectionToken,
logErrorInjectionToken,
logInfoInjectionToken, logInfoInjectionToken,
logSillyInjectionToken, logWarningInjectionToken, logSillyInjectionToken,
logWarningInjectionToken,
} from "./logger.injectable"; } from "./logger.injectable";
import { getFeature } from "@k8slens/feature-core/src/feature";
describe("logger", () => { describe("logger", () => {
[ [
{ scenario: "debug", injectionToken: logDebugInjectionToken }, { scenario: "debug", injectionToken: logDebugInjectionToken },
@ -16,7 +21,7 @@ describe("logger", () => {
{ scenario: "error", injectionToken: logErrorInjectionToken }, { scenario: "error", injectionToken: logErrorInjectionToken },
{ scenario: "silly", injectionToken: logSillyInjectionToken }, { scenario: "silly", injectionToken: logSillyInjectionToken },
].forEach(({ scenario, injectionToken }) => { ].forEach(({ scenario, injectionToken }) => {
it(`when logging "${scenario}", does so`, () => { it(`given not inside a Feature, when logging "${scenario}", does so without a prefix`, () => {
const di = createContainer("irrelevant"); const di = createContainer("irrelevant");
registerFeature(di, loggerFeature); registerFeature(di, loggerFeature);
@ -34,5 +39,40 @@ describe("logger", () => {
"some-data" "some-data"
); );
}); });
it(`given inside a Feature, when logging "${scenario}", does so with Feature's id as prefix`, () => {
const di = createContainer("irrelevant");
const logScenarioInFeature = getInjectable({
id: "some-functionality",
instantiate: (di) => di.inject(injectionToken),
});
const someFeature = getFeature({
id: "some-feature",
register: (di) => {
di.register(logScenarioInFeature);
},
dependencies: [loggerFeature],
});
registerFeature(di, someFeature);
const winstonLoggerStub = { [scenario]: jest.fn() } as any;
di.override(winstonLoggerInjectable, () => winstonLoggerStub);
const logScenario = di.inject(logScenarioInFeature);
logScenario("some-message", "some-data");
expect(winstonLoggerStub[scenario]).toHaveBeenCalledWith(
"[SOME-FEATURE]: some-message",
"some-data"
);
});
}); });
}); });