feat: add manager otel spans
This commit is contained in:
+49
-8
@@ -20,6 +20,7 @@ import { getProviderProfileConfig, getProviderProfileValidation, listBackendCapa
|
||||
import { listToolCredentials, setGithubSshToolCredential, showToolCredential } from "./tool-credentials.js";
|
||||
import { aipodSpecFromInput, applyAipodSpec, deleteAipodSpec, listAipodSpecs, renderAipodSpecByName, showAipodSpec } from "../common/aipod-specs.js";
|
||||
import { staticWorkReadyCapabilitySummary } from "../common/work-ready.js";
|
||||
import { emitAgentRunOtelSpan } from "../common/otel-trace.js";
|
||||
|
||||
function pvcOptions(defaults: { kubectlCommand?: string } | undefined): SessionPvcOptions {
|
||||
return defaults?.kubectlCommand ? { kubectlCommand: defaults.kubectlCommand } : {};
|
||||
@@ -652,17 +653,36 @@ async function route({ method, url, body, store, sourceCommit, authSummary, runn
|
||||
await refreshRunningQueueTasksForRead(store, queue);
|
||||
return await queueCommanderForRead(store, queue, url.searchParams.get("readerId"));
|
||||
}
|
||||
if (method === "POST" && path === "/api/v1/runs") return await store.createRun(validateCreateRun(body)) as unknown as JsonValue;
|
||||
if (method === "POST" && path === "/api/v1/runs") {
|
||||
const startedAt = Date.now();
|
||||
const run = await store.createRun(validateCreateRun(body));
|
||||
void emitAgentRunOtelSpan("run_created", run, process.env, { startTimeMs: startedAt, kind: 2, attributes: { "http.method": "POST", "http.route": "/api/v1/runs", "http.status_code": 200, backendProfile: run.backendProfile, providerId: run.providerId } });
|
||||
return run as unknown as JsonValue;
|
||||
}
|
||||
const runMatch = path.match(/^\/api\/v1\/runs\/([^/]+)$/u);
|
||||
if (method === "GET" && runMatch) return await store.getRun(runMatch[1] ?? "") as unknown as JsonValue;
|
||||
const eventMatch = path.match(/^\/api\/v1\/runs\/([^/]+)\/events$/u);
|
||||
if (method === "GET" && eventMatch) {
|
||||
const startedAt = Date.now();
|
||||
const runId = eventMatch[1] ?? "";
|
||||
const afterSeq = integerQuery(url, "afterSeq", 0);
|
||||
const limit = integerQuery(url, "limit", 100);
|
||||
return { items: await store.listEvents(eventMatch[1] ?? "", afterSeq, limit) as unknown as JsonValue };
|
||||
const run = await store.getRun(runId);
|
||||
const items = await store.listEvents(runId, afterSeq, limit);
|
||||
void emitAgentRunOtelSpan("projection_sync", run, process.env, { startTimeMs: startedAt, kind: 2, attributes: { "http.method": "GET", "http.route": "/api/v1/runs/:runId/events", "http.status_code": 200, afterSeq, limit, eventCount: items.length } });
|
||||
return { items: items as unknown as JsonValue };
|
||||
}
|
||||
const runResultMatch = path.match(/^\/api\/v1\/runs\/([^/]+)\/result$/u);
|
||||
if (method === "GET" && runResultMatch) return await buildRunResult(store, runResultMatch[1] ?? "", url.searchParams.get("commandId") ?? undefined) as JsonValue;
|
||||
if (method === "GET" && runResultMatch) {
|
||||
const startedAt = Date.now();
|
||||
const runId = runResultMatch[1] ?? "";
|
||||
const run = await store.getRun(runId);
|
||||
const commandId = url.searchParams.get("commandId") ?? undefined;
|
||||
const command = commandId ? await store.getCommand(commandId) : null;
|
||||
const result = await buildRunResult(store, runId, commandId) as JsonValue;
|
||||
void emitAgentRunOtelSpan("command_result", run, process.env, { command, startTimeMs: startedAt, kind: 2, attributes: { "http.method": "GET", "http.route": "/api/v1/runs/:runId/result", "http.status_code": 200, terminalStatus: typeof result === "object" && result !== null && !Array.isArray(result) ? (result as JsonRecord).terminalStatus ?? null : null } });
|
||||
return result;
|
||||
}
|
||||
const runCancelMatch = path.match(/^\/api\/v1\/runs\/([^/]+)\/cancel$/u);
|
||||
if (method === "POST" && runCancelMatch) {
|
||||
const record = body === null ? {} : asRecord(body, "cancel");
|
||||
@@ -670,16 +690,29 @@ async function route({ method, url, body, store, sourceCommit, authSummary, runn
|
||||
return await store.cancelRun(runCancelMatch[1] ?? "", reason) as unknown as JsonValue;
|
||||
}
|
||||
const commandCreateMatch = path.match(/^\/api\/v1\/runs\/([^/]+)\/commands$/u);
|
||||
if (method === "POST" && commandCreateMatch) return await store.createCommand(commandCreateMatch[1] ?? "", validateCreateCommand(body)) as unknown as JsonValue;
|
||||
if (method === "POST" && commandCreateMatch) {
|
||||
const startedAt = Date.now();
|
||||
const runId = commandCreateMatch[1] ?? "";
|
||||
const command = await store.createCommand(runId, validateCreateCommand(body));
|
||||
const run = await store.getRun(runId);
|
||||
void emitAgentRunOtelSpan("command_created", run, process.env, { command, startTimeMs: startedAt, kind: 2, attributes: { "http.method": "POST", "http.route": "/api/v1/runs/:runId/commands", "http.status_code": 200, commandType: command.type, commandState: command.state } });
|
||||
return command as unknown as JsonValue;
|
||||
}
|
||||
if (method === "GET" && commandCreateMatch) return { items: await store.listCommands(commandCreateMatch[1] ?? "", integerQuery(url, "afterSeq", 0), integerQuery(url, "limit", 20)) as unknown as JsonValue };
|
||||
const runnerJobMatch = path.match(/^\/api\/v1\/runs\/([^/]+)\/runner-jobs$/u);
|
||||
if (method === "POST" && runnerJobMatch) {
|
||||
return await createKubernetesRunnerJob({
|
||||
const startedAt = Date.now();
|
||||
const runId = runnerJobMatch[1] ?? "";
|
||||
const runnerJob = await createKubernetesRunnerJob({
|
||||
store,
|
||||
runId: runnerJobMatch[1] ?? "",
|
||||
runId,
|
||||
input: asRecord(body ?? {}, "runnerJob") as never,
|
||||
defaults: runnerJobDefaultsForRequest(runnerJobDefaults, sourceCommit),
|
||||
}) as unknown as JsonValue;
|
||||
}) as unknown as JsonRecord;
|
||||
const run = await store.getRun(runId);
|
||||
const command = typeof runnerJob.commandId === "string" ? await store.getCommand(runnerJob.commandId) : null;
|
||||
void emitAgentRunOtelSpan("runner_job_created", run, process.env, { command, startTimeMs: startedAt, kind: 2, attributes: { "http.method": "POST", "http.route": "/api/v1/runs/:runId/runner-jobs", "http.status_code": 200, jobName: typeof runnerJob.jobName === "string" ? runnerJob.jobName : null, namespace: typeof runnerJob.namespace === "string" ? runnerJob.namespace : null } });
|
||||
return runnerJob as unknown as JsonValue;
|
||||
}
|
||||
if (method === "GET" && runnerJobMatch) {
|
||||
const runId = runnerJobMatch[1] ?? "";
|
||||
@@ -700,7 +733,15 @@ async function route({ method, url, body, store, sourceCommit, authSummary, runn
|
||||
const commandShowMatch = path.match(/^\/api\/v1\/runs\/([^/]+)\/commands\/([^/]+)$/u);
|
||||
if (method === "GET" && commandShowMatch) return await store.getCommand(commandShowMatch[2] ?? "") as unknown as JsonValue;
|
||||
const commandResultMatch = path.match(/^\/api\/v1\/runs\/([^/]+)\/commands\/([^/]+)\/result$/u);
|
||||
if (method === "GET" && commandResultMatch) return await buildRunResult(store, commandResultMatch[1] ?? "", commandResultMatch[2] ?? "") as JsonValue;
|
||||
if (method === "GET" && commandResultMatch) {
|
||||
const startedAt = Date.now();
|
||||
const runId = commandResultMatch[1] ?? "";
|
||||
const commandId = commandResultMatch[2] ?? "";
|
||||
const [run, command] = await Promise.all([store.getRun(runId), store.getCommand(commandId)]);
|
||||
const result = await buildRunResult(store, runId, commandId) as JsonValue;
|
||||
void emitAgentRunOtelSpan("command_result", run, process.env, { command, startTimeMs: startedAt, kind: 2, attributes: { "http.method": "GET", "http.route": "/api/v1/runs/:runId/commands/:commandId/result", "http.status_code": 200, terminalStatus: typeof result === "object" && result !== null && !Array.isArray(result) ? (result as JsonRecord).terminalStatus ?? null : null } });
|
||||
return result;
|
||||
}
|
||||
if (method === "POST" && path === "/api/v1/runners/register") return await store.registerRunner(asRecord(body ?? {}, "runner")) as unknown as JsonValue;
|
||||
const claimMatch = path.match(/^\/api\/v1\/runs\/([^/]+)\/claim$/u);
|
||||
if (method === "POST" && claimMatch) {
|
||||
|
||||
Reference in New Issue
Block a user