fix: harden workbench trace timeout observability
This commit is contained in:
@@ -5,7 +5,7 @@ import assert from "node:assert/strict";
|
||||
import { test } from "bun:test";
|
||||
|
||||
import { createCloudApiServer } from "./server.ts";
|
||||
import { createWebPerformanceStore, webPerformanceRouteTemplate } from "./web-performance.ts";
|
||||
import { createWebPerformanceStore, emitWorkbenchUiOtelSpans, webPerformanceRouteTemplate } from "./web-performance.ts";
|
||||
|
||||
test("web performance store aggregates browser-perceived durations as Prometheus histograms", () => {
|
||||
const store = createWebPerformanceStore({ env: { HWLAB_METRICS_NAMESPACE: "hwlab-v02", HWLAB_GITOPS_TARGET: "v02" } });
|
||||
@@ -202,6 +202,53 @@ test("web performance store accepts Workbench UI lifecycle events without high-c
|
||||
assert.doesNotMatch(text, /ses_secret|trc_secret|ui_secret|0123456789abcdef|sessionId|traceId|otelTraceId|prompt|api key/iu);
|
||||
});
|
||||
|
||||
test("Workbench UI OTel spans include timeout activity diagnostics without raw trace ids", async () => {
|
||||
const calls: any[] = [];
|
||||
const originalFetch = globalThis.fetch;
|
||||
globalThis.fetch = async (_url: string | URL | Request, init?: RequestInit) => {
|
||||
calls.push(JSON.parse(String(init?.body ?? "{}")));
|
||||
return new Response(null, { status: 200 });
|
||||
};
|
||||
try {
|
||||
const result = await emitWorkbenchUiOtelSpans({
|
||||
schemaVersion: "hwlab-web-performance-v2",
|
||||
page: "/workbench/sessions/ses_secret",
|
||||
events: [{
|
||||
kind: "workbench_ui_event",
|
||||
eventType: "api_request",
|
||||
loadingScope: "api",
|
||||
state: "request",
|
||||
reason: "api_request",
|
||||
route: "/v1/workbench/turns/trc_secret",
|
||||
method: "GET",
|
||||
status: 0,
|
||||
outcome: "timeout",
|
||||
valueMs: 8001,
|
||||
uiTraceId: "ui_secret",
|
||||
otelTraceId: "0123456789abcdef0123456789abcdef",
|
||||
timeoutName: "workbench turn",
|
||||
activityWaitingFor: "code-agent",
|
||||
activityLastEventLabel: "realtime:heartbeat",
|
||||
activityIdleMs: 13042,
|
||||
traceId: "trc_secret"
|
||||
}]
|
||||
} as Record<string, unknown>, { OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: "http://otel.example/v1/traces" });
|
||||
|
||||
assert.equal(result.submitted, 1);
|
||||
assert.equal(calls.length, 1);
|
||||
const span = calls[0].resourceSpans[0].scopeSpans[0].spans[0];
|
||||
const attrs = Object.fromEntries(span.attributes.map((item: any) => [item.key, item.value.stringValue ?? Number(item.value.intValue) ?? item.value.boolValue]));
|
||||
assert.equal(attrs["http.route"], "/v1/workbench/turns/:id");
|
||||
assert.equal(attrs["workbench.ui.timeout_name"], "workbench turn");
|
||||
assert.equal(attrs["workbench.ui.activity_waiting_for"], "code-agent");
|
||||
assert.equal(attrs["workbench.ui.activity_last_event_label"], "realtime:heartbeat");
|
||||
assert.equal(attrs["workbench.ui.activity_idle_ms"], 13042);
|
||||
assert.doesNotMatch(JSON.stringify(calls[0]), /trc_secret|ses_secret|prompt|api key/iu);
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch;
|
||||
}
|
||||
});
|
||||
|
||||
test("web performance store drops unsupported Workbench labels and counts series limit drops", () => {
|
||||
const store = createWebPerformanceStore({ env: { HWLAB_METRICS_NAMESPACE: "hwlab-v03", HWLAB_GITOPS_TARGET: "v03" }, maxSeries: 1 });
|
||||
const first = store.record({
|
||||
|
||||
Reference in New Issue
Block a user