mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Revert "Renderer file logging through IPC" (#7393)
This reverts commit 48db54ec9e.
This commit is contained in:
1 parent
48db54ec9e
commit
5409324236
24 files changed
+72
-832
No files matched your search
@@ -1,46 +0,0 @@
|
||||
/**
|
||||
* 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 currentlyInClusterFrameInjectable from "../../routes/currently-in-cluster-frame.injectable";
|
||||
import { beforeFrameStartsSecondInjectionToken } from "../tokens";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable";
|
||||
import frameRoutingIdInjectable from "../../frames/cluster-frame/init-cluster-frame/frame-routing-id/frame-routing-id.injectable";
|
||||
import closeRendererLogFileInjectable from "../../logger/close-renderer-log-file.injectable";
|
||||
import { unmountComponentAtNode } from "react-dom";
|
||||
|
||||
const listenUnloadInjectable = getInjectable({
|
||||
id: "listen-unload",
|
||||
instantiate: (di) => ({
|
||||
run: () => {
|
||||
const closeRendererLogFile = di.inject(closeRendererLogFileInjectable);
|
||||
const isClusterFrame = di.inject(currentlyInClusterFrameInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
window.addEventListener("beforeunload", () => {
|
||||
if (isClusterFrame) {
|
||||
const hostedCluster = di.inject(hostedClusterInjectable);
|
||||
const frameRoutingId = di.inject(frameRoutingIdInjectable);
|
||||
|
||||
logger.info(
|
||||
`[CLUSTER-FRAME] Unload dashboard, clusterId=${hostedCluster?.id}, frameId=${frameRoutingId}`,
|
||||
);
|
||||
} else {
|
||||
logger.info("[ROOT-FRAME]: Unload app");
|
||||
}
|
||||
|
||||
closeRendererLogFile();
|
||||
const rootElem = document.getElementById("app");
|
||||
|
||||
if (rootElem) {
|
||||
unmountComponentAtNode(rootElem);
|
||||
}
|
||||
});
|
||||
},
|
||||
}),
|
||||
injectionToken: beforeFrameStartsSecondInjectionToken,
|
||||
});
|
||||
|
||||
export default listenUnloadInjectable;
|
||||
@@ -6,7 +6,7 @@
|
||||
import "./components/app.scss";
|
||||
|
||||
import React from "react";
|
||||
import { render } from "react-dom";
|
||||
import { render, unmountComponentAtNode } from "react-dom";
|
||||
import { DefaultProps } from "./mui-base-theme";
|
||||
import { DiContextProvider } from "@ogre-tools/injectable-react";
|
||||
import type {
|
||||
@@ -43,7 +43,7 @@ export async function bootstrap(di: DiContainerForInjection) {
|
||||
}
|
||||
|
||||
try {
|
||||
await initializeApp();
|
||||
await initializeApp(() => unmountComponentAtNode(rootElem));
|
||||
} catch (error) {
|
||||
console.error(`[BOOTSTRAP]: view initialization error: ${error}`, {
|
||||
origin: location.href,
|
||||
|
||||
+49
-38
@@ -22,51 +22,62 @@ interface Dependencies {
|
||||
|
||||
const logPrefix = "[CLUSTER-FRAME]:";
|
||||
|
||||
export const initClusterFrame =
|
||||
({
|
||||
hostedCluster,
|
||||
loadExtensions,
|
||||
catalogEntityRegistry,
|
||||
frameRoutingId,
|
||||
emitAppEvent,
|
||||
logger,
|
||||
showErrorNotification,
|
||||
}: Dependencies) =>
|
||||
async () => {
|
||||
export const initClusterFrame = ({
|
||||
hostedCluster,
|
||||
loadExtensions,
|
||||
catalogEntityRegistry,
|
||||
frameRoutingId,
|
||||
emitAppEvent,
|
||||
logger,
|
||||
showErrorNotification,
|
||||
}: Dependencies) =>
|
||||
async (unmountRoot: () => void) => {
|
||||
// TODO: Make catalogEntityRegistry already initialized when passed as dependency
|
||||
catalogEntityRegistry.init();
|
||||
catalogEntityRegistry.init();
|
||||
|
||||
logger.info(
|
||||
`${logPrefix} Init dashboard, clusterId=${hostedCluster.id}, frameId=${frameRoutingId}`,
|
||||
);
|
||||
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
|
||||
await requestSetClusterFrameId(hostedCluster.id);
|
||||
await when(() => hostedCluster.ready.get()); // cluster.activate() is done at this point
|
||||
|
||||
catalogEntityRegistry.activeEntity = hostedCluster.id;
|
||||
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);
|
||||
// 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.");
|
||||
},
|
||||
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}`,
|
||||
);
|
||||
|
||||
setTimeout(() => {
|
||||
emitAppEvent({
|
||||
name: "cluster",
|
||||
action: "open",
|
||||
params: {
|
||||
clusterId: hostedCluster.id,
|
||||
},
|
||||
});
|
||||
});
|
||||
unmountRoot();
|
||||
};
|
||||
};
|
||||
@@ -9,6 +9,7 @@ import lensProtocolRouterRendererInjectable from "../../protocol-handler/lens-pr
|
||||
import catalogEntityRegistryInjectable from "../../api/catalog/entity/registry.injectable";
|
||||
import registerIpcListenersInjectable from "../../ipc/register-ipc-listeners.injectable";
|
||||
import loadExtensionsInjectable from "../load-extensions.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import { delay } from "@k8slens/utilities";
|
||||
import { broadcastMessage } from "../../../common/ipc";
|
||||
import { bundledExtensionsLoaded } from "../../../common/ipc/extension-handling";
|
||||
@@ -22,8 +23,9 @@ const initRootFrameInjectable = getInjectable({
|
||||
const bindProtocolAddRouteHandlers = di.inject(bindProtocolAddRouteHandlersInjectable);
|
||||
const lensProtocolRouterRenderer = di.inject(lensProtocolRouterRendererInjectable);
|
||||
const catalogEntityRegistry = di.inject(catalogEntityRegistryInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return async () => {
|
||||
return async (unmountRoot: () => void) => {
|
||||
catalogEntityRegistry.init();
|
||||
|
||||
try {
|
||||
@@ -54,6 +56,12 @@ const initRootFrameInjectable = getInjectable({
|
||||
window.addEventListener("online", () => broadcastMessage("network:online"));
|
||||
|
||||
registerIpcListeners();
|
||||
|
||||
window.addEventListener("beforeunload", () => {
|
||||
logger.info("[ROOT-FRAME]: Unload app");
|
||||
|
||||
unmountRoot();
|
||||
});
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/**
|
||||
* 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 { getDiForUnitTesting } from "../getDiForUnitTesting";
|
||||
import closeRendererLogFileInjectable from "./close-renderer-log-file.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import type winston from "winston";
|
||||
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 ipcLogTransportInjectable from "./ipc-transport.injectable";
|
||||
import type IpcLogTransport from "./ipc-transport";
|
||||
|
||||
describe("close renderer file logging", () => {
|
||||
let di: DiContainer;
|
||||
let sendIpcMock: SendMessageToChannel;
|
||||
let winstonMock: winston.Logger;
|
||||
let ipcTransportMock: IpcLogTransport;
|
||||
|
||||
beforeEach(() => {
|
||||
di = getDiForUnitTesting();
|
||||
sendIpcMock = jest.fn();
|
||||
winstonMock = {
|
||||
remove: jest.fn(),
|
||||
} as any as winston.Logger;
|
||||
ipcTransportMock = { name: "ipc-renderer-transport" } as IpcLogTransport;
|
||||
|
||||
di.override(winstonLoggerInjectable, () => winstonMock);
|
||||
di.override(sendMessageToChannelInjectionToken, () => sendIpcMock);
|
||||
di.override(rendererLogFileIdInjectable, () => "some-log-id");
|
||||
di.override(ipcLogTransportInjectable, () => ipcTransportMock);
|
||||
});
|
||||
|
||||
it("sends the ipc close message with correct log id", () => {
|
||||
const closeLog = di.inject(closeRendererLogFileInjectable);
|
||||
|
||||
closeLog();
|
||||
|
||||
expect(sendIpcMock).toHaveBeenCalledWith(
|
||||
{ id: "close-ipc-file-logger-channel" },
|
||||
"some-log-id",
|
||||
);
|
||||
});
|
||||
|
||||
it("removes the transport to prevent further logging to closed file", () => {
|
||||
const closeLog = di.inject(closeRendererLogFileInjectable);
|
||||
|
||||
closeLog();
|
||||
|
||||
expect(winstonMock.remove).toHaveBeenCalledWith({
|
||||
name: "ipc-renderer-transport",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* 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 winstonLoggerInjectable from "../../common/winston-logger.injectable";
|
||||
import { closeIpcFileLoggerChannel } from "../../common/logger/ipc-file-logger-channel";
|
||||
import { sendMessageToChannelInjectionToken } from "../../common/utils/channel/message-to-channel-injection-token";
|
||||
import rendererLogFileIdInjectable from "./renderer-log-file-id.injectable";
|
||||
import ipcLogTransportInjectable from "./ipc-transport.injectable";
|
||||
|
||||
const closeRendererLogFileInjectable = getInjectable({
|
||||
id: "close-renderer-log-file",
|
||||
instantiate: (di) => {
|
||||
const winstonLogger = di.inject(winstonLoggerInjectable);
|
||||
const ipcLogTransport = di.inject(ipcLogTransportInjectable);
|
||||
const messageToChannel = di.inject(sendMessageToChannelInjectionToken);
|
||||
const fileId = di.inject(rendererLogFileIdInjectable);
|
||||
|
||||
|
||||
return () => {
|
||||
messageToChannel(closeIpcFileLoggerChannel, fileId);
|
||||
winstonLogger.remove(ipcLogTransport);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default closeRendererLogFileInjectable;
|
||||
@@ -1,60 +0,0 @@
|
||||
/**
|
||||
* 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 { loggerTransportInjectionToken } from "../../common/logger/transports";
|
||||
import type winston from "winston";
|
||||
import { MESSAGE } from "triple-beam";
|
||||
|
||||
import IpcLogTransport from "./ipc-transport";
|
||||
import { sendMessageToChannelInjectionToken } from "../../common/utils/channel/message-to-channel-injection-token";
|
||||
import type {
|
||||
IpcFileLogObject } from "../../common/logger/ipc-file-logger-channel";
|
||||
import {
|
||||
closeIpcFileLoggerChannel,
|
||||
ipcFileLoggerChannel,
|
||||
} from "../../common/logger/ipc-file-logger-channel";
|
||||
import rendererLogFileIdInjectable from "./renderer-log-file-id.injectable";
|
||||
|
||||
/**
|
||||
* Winston uses symbol property for the actual message.
|
||||
*
|
||||
* For that to get through IPC, use the internalMessage property instead
|
||||
*/
|
||||
function serializeLogForIpc(
|
||||
fileId: string,
|
||||
entry: winston.LogEntry,
|
||||
): IpcFileLogObject {
|
||||
return {
|
||||
fileId,
|
||||
entry: {
|
||||
level: entry.level,
|
||||
message: entry.message,
|
||||
internalMessage: Object.getOwnPropertyDescriptor(entry, MESSAGE)?.value,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const ipcLogTransportInjectable = getInjectable({
|
||||
id: "renderer-file-logger-transport",
|
||||
instantiate: (di) => {
|
||||
const messageToChannel = di.inject(sendMessageToChannelInjectionToken);
|
||||
const fileId = di.inject(rendererLogFileIdInjectable);
|
||||
|
||||
return new IpcLogTransport({
|
||||
sendIpcLogMessage: (entry) =>
|
||||
messageToChannel(
|
||||
ipcFileLoggerChannel,
|
||||
serializeLogForIpc(fileId, entry),
|
||||
),
|
||||
closeIpcLogging: () =>
|
||||
messageToChannel(closeIpcFileLoggerChannel, fileId),
|
||||
handleExceptions: false,
|
||||
level: "info",
|
||||
});
|
||||
},
|
||||
injectionToken: loggerTransportInjectionToken,
|
||||
});
|
||||
|
||||
export default ipcLogTransportInjectable;
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* 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 { 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 rendererLogFileIdInjectable from "./renderer-log-file-id.injectable";
|
||||
import ipcLogTransportInjectable from "./ipc-transport.injectable";
|
||||
import { MESSAGE } from "triple-beam";
|
||||
|
||||
describe("renderer log transport through ipc", () => {
|
||||
let di: DiContainer;
|
||||
let sendIpcMock: SendMessageToChannel;
|
||||
|
||||
beforeEach(() => {
|
||||
sendIpcMock = jest.fn();
|
||||
di = getDiForUnitTesting();
|
||||
di.override(sendMessageToChannelInjectionToken, () => sendIpcMock);
|
||||
di.override(rendererLogFileIdInjectable, () => "some-log-id");
|
||||
});
|
||||
|
||||
it("send serialized ipc messages on log", () => {
|
||||
const logTransport = di.inject(ipcLogTransportInjectable);
|
||||
|
||||
logTransport.log(
|
||||
{
|
||||
level: "info",
|
||||
message: "some log text",
|
||||
[MESSAGE]: "actual winston log text",
|
||||
},
|
||||
() => {},
|
||||
);
|
||||
|
||||
expect(sendIpcMock).toHaveBeenCalledWith(
|
||||
{ id: "ipc-file-logger-channel" },
|
||||
{
|
||||
entry: {
|
||||
level: "info",
|
||||
message: "some log text",
|
||||
internalMessage: "actual winston log text",
|
||||
},
|
||||
fileId: "some-log-id",
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,41 +0,0 @@
|
||||
/**
|
||||
* 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 { TransportStreamOptions } from "winston-transport";
|
||||
import TransportStream from "winston-transport";
|
||||
|
||||
interface IpcLogTransportOptions extends TransportStreamOptions {
|
||||
sendIpcLogMessage: (entry: LogEntry) => void;
|
||||
closeIpcLogging: () => void;
|
||||
}
|
||||
|
||||
class IpcLogTransport extends TransportStream {
|
||||
sendIpcLogMessage: (entry: LogEntry) => void;
|
||||
closeIpcLogging: () => void;
|
||||
name = "ipc-renderer-transport";
|
||||
|
||||
constructor(options: IpcLogTransportOptions) {
|
||||
const { sendIpcLogMessage, closeIpcLogging, ...winstonOptions } = options;
|
||||
|
||||
super(winstonOptions);
|
||||
|
||||
this.sendIpcLogMessage = sendIpcLogMessage;
|
||||
this.closeIpcLogging = closeIpcLogging;
|
||||
}
|
||||
|
||||
log(logEntry: LogEntry, next: () => void) {
|
||||
setImmediate(() => {
|
||||
this.emit("logged", logEntry);
|
||||
});
|
||||
this.sendIpcLogMessage(logEntry);
|
||||
next();
|
||||
}
|
||||
|
||||
close() {
|
||||
this.closeIpcLogging();
|
||||
}
|
||||
}
|
||||
|
||||
export default IpcLogTransport;
|
||||
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* 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 windowLocationInjectable from "../../common/k8s-api/window-location.injectable";
|
||||
import currentlyInClusterFrameInjectable from "../routes/currently-in-cluster-frame.injectable";
|
||||
import { getClusterIdFromHost } from "../../common/utils";
|
||||
|
||||
const rendererLogFileIdInjectable = getInjectable({
|
||||
id: "renderer-log-file-id",
|
||||
instantiate: (di) => {
|
||||
let frameId: string;
|
||||
const currentlyInClusterFrame = di.inject(currentlyInClusterFrameInjectable);
|
||||
|
||||
if (currentlyInClusterFrame) {
|
||||
const { host } = di.inject(windowLocationInjectable);
|
||||
const clusterId = getClusterIdFromHost(host);
|
||||
|
||||
frameId = `cluster-${clusterId}`;
|
||||
} else {
|
||||
frameId = "main";
|
||||
}
|
||||
|
||||
return `renderer-${frameId}`;
|
||||
},
|
||||
});
|
||||
|
||||
export default rendererLogFileIdInjectable;
|
||||
@@ -1,34 +0,0 @@
|
||||
/**
|
||||
* 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 { getDiForUnitTesting } from "../getDiForUnitTesting";
|
||||
import currentlyInClusterFrameInjectable from "../routes/currently-in-cluster-frame.injectable";
|
||||
import rendererLogFileIdInjectable from "./renderer-log-file-id.injectable";
|
||||
|
||||
describe("renderer log file id", () => {
|
||||
|
||||
it("clearly names log for renderer main frame", () => {
|
||||
const di = getDiForUnitTesting();
|
||||
|
||||
di.override(currentlyInClusterFrameInjectable, () => false);
|
||||
|
||||
const mainFileId = di.inject(rendererLogFileIdInjectable);
|
||||
|
||||
expect(mainFileId).toBe("renderer-main");
|
||||
});
|
||||
|
||||
it("includes cluster id in renderer log file names", () => {
|
||||
const di = getDiForUnitTesting();
|
||||
|
||||
di.override(currentlyInClusterFrameInjectable, () => true);
|
||||
di.override(windowLocationInjectable, () => ({
|
||||
host: "some-cluster.lens.app",
|
||||
port: "irrelevant",
|
||||
}));
|
||||
const clusterFileId = di.inject(rendererLogFileIdInjectable);
|
||||
|
||||
expect(clusterFileId).toBe("renderer-cluster-some-cluster");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user