fix: depollute v02 web performance telemetry
This commit is contained in:
@@ -57,7 +57,8 @@ assertIncludes(appSource, "CommandBar", "command bar component must exist");
|
||||
assertIncludes(appSource, "PerformanceView", "performance view component must exist");
|
||||
assertIncludes(appSource, "SkillsView", "skills component must exist");
|
||||
assertIncludes(appSource, "SettingsView", "settings component must exist");
|
||||
assertIncludes(appTsx, "useWorkbenchStore(auth.authState === \"authenticated\")", "Workbench data requests must wait until auth is authenticated");
|
||||
assertIncludes(appTsx, "const workspaceRoute = route === \"workspace\"", "React runtime must explicitly identify workspace route before starting workbench data flows");
|
||||
assertIncludes(appTsx, "useWorkbenchStore(auth.authState === \"authenticated\" && workspaceRoute)", "Workbench data requests must wait until auth is authenticated and workspace route is active");
|
||||
assertIncludes(apiClientSource, "adapter: (): Promise<ApiResult<LiveProbePayload>> => fetchJson(\"/v1/rpc/system.health\", { method: \"POST\"", "adapter health must use POST /v1/rpc/system.health");
|
||||
assertIncludes(appSource, "selectVisibleDevicePodId", "Device Pod detail probes must be selected from the authenticated visible list");
|
||||
assertIncludes(appSource, "api.devicePods()", "Device Pod list must be fetched before detail probes");
|
||||
|
||||
@@ -45,8 +45,9 @@ const routeLabels: Record<RouteId, string> = {
|
||||
|
||||
export function App(): ReactElement {
|
||||
const auth = useAuth();
|
||||
const store = useWorkbenchStore(auth.authState === "authenticated");
|
||||
const [route, setRoute] = useState<RouteId>(() => routeFromLocation());
|
||||
const workspaceRoute = route === "workspace";
|
||||
const store = useWorkbenchStore(auth.authState === "authenticated" && workspaceRoute);
|
||||
const [pickedDraft, setPickedDraft] = useState<string | null>(null);
|
||||
const [leftCollapsed, setLeftCollapsed] = useState(false);
|
||||
const [rightCollapsed, setRightCollapsed] = useState(false);
|
||||
@@ -113,7 +114,6 @@ export function App(): ReactElement {
|
||||
}, [route]);
|
||||
|
||||
const modelLabel = useMemo(() => store.state.providerProfile === "codex-api" ? "Codex API" : store.state.providerProfile === "minimax-m3" ? "MiniMax-M3" : "DeepSeek", [store.state.providerProfile]);
|
||||
const workspaceRoute = route === "workspace";
|
||||
const sessionSidebarVisible = workspaceRoute && !leftCollapsed;
|
||||
const devicePodSidebarVisible = workspaceRoute && !rightCollapsed;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { test } from "bun:test";
|
||||
|
||||
import { __resetWebPerformanceTelemetryForTest, webPerformanceRouteTemplate, webPerformanceStatusClass } from "./rum";
|
||||
import { __resetWebPerformanceTelemetryForTest, recordApiTiming, webPerformanceRouteTemplate, webPerformanceStatusClass } from "./rum";
|
||||
|
||||
test("web performance route templates remove high-cardinality identifiers", () => {
|
||||
assert.equal(webPerformanceRouteTemplate("/v1/agent/chat/result/trc_abc123456789"), "/v1/agent/chat/result/:id");
|
||||
@@ -17,3 +17,36 @@ test("web performance status class keeps API labels low-cardinality", () => {
|
||||
assert.equal(webPerformanceStatusClass("bad"), "network");
|
||||
__resetWebPerformanceTelemetryForTest();
|
||||
});
|
||||
|
||||
test("web performance telemetry does not record observability page API calls", () => {
|
||||
const previousWindow = globalThis.window;
|
||||
const previousDocument = globalThis.document;
|
||||
const previousPerformance = globalThis.performance;
|
||||
const previousFetch = globalThis.fetch;
|
||||
const events = [];
|
||||
globalThis.window = {
|
||||
location: { hash: "#/performance", origin: "http://web.test" },
|
||||
setTimeout: (handler: TimerHandler) => {
|
||||
if (typeof handler === "function") handler();
|
||||
return 0;
|
||||
},
|
||||
clearTimeout: () => undefined
|
||||
} as unknown as Window & typeof globalThis;
|
||||
globalThis.document = {} as Document;
|
||||
globalThis.performance = {} as Performance;
|
||||
globalThis.fetch = (async (_path: string, init?: RequestInit) => {
|
||||
events.push(JSON.parse(String(init?.body ?? "{}")));
|
||||
return new Response("{}", { status: 202, headers: { "content-type": "application/json" } });
|
||||
}) as typeof fetch;
|
||||
try {
|
||||
recordApiTiming({ path: "/v1/live-builds", durationMs: 1200, status: 200, outcome: "ok" });
|
||||
recordApiTiming({ path: "/v1/web-performance/summary", durationMs: 600, status: 200, outcome: "ok" });
|
||||
assert.equal(events.length, 0);
|
||||
} finally {
|
||||
globalThis.window = previousWindow;
|
||||
globalThis.document = previousDocument;
|
||||
globalThis.performance = previousPerformance;
|
||||
globalThis.fetch = previousFetch;
|
||||
__resetWebPerformanceTelemetryForTest();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -77,7 +77,7 @@ export function installWebPerformanceTelemetry(): void {
|
||||
export function recordApiTiming(input: ApiTimingInput): void {
|
||||
if (!browserRuntimeAvailable()) return;
|
||||
const route = webPerformanceRouteTemplate(input.path);
|
||||
if (route === TELEMETRY_ENDPOINT) return;
|
||||
if (isObservabilityRoute(route) || currentPageRoute() === "/performance") return;
|
||||
const durationMs = finitePositive(input.durationMs, 0);
|
||||
if (durationMs <= 0) return;
|
||||
enqueueWebPerformanceEvent({
|
||||
@@ -205,6 +205,7 @@ function enqueueDuration(kind: WebPerformanceKind, metric: string, route: string
|
||||
|
||||
function enqueueWebPerformanceEvent(event: WebPerformanceEvent): void {
|
||||
if (!browserRuntimeAvailable()) return;
|
||||
if (isObservabilityPageRoute(currentPageRoute())) return;
|
||||
queue.push(event);
|
||||
if (queue.length > MAX_QUEUE_EVENTS) queue = queue.slice(queue.length - MAX_QUEUE_EVENTS);
|
||||
scheduleFlush();
|
||||
@@ -222,6 +223,10 @@ function flushWebPerformanceQueue(useBeacon: boolean): void {
|
||||
flushTimer = null;
|
||||
}
|
||||
if (queue.length === 0) return;
|
||||
if (isObservabilityPageRoute(currentPageRoute())) {
|
||||
queue = [];
|
||||
return;
|
||||
}
|
||||
const events = queue.splice(0, MAX_BATCH_EVENTS);
|
||||
const payload = JSON.stringify({
|
||||
schemaVersion: PAYLOAD_SCHEMA_VERSION,
|
||||
@@ -248,6 +253,14 @@ function currentPageRoute(): string {
|
||||
return webPerformanceRouteTemplate(hash || "/workspace");
|
||||
}
|
||||
|
||||
function isObservabilityRoute(route: string): boolean {
|
||||
return route === TELEMETRY_ENDPOINT || route.startsWith(`${TELEMETRY_ENDPOINT}/`);
|
||||
}
|
||||
|
||||
function isObservabilityPageRoute(route: string): boolean {
|
||||
return route === "/performance";
|
||||
}
|
||||
|
||||
function supportsEntryType(type: string): boolean {
|
||||
const supported = PerformanceObserver.supportedEntryTypes;
|
||||
return Array.isArray(supported) && supported.includes(type);
|
||||
|
||||
Reference in New Issue
Block a user