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

Improve bootstrap logging for help with iframe debugging (#4020)

This commit is contained in:
Sebastian Malton 2021-11-18 16:54:43 -05:00 committed by GitHub
parent e779c7c317
commit 885af07d0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 113 additions and 76 deletions

View File

@ -43,6 +43,8 @@ export abstract class BaseStore<T> extends Singleton {
protected storeConfig?: Config<T>;
protected syncDisposers: Disposer[] = [];
readonly displayName: string = this.constructor.name;
protected constructor(protected params: BaseStoreParams<T>) {
super();
makeObservable(this);
@ -56,6 +58,10 @@ export abstract class BaseStore<T> extends Singleton {
* This must be called after the last child's constructor is finished (or just before it finishes)
*/
load() {
if (!isTestEnv) {
logger.info(`[${kebabCase(this.displayName).toUpperCase()}]: LOADING from ${this.path} ...`);
}
this.storeConfig = new Config({
...this.params,
projectName: "lens",
@ -66,13 +72,13 @@ export abstract class BaseStore<T> extends Singleton {
const res: any = this.fromStore(this.storeConfig.store);
if (res instanceof Promise || (typeof res === "object" && res && typeof res.then === "function")) {
console.error(`${this.constructor.name} extends BaseStore<T>'s fromStore method returns a Promise or promise-like object. This is an error and must be fixed.`);
console.error(`${this.displayName} extends BaseStore<T>'s fromStore method returns a Promise or promise-like object. This is an error and must be fixed.`);
}
this.enableSync();
if (!isTestEnv) {
logger.info(`[${kebabCase(this.constructor.name).toUpperCase()}]: LOADED from ${this.path}`);
logger.info(`[${kebabCase(this.displayName).toUpperCase()}]: LOADED from ${this.path}`);
}
}

View File

@ -37,6 +37,7 @@ export interface ClusterStoreModel {
const initialStates = "cluster:states";
export class ClusterStore extends BaseStore<ClusterStoreModel> {
readonly displayName = "ClusterStore";
clusters = observable.map<ClusterId, Cluster>();
protected disposer = disposer();

View File

@ -35,6 +35,7 @@ export interface HotbarStoreModel {
}
export class HotbarStore extends BaseStore<HotbarStoreModel> {
readonly displayName = "HotbarStore";
@observable hotbars: Hotbar[] = [];
@observable private _activeHotbarId: string;

View File

@ -39,6 +39,7 @@ export interface UserStoreModel {
}
export class UserStore extends BaseStore<UserStoreModel> /* implements UserStoreFlatModel (when strict null is enabled) */ {
readonly displayName = "UserStore";
constructor() {
super({
configName: "lens-user-store",

View File

@ -43,6 +43,7 @@ export interface WeblinkStoreModel {
}
export class WeblinkStore extends BaseStore<WeblinkStoreModel> {
readonly displayName = "WeblinkStore";
@observable weblinks: WeblinkData[] = [];
constructor() {

View File

@ -24,6 +24,7 @@ import * as path from "path";
import type { LensExtension } from "./lens-extension";
export abstract class ExtensionStore<T> extends BaseStore<T> {
readonly displayName = "ExtensionStore<T>";
protected extension: LensExtension;
loadExtension(extension: LensExtension) {

View File

@ -34,6 +34,7 @@ export interface LensExtensionState {
}
export class ExtensionsStore extends BaseStore<LensExtensionsStoreModel> {
readonly displayName = "ExtensionsStore";
constructor() {
super({
configName: "lens-extensions",

View File

@ -34,6 +34,7 @@ interface FSProvisionModel {
}
export class FilesystemProvisionerStore extends BaseStore<FSProvisionModel> {
readonly displayName = "FilesystemProvisionerStore";
registeredExtensions = observable.map<LensExtensionId, string>();
constructor() {

View File

@ -40,6 +40,7 @@ import { ExtensionInstallationStateStore } from "./components/+extensions/extens
import { DefaultProps } from "./mui-base-theme";
import configurePackages from "../common/configure-packages";
import * as initializers from "./initializers";
import logger from "../common/logger";
import { HotbarStore } from "../common/hotbar-store";
import { WeblinkStore } from "../common/weblink-store";
import { ExtensionsStore } from "../extensions/extensions-store";
@ -69,37 +70,59 @@ async function attachChromeDebugger() {
}
type AppComponent = React.ComponentType & {
init?(rootElem: HTMLElement): Promise<void>;
init(rootElem: HTMLElement): Promise<void>;
};
export async function bootstrap(comp: () => Promise<AppComponent>) {
await AppPaths.init();
const rootElem = document.getElementById("app");
const logPrefix = `[BOOTSTRAP-${process.isMainFrame ? "ROOT" : "CLUSTER"}-FRAME]:`;
await AppPaths.init();
UserStore.createInstance();
await attachChromeDebugger();
rootElem.classList.toggle("is-mac", isMac);
logger.info(`${logPrefix} initializing Registries`);
initializers.initRegistries();
logger.info(`${logPrefix} initializing CommandRegistry`);
initializers.initCommandRegistry();
logger.info(`${logPrefix} initializing EntitySettingsRegistry`);
initializers.initEntitySettingsRegistry();
logger.info(`${logPrefix} initializing KubeObjectMenuRegistry`);
initializers.initKubeObjectMenuRegistry();
initializers.intiKubeObjectDetailRegistry();
logger.info(`${logPrefix} initializing KubeObjectDetailRegistry`);
initializers.initKubeObjectDetailRegistry();
logger.info(`${logPrefix} initializing WelcomeMenuRegistry`);
initializers.initWelcomeMenuRegistry();
logger.info(`${logPrefix} initializing WorkloadsOverviewDetailRegist`);
initializers.initWorkloadsOverviewDetailRegistry();
logger.info(`${logPrefix} initializing CatalogEntityDetailRegistry`);
initializers.initCatalogEntityDetailRegistry();
logger.info(`${logPrefix} initializing CatalogCategoryRegistryEntrie`);
initializers.initCatalogCategoryRegistryEntries();
logger.info(`${logPrefix} initializing Catalog`);
initializers.initCatalog();
logger.info(`${logPrefix} initializing IpcRendererListeners`);
initializers.initIpcRendererListeners();
ExtensionLoader.createInstance().init();
ExtensionDiscovery.createInstance().init();
// ClusterStore depends on: UserStore
const cs = ClusterStore.createInstance();
const clusterStore = ClusterStore.createInstance();
await cs.loadInitialOnRenderer();
await clusterStore.loadInitialOnRenderer();
// HotbarStore depends on: ClusterStore
HotbarStore.createInstance();
@ -117,7 +140,7 @@ export async function bootstrap(comp: () => Promise<AppComponent>) {
HelmRepoManager.createInstance(); // initialize the manager
// Register additional store listeners
cs.registerIpcListener();
clusterStore.registerIpcListener();
// init app's dependencies if any
const App = await comp();
@ -133,8 +156,8 @@ export async function bootstrap(comp: () => Promise<AppComponent>) {
// run
bootstrap(
async () => process.isMainFrame
? (await import("./lens-app")).LensApp
: (await import("./components/app")).App,
? (await import("./root-frame")).RootFrame
: (await import("./cluster-frame")).ClusterFrame,
);

View File

@ -22,61 +22,63 @@ import React from "react";
import { observable, makeObservable } from "mobx";
import { disposeOnUnmount, observer } from "mobx-react";
import { Redirect, Route, Router, Switch } from "react-router";
import { history } from "../navigation";
import { NotFound } from "./+404";
import { UserManagement } from "./+user-management/user-management";
import { ConfirmDialog } from "./confirm-dialog";
import { ClusterOverview } from "./+cluster/cluster-overview";
import { Events } from "./+events/events";
import { DeploymentScaleDialog } from "./+workloads-deployments/deployment-scale-dialog";
import { CronJobTriggerDialog } from "./+workloads-cronjobs/cronjob-trigger-dialog";
import { CustomResources } from "./+custom-resources/custom-resources";
import { isAllowedResource } from "../../common/utils/allowed-resource";
import logger from "../../main/logger";
import { history } from "./navigation";
import { NotFound } from "./components/+404";
import { UserManagement } from "./components/+user-management/user-management";
import { ConfirmDialog } from "./components/confirm-dialog";
import { ClusterOverview } from "./components/+cluster/cluster-overview";
import { Events } from "./components/+events/events";
import { DeploymentScaleDialog } from "./components/+workloads-deployments/deployment-scale-dialog";
import { CronJobTriggerDialog } from "./components/+workloads-cronjobs/cronjob-trigger-dialog";
import { CustomResources } from "./components/+custom-resources/custom-resources";
import { isAllowedResource } from "../common/utils/allowed-resource";
import logger from "../main/logger";
import { webFrame } from "electron";
import { ClusterPageRegistry, getExtensionPageUrl } from "../../extensions/registries/page-registry";
import { ExtensionLoader } from "../../extensions/extension-loader";
import { appEventBus } from "../../common/event-bus";
import { requestMain } from "../../common/ipc";
import { ClusterPageRegistry, getExtensionPageUrl } from "../extensions/registries/page-registry";
import { ExtensionLoader } from "../extensions/extension-loader";
import { appEventBus } from "../common/event-bus";
import { requestMain } from "../common/ipc";
import whatInput from "what-input";
import { clusterSetFrameIdHandler } from "../../common/cluster-ipc";
import { ClusterPageMenuRegistration, ClusterPageMenuRegistry } from "../../extensions/registries";
import { StatefulSetScaleDialog } from "./+workloads-statefulsets/statefulset-scale-dialog";
import { kubeWatchApi } from "../../common/k8s-api/kube-watch-api";
import { ReplicaSetScaleDialog } from "./+workloads-replicasets/replicaset-scale-dialog";
import { CommandContainer } from "./command-palette/command-container";
import { KubeObjectStore } from "../../common/k8s-api/kube-object.store";
import { clusterContext } from "./context";
import * as routes from "../../common/routes";
import { TabLayout, TabLayoutRoute } from "./layout/tab-layout";
import { ErrorBoundary } from "./error-boundary";
import { MainLayout } from "./layout/main-layout";
import { Notifications } from "./notifications";
import { KubeObjectDetails } from "./kube-object-details";
import { KubeConfigDialog } from "./kubeconfig-dialog";
import { Terminal } from "./dock/terminal";
import { namespaceStore } from "./+namespaces/namespace.store";
import { Sidebar } from "./layout/sidebar";
import { Dock } from "./dock";
import { Apps } from "./+apps";
import { Namespaces } from "./+namespaces";
import { Network } from "./+network";
import { Nodes } from "./+nodes";
import { Workloads } from "./+workloads";
import { Config } from "./+config";
import { Storage } from "./+storage";
import { catalogEntityRegistry } from "../api/catalog-entity-registry";
import { getHostedClusterId } from "../utils";
import { ClusterStore } from "../../common/cluster-store";
import type { ClusterId } from "../../common/cluster-types";
import { watchHistoryState } from "../remote-helpers/history-updater";
import { clusterSetFrameIdHandler } from "../common/cluster-ipc";
import { ClusterPageMenuRegistration, ClusterPageMenuRegistry } from "../extensions/registries";
import { StatefulSetScaleDialog } from "./components/+workloads-statefulsets/statefulset-scale-dialog";
import { kubeWatchApi } from "../common/k8s-api/kube-watch-api";
import { ReplicaSetScaleDialog } from "./components/+workloads-replicasets/replicaset-scale-dialog";
import { CommandContainer } from "./components/command-palette/command-container";
import { KubeObjectStore } from "../common/k8s-api/kube-object.store";
import { clusterContext } from "./components/context";
import * as routes from "../common/routes";
import { TabLayout, TabLayoutRoute } from "./components/layout/tab-layout";
import { ErrorBoundary } from "./components/error-boundary";
import { MainLayout } from "./components/layout/main-layout";
import { Notifications } from "./components/notifications";
import { KubeObjectDetails } from "./components/kube-object-details";
import { KubeConfigDialog } from "./components/kubeconfig-dialog";
import { Terminal } from "./components/dock/terminal";
import { namespaceStore } from "./components/+namespaces/namespace.store";
import { Sidebar } from "./components/layout/sidebar";
import { Dock } from "./components/dock";
import { Apps } from "./components/+apps";
import { Namespaces } from "./components/+namespaces";
import { Network } from "./components/+network";
import { Nodes } from "./components/+nodes";
import { Workloads } from "./components/+workloads";
import { Config } from "./components/+config";
import { Storage } from "./components/+storage";
import { catalogEntityRegistry } from "./api/catalog-entity-registry";
import { getHostedClusterId } from "./utils";
import { ClusterStore } from "../common/cluster-store";
import type { ClusterId } from "../common/cluster-types";
import { watchHistoryState } from "./remote-helpers/history-updater";
import { unmountComponentAtNode } from "react-dom";
import { PortForwardDialog } from "../port-forward";
import { DeleteClusterDialog } from "./delete-cluster-dialog";
import { PortForwardDialog } from "./port-forward";
import { DeleteClusterDialog } from "./components/delete-cluster-dialog";
@observer
export class App extends React.Component {
export class ClusterFrame extends React.Component {
static clusterId: ClusterId;
static readonly logPrefix = "[CLUSTER-FRAME]:";
static displayName = "ClusterFrame";
constructor(props: {}) {
super(props);
@ -87,17 +89,14 @@ export class App extends React.Component {
catalogEntityRegistry.init();
const frameId = webFrame.routingId;
App.clusterId = getHostedClusterId();
ClusterFrame.clusterId = getHostedClusterId();
logger.info(`[APP]: Init dashboard, clusterId=${App.clusterId}, frameId=${frameId}`);
logger.info(`${ClusterFrame.logPrefix} Init dashboard, clusterId=${ClusterFrame.clusterId}, frameId=${frameId}`);
await Terminal.preloadFonts();
await requestMain(clusterSetFrameIdHandler, App.clusterId);
await requestMain(clusterSetFrameIdHandler, ClusterFrame.clusterId);
await ClusterStore.getInstance().getById(ClusterFrame.clusterId).whenReady; // cluster.activate() is done at this point
const cluster = ClusterStore.getInstance().getById(App.clusterId);
await cluster.whenReady; // cluster.activate() is done at this point
catalogEntityRegistry.activeEntity = App.clusterId;
catalogEntityRegistry.activeEntity = ClusterFrame.clusterId;
ExtensionLoader.getInstance().loadOnClusterRenderer();
setTimeout(() => {
@ -105,7 +104,7 @@ export class App extends React.Component {
name: "cluster",
action: "open",
params: {
clusterId: App.clusterId,
clusterId: ClusterFrame.clusterId,
},
});
});
@ -114,7 +113,7 @@ export class App extends React.Component {
});
window.onbeforeunload = () => {
logger.info(`[APP]: Unload dashboard, clusterId=${App.clusterId}, frameId=${frameId}`);
logger.info(`${ClusterFrame.logPrefix} Unload dashboard, clusterId=${ClusterFrame.clusterId}, frameId=${frameId}`);
unmountComponentAtNode(rootElem);
};
@ -225,7 +224,7 @@ export class App extends React.Component {
<CronJobTriggerDialog/>
<PortForwardDialog/>
<DeleteClusterDialog/>
<CommandContainer clusterId={App.clusterId}/>
<CommandContainer clusterId={ClusterFrame.clusterId}/>
</ErrorBoundary>
</Router>
);

View File

@ -54,7 +54,7 @@ import { ReplicaSetDetails } from "../components/+workloads-replicasets";
import { StatefulSetDetails } from "../components/+workloads-statefulsets";
import type { KubeObjectDetailsProps } from "../components/kube-object-details";
export function intiKubeObjectDetailRegistry() {
export function initKubeObjectDetailRegistry() {
KubeObjectDetailRegistry.getInstance()
.add([
{

View File

@ -43,7 +43,10 @@ import { ClusterFrameHandler } from "./components/cluster-manager/lens-views";
injectSystemCAs();
@observer
export class LensApp extends React.Component {
export class RootFrame extends React.Component {
static readonly logPrefix = "[ROOT-FRAME]:";
static displayName = "RootFrame";
static async init(rootElem: HTMLElement) {
catalogEntityRegistry.init();
ExtensionLoader.getInstance().loadOnClusterManagerRenderer();
@ -55,11 +58,10 @@ export class LensApp extends React.Component {
registerIpcListeners();
window.onbeforeunload = () => {
logger.info("[App]: Unload app");
window.addEventListener("beforeunload", () => {
logger.info(`${RootFrame.logPrefix} Unload app`);
unmountComponentAtNode(rootElem);
};
});
}
constructor(props: {}) {