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 storeConfig?: Config<T>;
protected syncDisposers: Disposer[] = []; protected syncDisposers: Disposer[] = [];
readonly displayName: string = this.constructor.name;
protected constructor(protected params: BaseStoreParams<T>) { protected constructor(protected params: BaseStoreParams<T>) {
super(); super();
makeObservable(this); 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) * This must be called after the last child's constructor is finished (or just before it finishes)
*/ */
load() { load() {
if (!isTestEnv) {
logger.info(`[${kebabCase(this.displayName).toUpperCase()}]: LOADING from ${this.path} ...`);
}
this.storeConfig = new Config({ this.storeConfig = new Config({
...this.params, ...this.params,
projectName: "lens", projectName: "lens",
@ -66,13 +72,13 @@ export abstract class BaseStore<T> extends Singleton {
const res: any = this.fromStore(this.storeConfig.store); const res: any = this.fromStore(this.storeConfig.store);
if (res instanceof Promise || (typeof res === "object" && res && typeof res.then === "function")) { 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(); this.enableSync();
if (!isTestEnv) { 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"; const initialStates = "cluster:states";
export class ClusterStore extends BaseStore<ClusterStoreModel> { export class ClusterStore extends BaseStore<ClusterStoreModel> {
readonly displayName = "ClusterStore";
clusters = observable.map<ClusterId, Cluster>(); clusters = observable.map<ClusterId, Cluster>();
protected disposer = disposer(); protected disposer = disposer();

View File

@ -35,6 +35,7 @@ export interface HotbarStoreModel {
} }
export class HotbarStore extends BaseStore<HotbarStoreModel> { export class HotbarStore extends BaseStore<HotbarStoreModel> {
readonly displayName = "HotbarStore";
@observable hotbars: Hotbar[] = []; @observable hotbars: Hotbar[] = [];
@observable private _activeHotbarId: string; @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) */ { export class UserStore extends BaseStore<UserStoreModel> /* implements UserStoreFlatModel (when strict null is enabled) */ {
readonly displayName = "UserStore";
constructor() { constructor() {
super({ super({
configName: "lens-user-store", configName: "lens-user-store",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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