fix: expose workbench cache observability
This commit is contained in:
@@ -300,6 +300,25 @@ function recordWorkbenchTurnReadMetric(options = {}, url, statusCode, body = {},
|
||||
});
|
||||
}
|
||||
|
||||
function recordWorkbenchCacheMetric(options = {}, url, body = {}, startedAt = nowMs()) {
|
||||
const performanceStore = options.backendPerformanceStore ?? options.backendPerformance;
|
||||
if (!performanceStore?.recordWorkbenchCache) return;
|
||||
const cache = body?.cache && typeof body.cache === "object" ? body.cache : null;
|
||||
if (!cache) return;
|
||||
performanceStore.recordWorkbenchCache({
|
||||
route: url?.pathname ?? "/v1/workbench",
|
||||
cacheKeyClass: cache.class,
|
||||
cacheStatus: cache.status,
|
||||
operation: "read",
|
||||
durationMs: nowMs() - startedAt,
|
||||
payloadBytes: cache.payloadBytes,
|
||||
cacheAgeMs: cache.cacheAgeMs,
|
||||
dbQueryAvoided: cache.dbQueryAvoided,
|
||||
freshnessSloMs: cache.freshnessSloMs,
|
||||
projectionSeq: cache.projectionSeq
|
||||
});
|
||||
}
|
||||
|
||||
function recordWorkbenchProjectionMetric(options = {}, { result = null, trace = null, projection = null, diagnostic = null } = {}) {
|
||||
const performanceStore = options.backendPerformanceStore ?? options.backendPerformance;
|
||||
if (!performanceStore?.recordWorkbenchProjection || !projection) return;
|
||||
@@ -405,6 +424,7 @@ async function authenticateWorkbenchRead(request, response, options) {
|
||||
}
|
||||
|
||||
async function handleWorkbenchSessionList(request, response, url, options, actor) {
|
||||
const startedAt = nowMs();
|
||||
if (url.searchParams.has("projectId") || url.searchParams.has("workspaceId")) return sendJson(response, 400, workbenchError("workbench_authority_removed", "Workbench session list is keyed by sessionId only."));
|
||||
const limit = boundedSessionListLimit(url.searchParams.get("limit"));
|
||||
const offset = cursorOffset(url.searchParams.get("cursor") ?? url.searchParams.get("after"));
|
||||
@@ -421,6 +441,7 @@ async function handleWorkbenchSessionList(request, response, url, options, actor
|
||||
includeSessionId: includeRouteId ?? null,
|
||||
actor: { id: actor.id, role: actor.role ?? "user", valuesRedacted: true }
|
||||
});
|
||||
recordWorkbenchCacheMetric(options, url, payload, startedAt);
|
||||
return sendJson(response, 200, payload);
|
||||
}
|
||||
|
||||
@@ -1147,6 +1168,7 @@ async function handleWorkbenchTurnSnapshot(response, url, options, actor, rawTur
|
||||
contractVersion: "workbench-turn-snapshot-v1",
|
||||
turn: snapshot,
|
||||
projection,
|
||||
cache: result.cache ?? null,
|
||||
projectionStatus: projection.projectionStatus,
|
||||
projectionHealth: projection.projectionHealth,
|
||||
lastProjectedSeq: projection.lastProjectedSeq,
|
||||
@@ -1162,10 +1184,12 @@ async function handleWorkbenchTurnSnapshot(response, url, options, actor, rawTur
|
||||
diagnostic: projection
|
||||
});
|
||||
recordWorkbenchTurnReadMetric(options, url, 200, body, startedAt);
|
||||
recordWorkbenchCacheMetric(options, url, body, startedAt);
|
||||
sendJson(response, 200, body);
|
||||
}
|
||||
|
||||
async function handleWorkbenchTraceEventPage(response, url, options, actor, rawTraceId) {
|
||||
const startedAt = nowMs();
|
||||
const traceId = safeTraceId(rawTraceId);
|
||||
if (!traceId) return sendJson(response, 400, workbenchError("invalid_trace_id", "traceId must start with trc_.", { traceId: rawTraceId }));
|
||||
const readModel = createWorkbenchReadModel(options, actor);
|
||||
@@ -1199,7 +1223,7 @@ async function handleWorkbenchTraceEventPage(response, url, options, actor, rawT
|
||||
page.blocker = blocker;
|
||||
}
|
||||
const responseProjection = page.blocker ? blockedTraceEventProjection(projection, page.blocker) : projection;
|
||||
sendJson(response, 200, {
|
||||
const body = {
|
||||
ok: true,
|
||||
status: page.blocker ? "blocked" : "succeeded",
|
||||
contractVersion: "workbench-trace-events-v1",
|
||||
@@ -1208,6 +1232,7 @@ async function handleWorkbenchTraceEventPage(response, url, options, actor, rawT
|
||||
threadId: safeOpaqueId(session?.threadId) ?? (textValue(session?.threadId) || null),
|
||||
...page,
|
||||
projection: responseProjection,
|
||||
cache: pageResult.cache ?? metadata.cache ?? null,
|
||||
projectionStatus: responseProjection.projectionStatus,
|
||||
projectionHealth: responseProjection.projectionHealth,
|
||||
lastProjectedSeq: responseProjection.lastProjectedSeq,
|
||||
@@ -1222,7 +1247,9 @@ async function handleWorkbenchTraceEventPage(response, url, options, actor, rawT
|
||||
durationMs: responseProjection.durationMs,
|
||||
valuesRedacted: true,
|
||||
secretMaterialStored: false
|
||||
});
|
||||
};
|
||||
recordWorkbenchCacheMetric(options, url, body, startedAt);
|
||||
sendJson(response, 200, body);
|
||||
}
|
||||
|
||||
function traceEventPageFromFacts(sourceEvents, options, metadata = {}) {
|
||||
|
||||
Reference in New Issue
Block a user