-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Renderer file logging through IPC (#7300)
* Renderer file logging through IPC Signed-off-by: Sami Tiilikainen <97873007+samitiilikainen@users.noreply.github.com> * Remove pagehide event listener as it may cause UI to freeze Pagehide was needed in cluster frame to better handle main frame close/reload situation. But even empty pagehide listener in cluster frame seems to freeze the UI at least on some situations (multiple clusters open). Beforeunload is not always executed in cluster frame when main frame is reloaded/closed, leaving log files open. To fix that, `stopIpcLoggingInjectable` is introduced to close all log files. Signed-off-by: Sami Tiilikainen <97873007+samitiilikainen@users.noreply.github.com> * Remove unnecessary formatting changes Signed-off-by: Sami Tiilikainen <97873007+samitiilikainen@users.noreply.github.com> * Lint fix Signed-off-by: Sami Tiilikainen <97873007+samitiilikainen@users.noreply.github.com> * Winston logger override Signed-off-by: Sami Tiilikainen <97873007+samitiilikainen@users.noreply.github.com> * Remove usage of doGeneralOverrides as it has been removed Signed-off-by: Sami Tiilikainen <97873007+samitiilikainen@users.noreply.github.com> * Update imports to match the new base Signed-off-by: Sami Tiilikainen <97873007+samitiilikainen@users.noreply.github.com> * Remove unnecessary id Signed-off-by: Sami Tiilikainen <97873007+samitiilikainen@users.noreply.github.com> * Review improvements Signed-off-by: Sami Tiilikainen <97873007+samitiilikainen@users.noreply.github.com> * Extract beforeunload listener to injectable Signed-off-by: Sami Tiilikainen <97873007+samitiilikainen@users.noreply.github.com> * Typo fix Signed-off-by: Sami Tiilikainen <97873007+samitiilikainen@users.noreply.github.com> --------- Signed-off-by: Sami Tiilikainen <97873007+samitiilikainen@users.noreply.github.com>
- Loading branch information
1 parent
517e2fe
commit 48db54e
Showing
24 changed files
with
832 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
packages/core/src/common/logger/ipc-file-logger-channel.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token"; | ||
|
||
export interface IpcFileLogObject { | ||
fileId: string; | ||
entry: { | ||
level: string; | ||
message: string; | ||
internalMessage: string; | ||
}; | ||
} | ||
|
||
export type IpcFileLoggerChannel = MessageChannel<IpcFileLogObject>; | ||
|
||
export const ipcFileLoggerChannel: IpcFileLoggerChannel = { | ||
id: "ipc-file-logger-channel", | ||
}; | ||
|
||
export const closeIpcFileLoggerChannel: MessageChannel<string> = { | ||
id: "close-ipc-file-logger-channel", | ||
}; |
23 changes: 23 additions & 0 deletions
23
packages/core/src/common/winston-logger.global-override-for-injectable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
|
||
import type winston from "winston"; | ||
import { getGlobalOverride } from "@k8slens/test-utils"; | ||
import { noop } from "@k8slens/utilities"; | ||
import winstonLoggerInjectable from "./winston-logger.injectable"; | ||
|
||
export default getGlobalOverride(winstonLoggerInjectable, () => ({ | ||
log: noop, | ||
add: noop, | ||
remove: noop, | ||
clear: noop, | ||
close: noop, | ||
|
||
warn: noop, | ||
debug: noop, | ||
error: noop, | ||
info: noop, | ||
silly: noop, | ||
}) as winston.Logger); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
import { getInjectable } from "@ogre-tools/injectable"; | ||
import { createLogger, format } from "winston"; | ||
import { loggerTransportInjectionToken } from "./logger/transports"; | ||
|
||
const winstonLoggerInjectable = getInjectable({ | ||
id: "winston-logger", | ||
instantiate: (di) => | ||
createLogger({ | ||
format: format.combine(format.splat(), format.simple()), | ||
transports: di.injectMany(loggerTransportInjectionToken), | ||
}), | ||
}); | ||
|
||
export default winstonLoggerInjectable; |
21 changes: 21 additions & 0 deletions
21
packages/core/src/main/logger/close-ipc-logging-listener.injectable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
import ipcFileLoggerInjectable from "./ipc-file-logger.injectable"; | ||
import { getMessageChannelListenerInjectable } from "../../common/utils/channel/message-channel-listener-injection-token"; | ||
import { | ||
closeIpcFileLoggerChannel, | ||
} from "../../common/logger/ipc-file-logger-channel"; | ||
|
||
const closeIpcFileLoggingListenerInjectable = getMessageChannelListenerInjectable({ | ||
id: "close-ipc-file-logging", | ||
channel: closeIpcFileLoggerChannel, | ||
handler: (di) => { | ||
const ipcFileLogger = di.inject(ipcFileLoggerInjectable); | ||
|
||
return (fileId) => ipcFileLogger.close(fileId); | ||
}, | ||
}); | ||
|
||
export default closeIpcFileLoggingListenerInjectable; |
18 changes: 18 additions & 0 deletions
18
packages/core/src/main/logger/create-ipc-file-transport.global-override-for-injectable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
|
||
import type { transports } from "winston"; | ||
import { getGlobalOverride } from "@k8slens/test-utils"; | ||
import { noop } from "@k8slens/utilities"; | ||
import createIpcFileLoggerTransportInjectable from "./create-ipc-file-transport.injectable"; | ||
|
||
export default getGlobalOverride( | ||
createIpcFileLoggerTransportInjectable, | ||
() => () => | ||
({ | ||
log: noop, | ||
close: noop, | ||
} as typeof transports.File), | ||
); |
28 changes: 28 additions & 0 deletions
28
packages/core/src/main/logger/create-ipc-file-transport.injectable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
import { getInjectable } from "@ogre-tools/injectable"; | ||
import { transports } from "winston"; | ||
import directoryForLogsInjectable from "../../common/app-paths/directory-for-logs.injectable"; | ||
|
||
const createIpcFileLoggerTransportInjectable = getInjectable({ | ||
id: "create-ipc-file-logger-transport", | ||
instantiate: (di) => { | ||
const options = { | ||
dirname: di.inject(directoryForLogsInjectable), | ||
maxsize: 1024 * 1024, | ||
maxFiles: 2, | ||
tailable: true, | ||
}; | ||
|
||
return (fileId: string) => | ||
new transports.File({ | ||
...options, | ||
filename: `lens-${fileId}.log`, | ||
}); | ||
}, | ||
causesSideEffects: true, | ||
}); | ||
|
||
export default createIpcFileLoggerTransportInjectable; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
packages/core/src/main/logger/ipc-file-logger.injectable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
import { getInjectable } from "@ogre-tools/injectable"; | ||
import { getOrInsertWith } from "@k8slens/utilities"; | ||
import type { LogEntry, transports } from "winston"; | ||
import createIpcFileLoggerTransportInjectable from "./create-ipc-file-transport.injectable"; | ||
|
||
export interface IpcFileLogger { | ||
log: (fileLog: { fileId: string; entry: LogEntry }) => void; | ||
close: (fileId: string) => void; | ||
closeAll: () => void; | ||
} | ||
|
||
const ipcFileLoggerInjectable = getInjectable({ | ||
id: "ipc-file-logger", | ||
instantiate: (di): IpcFileLogger => { | ||
const createIpcFileTransport = di.inject(createIpcFileLoggerTransportInjectable); | ||
const fileTransports = new Map<string, transports.FileTransportInstance>(); | ||
|
||
function log({ fileId, entry }: { fileId: string; entry: LogEntry }) { | ||
const transport = getOrInsertWith( | ||
fileTransports, | ||
fileId, | ||
() => createIpcFileTransport(fileId), | ||
); | ||
|
||
transport?.log?.(entry, () => {}); | ||
} | ||
|
||
function close(fileId: string) { | ||
const transport = fileTransports.get(fileId); | ||
|
||
if (transport) { | ||
transport.close?.(); | ||
fileTransports.delete(fileId); | ||
} | ||
} | ||
|
||
function closeAll() { | ||
for (const fileId of fileTransports.keys()) { | ||
close(fileId); | ||
} | ||
} | ||
|
||
return { | ||
log, | ||
close, | ||
closeAll, | ||
}; | ||
}, | ||
}); | ||
|
||
export default ipcFileLoggerInjectable; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
/** | ||
* Copyright (c) OpenLens Authors. All rights reserved. | ||
* Licensed under MIT License. See LICENSE in root directory for more information. | ||
*/ | ||
import { getDiForUnitTesting } from "../getDiForUnitTesting"; | ||
import createIpcFileLoggerTransportInjectable from "./create-ipc-file-transport.injectable"; | ||
import type { IpcFileLogger } from "./ipc-file-logger.injectable"; | ||
import ipcFileLoggerInjectable from "./ipc-file-logger.injectable"; | ||
|
||
describe("ipc file logger in main", () => { | ||
let logMock: jest.Mock; | ||
let closeMock: jest.Mock; | ||
let createFileTransportMock: jest.Mock; | ||
let logger: IpcFileLogger; | ||
|
||
beforeEach(() => { | ||
logMock = jest.fn(); | ||
closeMock = jest.fn(); | ||
createFileTransportMock = jest.fn(() => ({ | ||
log: logMock, | ||
close: closeMock, | ||
})); | ||
|
||
const di = getDiForUnitTesting(); | ||
|
||
di.override(createIpcFileLoggerTransportInjectable, () => createFileTransportMock); | ||
logger = di.inject(ipcFileLoggerInjectable); | ||
}); | ||
|
||
it("creates a transport for new log file", () => { | ||
logger.log({ | ||
fileId: "some-log-file", | ||
entry: { level: "irrelevant", message: "irrelevant" }, | ||
}); | ||
|
||
expect(createFileTransportMock).toHaveBeenCalledWith("some-log-file"); | ||
}); | ||
|
||
it("uses existing transport for log file", () => { | ||
logger.log({ | ||
fileId: "some-log-file", | ||
entry: { level: "irrelevant", message: "irrelevant" }, | ||
}); | ||
|
||
logger.log({ | ||
fileId: "some-log-file", | ||
entry: { level: "irrelevant", message: "irrelevant" }, | ||
}); | ||
|
||
logger.log({ | ||
fileId: "some-log-file", | ||
entry: { level: "irrelevant", message: "irrelevant" }, | ||
}); | ||
|
||
expect(createFileTransportMock).toHaveBeenCalledTimes(1); | ||
|
||
expect(createFileTransportMock).toHaveBeenCalledWith("some-log-file"); | ||
}); | ||
|
||
it("creates separate transport for each log file", () => { | ||
logger.log({ | ||
fileId: "some-log-file", | ||
entry: { level: "irrelevant", message: "irrelevant" }, | ||
}); | ||
|
||
logger.log({ | ||
fileId: "some-other-log-file", | ||
entry: { level: "irrelevant", message: "irrelevant" }, | ||
}); | ||
|
||
logger.log({ | ||
fileId: "some-yet-another-log-file", | ||
entry: { level: "irrelevant", message: "irrelevant" }, | ||
}); | ||
|
||
expect(createFileTransportMock).toHaveBeenCalledTimes(3); | ||
|
||
expect(createFileTransportMock).toHaveBeenCalledWith("some-log-file"); | ||
|
||
expect(createFileTransportMock).toHaveBeenCalledWith("some-other-log-file"); | ||
|
||
expect(createFileTransportMock).toHaveBeenCalledWith("some-yet-another-log-file"); | ||
}); | ||
|
||
it("logs using file transport", () => { | ||
logger.log({ | ||
fileId: "some-log-file", | ||
entry: { level: "irrelevant", message: "some-log-message" }, | ||
}); | ||
expect(logMock.mock.calls[0][0]).toEqual({ | ||
level: "irrelevant", | ||
message: "some-log-message", | ||
}); | ||
}); | ||
|
||
it("logs to correct files", () => { | ||
const someLogMock = jest.fn(); | ||
const someOthertLogMock = jest.fn(); | ||
|
||
createFileTransportMock.mockImplementation((fileId: string) => { | ||
if (fileId === "some-log-file") { | ||
return { log: someLogMock }; | ||
} | ||
|
||
if (fileId === "some-other-log-file") { | ||
return { log: someOthertLogMock }; | ||
} | ||
|
||
return null; | ||
}); | ||
|
||
logger.log({ | ||
fileId: "some-log-file", | ||
entry: { level: "irrelevant", message: "some-log-message" }, | ||
}); | ||
logger.log({ | ||
fileId: "some-other-log-file", | ||
entry: { level: "irrelevant", message: "some-other-log-message" }, | ||
}); | ||
|
||
expect(someLogMock).toHaveBeenCalledTimes(1); | ||
expect(someLogMock.mock.calls[0][0]).toEqual({ | ||
level: "irrelevant", | ||
message: "some-log-message", | ||
}); | ||
expect(someOthertLogMock).toHaveBeenCalledTimes(1); | ||
expect(someOthertLogMock.mock.calls[0][0]).toEqual({ | ||
level: "irrelevant", | ||
message: "some-other-log-message", | ||
}); | ||
}); | ||
|
||
it("closes transport (to ensure no file handles are left open)", () => { | ||
logger.log({ | ||
fileId: "some-log-file", | ||
entry: { level: "irrelevant", message: "irrelevant" }, | ||
}); | ||
|
||
logger.close("some-log-file"); | ||
|
||
expect(closeMock).toHaveBeenCalled(); | ||
}); | ||
|
||
it("creates a new transport once needed after closing previous", () => { | ||
logger.log({ | ||
fileId: "some-log-file", | ||
entry: { level: "irrelevant", message: "irrelevant" }, | ||
}); | ||
|
||
logger.close("some-log-file"); | ||
|
||
logger.log({ | ||
fileId: "some-log-file", | ||
entry: { level: "irrelevant", message: "irrelevant" }, | ||
}); | ||
|
||
expect(createFileTransportMock).toHaveBeenCalledTimes(2); | ||
expect(logMock).toHaveBeenCalledTimes(2); | ||
}); | ||
}); |
Oops, something went wrong.