Files
cosmos-explorer/src/Metrics/useMetricPhases.ts
sunghyunkang1111 fb250259ed Perf/copilot cleanup and optimizations (#2447)
* perf: remove deprecated copilot feature, add ARM timeouts, fix race conditions

- Remove entire QueryCopilot feature (~50 files deleted, ~30 files cleaned)
- Remove CopilotConfigured and SampleDataLoaded metric phases
- Fix DatabaseTreeRendered 76% stuck rate (remove one-shot guard in useMetricPhases)
- Add 8s default timeout to ARM requests (AbortController-based)
- Fix MSAL token forceRefresh (true -> false, use cache)
- Add concurrency limit of 5 to collection loading in Explorer
- Remove orphaned SampleDataClient.ts and queryCopilotSampleData.json
- Clean up dead sampleDataConnectionInfo field from UserContext

* Clean up copilot and optimize initialization

* Clean up copilot and optimize initialization
2026-04-08 11:25:33 -05:00

64 lines
2.4 KiB
TypeScript

import React from "react";
import MetricScenario from "./MetricEvents";
import { ApplicationMetricPhase, CommonMetricPhase } from "./ScenarioConfig";
import { scenarioMonitor } from "./ScenarioMonitor";
/**
* Completes the Interactive phase once the browser is ready to paint.
*
* Uses requestAnimationFrame with a setTimeout fallback. In foreground tabs rAF fires
* first (~16 ms) giving an accurate "browser painted" signal. In background tabs browsers
* suspend rAF indefinitely, so the setTimeout fallback (1 s) completes the phase instead —
* well within the 10 s scenario timeout — preventing false-negative unhealthy reports.
*/
export function useInteractive(scenario: MetricScenario, enabled = true) {
React.useEffect(() => {
if (!enabled) {
return undefined;
}
let completed = false;
const complete = () => {
if (completed) {
return;
}
completed = true;
cancelAnimationFrame(rafId);
clearTimeout(timeoutId);
scenarioMonitor.completePhase(scenario, CommonMetricPhase.Interactive);
};
const rafId = requestAnimationFrame(complete);
// Fallback for background tabs where rAF is suspended.
const timeoutId = setTimeout(complete, 1000);
return () => {
cancelAnimationFrame(rafId);
clearTimeout(timeoutId);
};
}, [scenario, enabled]);
}
/**
* Hook to manage DatabaseLoad scenario phase completions.
* Tracks tree rendering and completes Interactive phase.
* Only attempts to complete DatabaseTreeRendered if the database fetch was successful.
* Note: Scenario must be started before databases are fetched (in refreshExplorer).
*
* No one-shot guard is needed — completePhase is idempotent (ScenarioMonitor returns
* early if the phase hasn't been started yet, is already completed, or is already
* emitted). This lets the effect safely re-fire on every databaseTreeNodes change
* until the phase has actually been started via startPhase() in Explorer.tsx.
*/
export function useDatabaseLoadScenario(databaseTreeNodes: unknown[], fetchSucceeded: boolean) {
// Track DatabaseTreeRendered phase (only if fetch succeeded)
React.useEffect(() => {
if (fetchSucceeded) {
scenarioMonitor.completePhase(MetricScenario.DatabaseLoad, ApplicationMetricPhase.DatabaseTreeRendered);
}
}, [databaseTreeNodes, fetchSucceeded]);
// Track Interactive phase
useInteractive(MetricScenario.DatabaseLoad);
}