mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-01-01 23:32:02 +00:00
Added health metrics for application load and database load (#2257)
* Added health metrics for application load * Added health metrics for application load * Fix unit tests * Added more metrics * Added few comments * Added DatabaseLoad Scenario and address comments * Fix unit tests * fix unit tests * Fix unit tests * fix unit tests * fix the mock * Fix unit tests
This commit is contained in:
@@ -38,6 +38,9 @@ import { ContainerConnectionInfo, IPhoenixServiceInfo, IProvisionData, IResponse
|
||||
import * as ViewModels from "../Contracts/ViewModels";
|
||||
import { UploadDetailsRecord } from "../Contracts/ViewModels";
|
||||
import { GitHubOAuthService } from "../GitHub/GitHubOAuthService";
|
||||
import MetricScenario from "../Metrics/MetricEvents";
|
||||
import { ApplicationMetricPhase } from "../Metrics/ScenarioConfig";
|
||||
import { scenarioMonitor } from "../Metrics/ScenarioMonitor";
|
||||
import { PhoenixClient } from "../Phoenix/PhoenixClient";
|
||||
import * as ExplorerSettings from "../Shared/ExplorerSettings";
|
||||
import { Action, ActionModifiers } from "../Shared/Telemetry/TelemetryConstants";
|
||||
@@ -402,7 +405,9 @@ export default class Explorer {
|
||||
updatedDatabases = [...updatedDatabases, ...deltaDatabases.toAdd].sort((db1, db2) =>
|
||||
db1.id().localeCompare(db2.id()),
|
||||
);
|
||||
useDatabases.setState({ databases: updatedDatabases });
|
||||
useDatabases.setState({ databases: updatedDatabases, databasesFetchedSuccessfully: true });
|
||||
scenarioMonitor.completePhase(MetricScenario.DatabaseLoad, ApplicationMetricPhase.DatabasesFetched);
|
||||
|
||||
await this.refreshAndExpandNewDatabases(deltaDatabases.toAdd, updatedDatabases);
|
||||
} catch (error) {
|
||||
const errorMessage = getErrorMessage(error);
|
||||
@@ -416,6 +421,8 @@ export default class Explorer {
|
||||
startKey,
|
||||
);
|
||||
logConsoleError(`Error while refreshing databases: ${errorMessage}`);
|
||||
useDatabases.setState({ databasesFetchedSuccessfully: false });
|
||||
scenarioMonitor.failPhase(MetricScenario.DatabaseLoad, ApplicationMetricPhase.DatabasesFetched);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1183,6 +1190,11 @@ export default class Explorer {
|
||||
}
|
||||
|
||||
public async refreshExplorer(): Promise<void> {
|
||||
// Start DatabaseLoad scenario before fetching databases
|
||||
if (userContext.apiType !== "Postgres" && userContext.apiType !== "VCoreMongo") {
|
||||
scenarioMonitor.start(MetricScenario.DatabaseLoad);
|
||||
}
|
||||
|
||||
if (userContext.apiType !== "Postgres" && userContext.apiType !== "VCoreMongo") {
|
||||
userContext.authType === AuthType.ResourceToken
|
||||
? this.refreshDatabaseForResourceToken()
|
||||
|
||||
@@ -35,6 +35,15 @@ import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
import { updateUserContext } from "../../../UserContext";
|
||||
import Explorer from "../../Explorer";
|
||||
|
||||
jest.mock("rx-jupyter", () => ({
|
||||
sessions: {
|
||||
create: jest.fn(),
|
||||
},
|
||||
contents: {
|
||||
JupyterContentProvider: jest.fn().mockImplementation(() => ({})),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock("Common/dataAccess/queryDocuments", () => ({
|
||||
queryDocuments: jest.fn(() => ({
|
||||
// Omit headers, because we can't mock a private field and we don't need to test it
|
||||
|
||||
@@ -19,6 +19,15 @@ import { act } from "react-dom/test-utils";
|
||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
import Explorer from "../../Explorer";
|
||||
|
||||
jest.mock("rx-jupyter", () => ({
|
||||
sessions: {
|
||||
create: jest.fn(),
|
||||
},
|
||||
contents: {
|
||||
JupyterContentProvider: jest.fn().mockImplementation(() => ({})),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.requireActual("Explorer/Controls/Editor/EditorReact");
|
||||
|
||||
const PROPERTY_VALUE = "__SOME_PROPERTY_VALUE__";
|
||||
|
||||
@@ -6,6 +6,15 @@ import { updateUserContext, userContext } from "../../UserContext";
|
||||
import Explorer from "../Explorer";
|
||||
import Database from "./Database";
|
||||
|
||||
jest.mock("rx-jupyter", () => ({
|
||||
sessions: {
|
||||
create: jest.fn(),
|
||||
},
|
||||
contents: {
|
||||
JupyterContentProvider: jest.fn().mockImplementation(() => ({})),
|
||||
},
|
||||
}));
|
||||
|
||||
const createMockContainer = (): Explorer => {
|
||||
const mockContainer = new Explorer();
|
||||
return mockContainer;
|
||||
|
||||
@@ -17,6 +17,7 @@ import { ReactTabKind, useTabs } from "hooks/useTabs";
|
||||
import * as React from "react";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import shallow from "zustand/shallow";
|
||||
import { useDatabaseLoadScenario } from "../../Metrics/useMetricPhases";
|
||||
import Explorer from "../Explorer";
|
||||
import { useNotebook } from "../Notebook/useNotebook";
|
||||
|
||||
@@ -53,6 +54,7 @@ export const ResourceTree: React.FC<ResourceTreeProps> = ({ explorer }: Resource
|
||||
resourceTokenCollection: state.resourceTokenCollection,
|
||||
sampleDataResourceTokenCollection: state.sampleDataResourceTokenCollection,
|
||||
}));
|
||||
const databasesFetchedSuccessfully = useDatabases((state) => state.databasesFetchedSuccessfully);
|
||||
const { isCopilotEnabled, isCopilotSampleDBEnabled } = useQueryCopilot((state) => ({
|
||||
isCopilotEnabled: state.copilotEnabled,
|
||||
isCopilotSampleDBEnabled: state.copilotSampleDBEnabled,
|
||||
@@ -114,6 +116,9 @@ export const ResourceTree: React.FC<ResourceTreeProps> = ({ explorer }: Resource
|
||||
}
|
||||
}, [databaseTreeNodes, sampleDataNodes]);
|
||||
|
||||
// Track complete DatabaseLoad scenario (start, tree rendered, interactive)
|
||||
useDatabaseLoadScenario(databaseTreeNodes, databasesFetchedSuccessfully);
|
||||
|
||||
useEffect(() => {
|
||||
// Compute open items based on node.isExpanded
|
||||
const updateOpenItems = (node: TreeNode, parentNodeId: string): void => {
|
||||
|
||||
@@ -9,6 +9,7 @@ interface DatabasesState {
|
||||
databases: ViewModels.Database[];
|
||||
resourceTokenCollection: ViewModels.CollectionBase;
|
||||
sampleDataResourceTokenCollection: ViewModels.CollectionBase;
|
||||
databasesFetchedSuccessfully: boolean; // Track if last database fetch was successful
|
||||
updateDatabase: (database: ViewModels.Database) => void;
|
||||
addDatabases: (databases: ViewModels.Database[]) => void;
|
||||
deleteDatabase: (database: ViewModels.Database) => void;
|
||||
@@ -30,6 +31,7 @@ export const useDatabases: UseStore<DatabasesState> = create((set, get) => ({
|
||||
databases: [],
|
||||
resourceTokenCollection: undefined,
|
||||
sampleDataResourceTokenCollection: undefined,
|
||||
databasesFetchedSuccessfully: false,
|
||||
updateDatabase: (updatedDatabase: ViewModels.Database) =>
|
||||
set((state) => {
|
||||
const updatedDatabases = state.databases.map((database: ViewModels.Database) => {
|
||||
|
||||
Reference in New Issue
Block a user