1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00
Signed-off-by: Sami Tiilikainen <97873007+samitiilikainen@users.noreply.github.com>
This commit is contained in:
Sami Tiilikainen 2023-03-07 09:31:40 +02:00
parent c7350a086c
commit dca043535e
12 changed files with 101 additions and 56 deletions

View File

@ -1,13 +1,17 @@
/**
* 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"; import type { MessageChannel } from "../utils/channel/message-channel-listener-injection-token";
export type IpcFileLogObject = { export interface IpcFileLogObject {
fileId: string; fileId: string;
entry: { entry: {
level: string; level: string;
message: string; message: string;
internalMessage: string; internalMessage: string;
}; };
}; }
export type IpcFileLoggerChannel = MessageChannel<IpcFileLogObject>; export type IpcFileLoggerChannel = MessageChannel<IpcFileLogObject>;

View File

@ -17,7 +17,7 @@ const ipcFileLoggerInjectable = getInjectable({
maxFiles: 2, maxFiles: 2,
tailable: true, tailable: true,
}, },
(options: transports.FileTransportOptions) => new transports.File(options) (options: transports.FileTransportOptions) => new transports.File(options),
), ),
}); });

View File

@ -1,3 +1,7 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import IpcFileLogger from "./ipc-file-logger"; import IpcFileLogger from "./ipc-file-logger";
describe("ipc file logger in main", () => { describe("ipc file logger in main", () => {
@ -19,7 +23,7 @@ describe("ipc file logger in main", () => {
maxFiles: 1, maxFiles: 1,
tailable: true, tailable: true,
}, },
createFileTransportMock createFileTransportMock,
); );
}); });
@ -122,9 +126,11 @@ describe("ipc file logger in main", () => {
if (options.filename === "lens-some-log-file.log") { if (options.filename === "lens-some-log-file.log") {
return { log: someLogMock }; return { log: someLogMock };
} }
if (options.filename === "lens-some-other-log-file.log") { if (options.filename === "lens-some-other-log-file.log") {
return { log: someOthertLogMock }; return { log: someOthertLogMock };
} }
return null; return null;
}); });

View File

@ -1,3 +1,7 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { LogEntry, transports } from "winston"; import type { LogEntry, transports } from "winston";
type IpcFileLoggerOptions = Omit<transports.FileTransportOptions, "filename">; type IpcFileLoggerOptions = Omit<transports.FileTransportOptions, "filename">;
@ -9,7 +13,7 @@ class IpcFileLogger {
private options: IpcFileLoggerOptions, private options: IpcFileLoggerOptions,
private createNewFileTransport: ( private createNewFileTransport: (
options: transports.FileTransportOptions options: transports.FileTransportOptions
) => transports.FileTransportInstance ) => transports.FileTransportInstance,
) {} ) {}
log({ fileId, entry }: { fileId: string; entry: LogEntry }) { log({ fileId, entry }: { fileId: string; entry: LogEntry }) {
@ -20,6 +24,7 @@ class IpcFileLogger {
close(fileId: string) { close(fileId: string) {
const transport = this.fileTransports.get(fileId); const transport = this.fileTransports.get(fileId);
if (transport) { if (transport) {
transport.close?.(); transport.close?.();
this.fileTransports.delete(fileId); this.fileTransports.delete(fileId);

View File

@ -4,9 +4,10 @@
*/ */
import ipcFileLoggerInjectable from "./ipc-file-logger.injectable"; import ipcFileLoggerInjectable from "./ipc-file-logger.injectable";
import { getMessageChannelListenerInjectable } from "../../common/utils/channel/message-channel-listener-injection-token"; import { getMessageChannelListenerInjectable } from "../../common/utils/channel/message-channel-listener-injection-token";
import type {
IpcFileLogObject } from "../../common/logger/ipc-file-logger-channel";
import { import {
ipcFileLoggerChannel, ipcFileLoggerChannel,
IpcFileLogObject,
} from "../../common/logger/ipc-file-logger-channel"; } from "../../common/logger/ipc-file-logger-channel";
import { MESSAGE } from "triple-beam"; import { MESSAGE } from "triple-beam";
@ -17,6 +18,7 @@ import { MESSAGE } from "triple-beam";
*/ */
export function deserializeLogFromIpc(ipcFileLogObject: IpcFileLogObject) { export function deserializeLogFromIpc(ipcFileLogObject: IpcFileLogObject) {
const { internalMessage, ...standardEntry } = ipcFileLogObject.entry; const { internalMessage, ...standardEntry } = ipcFileLogObject.entry;
return { return {
...ipcFileLogObject, ...ipcFileLogObject,
entry: { entry: {

View File

@ -34,50 +34,50 @@ export const initClusterFrame =
showErrorNotification, showErrorNotification,
closeFileLogging, closeFileLogging,
}: Dependencies) => }: Dependencies) =>
async (unmountRoot: () => void) => { async (unmountRoot: () => void) => {
// TODO: Make catalogEntityRegistry already initialized when passed as dependency // TODO: Make catalogEntityRegistry already initialized when passed as dependency
catalogEntityRegistry.init(); catalogEntityRegistry.init();
logger.info(
`${logPrefix} Init dashboard, clusterId=${hostedCluster.id}, frameId=${frameRoutingId}`,
);
await requestSetClusterFrameId(hostedCluster.id);
await when(() => hostedCluster.ready.get()); // cluster.activate() is done at this point
catalogEntityRegistry.activeEntity = hostedCluster.id;
// Only load the extensions once the catalog has been populated.
// Note that the Catalog might still have unprocessed entities until the extensions are fully loaded.
when(
() => catalogEntityRegistry.items.get().length > 0,
() => loadExtensions(),
{
timeout: 15_000,
onError: (error) => {
logger.warn("[CLUSTER-FRAME]: error from activeEntity when()", error);
showErrorNotification("Failed to get KubernetesCluster for this view. Extensions will not be loaded.");
},
},
);
setTimeout(() => {
emitAppEvent({
name: "cluster",
action: "open",
params: {
clusterId: hostedCluster.id,
},
});
});
window.onbeforeunload = () => {
logger.info( logger.info(
`${logPrefix} Unload dashboard, clusterId=${hostedCluster.id}, frameId=${frameRoutingId}` `${logPrefix} Init dashboard, clusterId=${hostedCluster.id}, frameId=${frameRoutingId}`,
); );
unmountRoot(); await requestSetClusterFrameId(hostedCluster.id);
closeFileLogging(); await when(() => hostedCluster.ready.get()); // cluster.activate() is done at this point
catalogEntityRegistry.activeEntity = hostedCluster.id;
// Only load the extensions once the catalog has been populated.
// Note that the Catalog might still have unprocessed entities until the extensions are fully loaded.
when(
() => catalogEntityRegistry.items.get().length > 0,
() => loadExtensions(),
{
timeout: 15_000,
onError: (error) => {
logger.warn("[CLUSTER-FRAME]: error from activeEntity when()", error);
showErrorNotification("Failed to get KubernetesCluster for this view. Extensions will not be loaded.");
},
},
);
setTimeout(() => {
emitAppEvent({
name: "cluster",
action: "open",
params: {
clusterId: hostedCluster.id,
},
});
});
window.onbeforeunload = () => {
logger.info(
`${logPrefix} Unload dashboard, clusterId=${hostedCluster.id}, frameId=${frameRoutingId}`,
);
unmountRoot();
closeFileLogging();
};
}; };
};

View File

@ -1,9 +1,14 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import winstonLoggerInjectable from "../../common/winston-logger.injectable"; import winstonLoggerInjectable from "../../common/winston-logger.injectable";
import { getDiForUnitTesting } from "../getDiForUnitTesting"; import { getDiForUnitTesting } from "../getDiForUnitTesting";
import closeRendererLogFileInjectable from "./close-renderer-log-file.injectable"; import closeRendererLogFileInjectable from "./close-renderer-log-file.injectable";
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import type winston from "winston"; import type winston from "winston";
import { SendMessageToChannel, sendMessageToChannelInjectionToken } from "../../common/utils/channel/message-to-channel-injection-token"; import type { SendMessageToChannel } from "../../common/utils/channel/message-to-channel-injection-token";
import { sendMessageToChannelInjectionToken } from "../../common/utils/channel/message-to-channel-injection-token";
import rendererLogFileIdInjectable from "./renderer-log-file-id.injectable"; import rendererLogFileIdInjectable from "./renderer-log-file-id.injectable";
import ipcLogTransportInjectable from "./ipc-transport.injectable"; import ipcLogTransportInjectable from "./ipc-transport.injectable";
import type IpcLogTransport from "./ipc-transport"; import type IpcLogTransport from "./ipc-transport";
@ -30,16 +35,18 @@ describe("close renderer file logging", () => {
it("sends the ipc close message with correct log id", () => { it("sends the ipc close message with correct log id", () => {
const closeLog = di.inject(closeRendererLogFileInjectable); const closeLog = di.inject(closeRendererLogFileInjectable);
closeLog(); closeLog();
expect(sendIpcMock).toHaveBeenCalledWith( expect(sendIpcMock).toHaveBeenCalledWith(
{ id: "close-ipc-file-logger-channel" }, { id: "close-ipc-file-logger-channel" },
"some-log-id" "some-log-id",
); );
}); });
it("removes the transport to prevent further logging to closed file", () => { it("removes the transport to prevent further logging to closed file", () => {
const closeLog = di.inject(closeRendererLogFileInjectable); const closeLog = di.inject(closeRendererLogFileInjectable);
closeLog(); closeLog();
expect(winstonMock.remove).toHaveBeenCalledWith({ expect(winstonMock.remove).toHaveBeenCalledWith({

View File

@ -9,10 +9,11 @@ import { MESSAGE } from "triple-beam";
import IpcLogTransport from "./ipc-transport"; import IpcLogTransport from "./ipc-transport";
import { sendMessageToChannelInjectionToken } from "../../common/utils/channel/message-to-channel-injection-token"; import { sendMessageToChannelInjectionToken } from "../../common/utils/channel/message-to-channel-injection-token";
import type {
IpcFileLogObject } from "../../common/logger/ipc-file-logger-channel";
import { import {
closeIpcFileLoggerChannel, closeIpcFileLoggerChannel,
ipcFileLoggerChannel, ipcFileLoggerChannel,
IpcFileLogObject,
} from "../../common/logger/ipc-file-logger-channel"; } from "../../common/logger/ipc-file-logger-channel";
import rendererLogFileIdInjectable from "./renderer-log-file-id.injectable"; import rendererLogFileIdInjectable from "./renderer-log-file-id.injectable";
@ -23,7 +24,7 @@ import rendererLogFileIdInjectable from "./renderer-log-file-id.injectable";
*/ */
function serializeLogForIpc( function serializeLogForIpc(
fileId: string, fileId: string,
entry: winston.LogEntry entry: winston.LogEntry,
): IpcFileLogObject { ): IpcFileLogObject {
return { return {
fileId, fileId,
@ -45,7 +46,7 @@ const ipcLogTransportInjectable = getInjectable({
sendIpcLogMessage: (entry) => sendIpcLogMessage: (entry) =>
messageToChannel( messageToChannel(
ipcFileLoggerChannel, ipcFileLoggerChannel,
serializeLogForIpc(fileId, entry) serializeLogForIpc(fileId, entry),
), ),
closeIpcLogging: () => closeIpcLogging: () =>
messageToChannel(closeIpcFileLoggerChannel, fileId), messageToChannel(closeIpcFileLoggerChannel, fileId),

View File

@ -1,5 +1,10 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import { SendMessageToChannel, sendMessageToChannelInjectionToken } from "../../common/utils/channel/message-to-channel-injection-token"; import type { SendMessageToChannel } from "../../common/utils/channel/message-to-channel-injection-token";
import { sendMessageToChannelInjectionToken } from "../../common/utils/channel/message-to-channel-injection-token";
import { getDiForUnitTesting } from "../getDiForUnitTesting"; import { getDiForUnitTesting } from "../getDiForUnitTesting";
import rendererLogFileIdInjectable from "./renderer-log-file-id.injectable"; import rendererLogFileIdInjectable from "./renderer-log-file-id.injectable";
import ipcLogTransportInjectable from "./ipc-transport.injectable"; import ipcLogTransportInjectable from "./ipc-transport.injectable";
@ -18,13 +23,14 @@ describe("renderer log transport through ipc", () => {
it("send serialized ipc messages on log", () => { it("send serialized ipc messages on log", () => {
const logTransport = di.inject(ipcLogTransportInjectable); const logTransport = di.inject(ipcLogTransportInjectable);
logTransport.log( logTransport.log(
{ {
level: "info", level: "info",
message: "some log text", message: "some log text",
[MESSAGE]: "actual winston log text", [MESSAGE]: "actual winston log text",
}, },
() => {} () => {},
); );
expect(sendIpcMock).toHaveBeenCalledWith( expect(sendIpcMock).toHaveBeenCalledWith(
@ -36,7 +42,7 @@ describe("renderer log transport through ipc", () => {
internalMessage: "actual winston log text", internalMessage: "actual winston log text",
}, },
fileId: "some-log-id", fileId: "some-log-id",
} },
); );
}); });
}); });

View File

@ -1,5 +1,10 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { LogEntry } from "winston"; import type { LogEntry } from "winston";
import TransportStream, { TransportStreamOptions } from "winston-transport"; import type { TransportStreamOptions } from "winston-transport";
import TransportStream from "winston-transport";
interface IpcLogTransportOptions extends TransportStreamOptions { interface IpcLogTransportOptions extends TransportStreamOptions {
sendIpcLogMessage: (entry: LogEntry) => void; sendIpcLogMessage: (entry: LogEntry) => void;
@ -13,6 +18,7 @@ class IpcLogTransport extends TransportStream {
constructor(options: IpcLogTransportOptions) { constructor(options: IpcLogTransportOptions) {
const { sendIpcLogMessage, closeIpcLogging, ...winstonOptions } = options; const { sendIpcLogMessage, closeIpcLogging, ...winstonOptions } = options;
super(winstonOptions); super(winstonOptions);
this.sendIpcLogMessage = sendIpcLogMessage; this.sendIpcLogMessage = sendIpcLogMessage;

View File

@ -17,6 +17,7 @@ const rendererLogFileIdInjectable = getInjectable({
if (currentlyInClusterFrame) { if (currentlyInClusterFrame) {
const { host } = di.inject(windowLocationInjectable); const { host } = di.inject(windowLocationInjectable);
const clusterId = getClusterIdFromHost(host); const clusterId = getClusterIdFromHost(host);
frameId = clusterId ? `cluster-${clusterId}` : "cluster"; frameId = clusterId ? `cluster-${clusterId}` : "cluster";
} else { } else {
frameId = "main"; frameId = "main";

View File

@ -1,3 +1,7 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import windowLocationInjectable from "../../common/k8s-api/window-location.injectable"; import windowLocationInjectable from "../../common/k8s-api/window-location.injectable";
import { getDiForUnitTesting } from "../getDiForUnitTesting"; import { getDiForUnitTesting } from "../getDiForUnitTesting";
import currentlyInClusterFrameInjectable from "../routes/currently-in-cluster-frame.injectable"; import currentlyInClusterFrameInjectable from "../routes/currently-in-cluster-frame.injectable";
@ -7,9 +11,11 @@ describe("renderer log file id", () => {
it("clearly names log for renderer main frame", () => { it("clearly names log for renderer main frame", () => {
const di = getDiForUnitTesting({ doGeneralOverrides: false }); const di = getDiForUnitTesting({ doGeneralOverrides: false });
di.override(currentlyInClusterFrameInjectable, () => false); di.override(currentlyInClusterFrameInjectable, () => false);
const mainFileId = di.inject(rendererLogFileIdInjectable); const mainFileId = di.inject(rendererLogFileIdInjectable);
expect(mainFileId).toBe("renderer-main"); expect(mainFileId).toBe("renderer-main");
}); });
@ -22,6 +28,7 @@ describe("renderer log file id", () => {
port: "irrelevant", port: "irrelevant",
})); }));
const clusterFileId = di.inject(rendererLogFileIdInjectable); const clusterFileId = di.inject(rendererLogFileIdInjectable);
expect(clusterFileId).toBe("renderer-cluster-some-cluster"); expect(clusterFileId).toBe("renderer-cluster-some-cluster");
}); });
}); });