Merge pull request #1694 from pikasTech/codex/hwlab-1691-attribution
fix: scope workbench performance attribution health
This commit is contained in:
@@ -249,6 +249,51 @@ test("web performance summary exposes Workbench p75 and low-sample diagnostics w
|
||||
assert.doesNotMatch(json, /trc_secret|ses_secret|run_secret|cmd_secret|traceId|sessionId|runId|commandId|conversationId|prompt|api key/iu);
|
||||
});
|
||||
|
||||
test("web performance collection health only requires backend attribution for backend-scoped Workbench series", () => {
|
||||
const frontendOnly = createWebPerformanceStore({ env: { HWLAB_METRICS_NAMESPACE: "hwlab-v03", HWLAB_GITOPS_TARGET: "v03" } });
|
||||
frontendOnly.record({
|
||||
schemaVersion: "hwlab-web-performance-v2",
|
||||
page: "/workbench",
|
||||
events: Array.from({ length: 5 }, () => ({
|
||||
kind: "workbench_journey",
|
||||
journey: "workbench_open_first_visible",
|
||||
route: "/workbench",
|
||||
cache: "warm",
|
||||
authState: "warm",
|
||||
visibility: "foreground",
|
||||
outcome: "ok",
|
||||
valueMs: 120
|
||||
}))
|
||||
});
|
||||
const frontendSummary = frontendOnly.summary();
|
||||
assert.equal(frontendSummary.collectionHealth.status, "fresh");
|
||||
assert.equal(frontendSummary.collectionHealth.unknownAttribution.workbenchRows, 1);
|
||||
assert.equal(frontendSummary.collectionHealth.unknownAttribution.attributableRows, 0);
|
||||
assert.equal(frontendSummary.collectionHealth.unknownAttribution.rowsWithUnknown, 0);
|
||||
assert.equal(frontendSummary.collectionHealth.diagnostics.some((item) => item.code === "unknown_attribution"), false);
|
||||
|
||||
const backendScoped = createWebPerformanceStore({ env: { HWLAB_METRICS_NAMESPACE: "hwlab-v03", HWLAB_GITOPS_TARGET: "v03" } });
|
||||
backendScoped.record({
|
||||
schemaVersion: "hwlab-web-performance-v2",
|
||||
page: "/workbench/sessions/ses_secret",
|
||||
events: Array.from({ length: 5 }, () => ({
|
||||
kind: "workbench_journey",
|
||||
journey: "submit_to_first_visible",
|
||||
route: "/workbench/sessions/ses_secret",
|
||||
entry: "existing",
|
||||
visibility: "foreground",
|
||||
outcome: "ok",
|
||||
valueMs: 600
|
||||
}))
|
||||
});
|
||||
const backendSummary = backendScoped.summary();
|
||||
assert.equal(backendSummary.collectionHealth.status, "degraded");
|
||||
assert.equal(backendSummary.collectionHealth.unknownAttribution.attributableRows, 1);
|
||||
assert.equal(backendSummary.collectionHealth.unknownAttribution.rowsWithUnknown, 1);
|
||||
assert.equal(backendSummary.collectionHealth.unknownAttribution.samplesWithUnknown, 5);
|
||||
assert.equal(backendSummary.collectionHealth.diagnostics.some((item) => item.code === "unknown_attribution"), true);
|
||||
});
|
||||
|
||||
test("web performance store accepts Workbench UI lifecycle events without high-cardinality labels", () => {
|
||||
const store = createWebPerformanceStore({ env: { HWLAB_METRICS_NAMESPACE: "hwlab-v03", HWLAB_GITOPS_TARGET: "v03" } });
|
||||
const result = store.record({
|
||||
|
||||
@@ -287,6 +287,7 @@ interface PerformanceCollectionHealth {
|
||||
sourceFamilyCounts: Array<{ sourceFamily: string; rowCount: number; sampleCount: number }>;
|
||||
unknownAttribution: {
|
||||
workbenchRows: number;
|
||||
attributableRows: number;
|
||||
rowsWithUnknown: number;
|
||||
samplesWithUnknown: number;
|
||||
backendUnknownRows: number;
|
||||
@@ -1623,11 +1624,18 @@ function collectionSourceFamilyCounts(rows: PerformanceSummaryRow[]) {
|
||||
|
||||
function collectionUnknownAttribution(rows: PerformanceSummaryRow[]) {
|
||||
const workbenchRows = rows.filter((row) => row.kind === "workbench_journey" || row.kind === "workbench_event_phase" || row.kind === "workbench_backend_event_visible");
|
||||
const backendUnknownRows = workbenchRows.filter((row) => unknownAttributionValue(row.backend)).length;
|
||||
const transportUnknownRows = workbenchRows.filter((row) => unknownAttributionValue(row.transport)).length;
|
||||
const rowsWithUnknown = workbenchRows.filter((row) => unknownAttributionValue(row.backend) || unknownAttributionValue(row.transport)).length;
|
||||
const samplesWithUnknown = workbenchRows.reduce((sum, row) => sum + ((unknownAttributionValue(row.backend) || unknownAttributionValue(row.transport)) ? Math.max(0, Number(row.count) || 0) : 0), 0);
|
||||
return { workbenchRows: workbenchRows.length, rowsWithUnknown, samplesWithUnknown, backendUnknownRows, transportUnknownRows };
|
||||
const attributionRows = workbenchRows.filter(rowNeedsWorkbenchAttribution);
|
||||
const backendUnknownRows = attributionRows.filter((row) => unknownAttributionValue(row.backend)).length;
|
||||
const transportUnknownRows = attributionRows.filter((row) => unknownAttributionValue(row.transport)).length;
|
||||
const rowsWithUnknown = attributionRows.filter((row) => unknownAttributionValue(row.backend) || unknownAttributionValue(row.transport)).length;
|
||||
const samplesWithUnknown = attributionRows.reduce((sum, row) => sum + ((unknownAttributionValue(row.backend) || unknownAttributionValue(row.transport)) ? Math.max(0, Number(row.count) || 0) : 0), 0);
|
||||
return { workbenchRows: workbenchRows.length, attributableRows: attributionRows.length, rowsWithUnknown, samplesWithUnknown, backendUnknownRows, transportUnknownRows };
|
||||
}
|
||||
|
||||
function rowNeedsWorkbenchAttribution(row: PerformanceSummaryRow) {
|
||||
if (row.kind === "workbench_event_phase" || row.kind === "workbench_backend_event_visible") return true;
|
||||
if (row.kind !== "workbench_journey") return false;
|
||||
return row.metric === "submit_to_first_visible" || row.metric === "submit_to_failure" || row.metric === "backend_event_to_visible";
|
||||
}
|
||||
|
||||
function unknownAttributionValue(value: unknown) {
|
||||
|
||||
@@ -468,7 +468,7 @@ export interface WebPerformanceCollectionHealth extends Record<string, unknown>
|
||||
secondsSinceLastSample?: number | null;
|
||||
windowCoverageSeconds?: number | null;
|
||||
sourceFamilyCounts?: Array<{ sourceFamily?: string; rowCount?: number; sampleCount?: number; [key: string]: unknown }>;
|
||||
unknownAttribution?: { workbenchRows?: number; rowsWithUnknown?: number; samplesWithUnknown?: number; backendUnknownRows?: number; transportUnknownRows?: number; [key: string]: unknown };
|
||||
unknownAttribution?: { workbenchRows?: number; attributableRows?: number; rowsWithUnknown?: number; samplesWithUnknown?: number; backendUnknownRows?: number; transportUnknownRows?: number; [key: string]: unknown };
|
||||
diagnostics?: WebPerformanceCollectionHealthDiagnostic[];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user