diff --git a/src/mgr/server.ts b/src/mgr/server.ts index 805ef68..7ce541e 100644 --- a/src/mgr/server.ts +++ b/src/mgr/server.ts @@ -807,6 +807,7 @@ async function applyNamedAipodSpec(name: string, body: unknown, dir?: string): P } async function sendToSession(input: { store: AgentRunStore; sessionId: string; body: unknown; sourceCommit: string; runnerJobDefaults?: ManagerServerOptions["runnerJobDefaults"] }): Promise { + const startedAt = Date.now(); const record = asRecord(input.body ?? {}, "sessionSend"); const dryRun = record.dryRun === true; const existing = await input.store.getSession(input.sessionId); @@ -819,6 +820,8 @@ async function sendToSession(input: { store: AgentRunStore; sessionId: string; b const request = { method: "POST", path: `/api/v1/runs/${active.run.id}/commands`, commandType: "steer", payloadBytes: jsonByteLength(payload), valuesPrinted: false }; if (dryRun) return sessionSendPlan(input.sessionId, "steer", active, request, null); const command = await input.store.createCommand(active.run.id, validateCreateCommand(commandBody)); + void emitAgentRunOtelSpan("command_created", active.run, process.env, { command, startTimeMs: startedAt, kind: 2, attributes: { "http.method": "POST", "http.route": "/api/v1/sessions/:sessionId/send", "http.status_code": 200, decision: "steer", commandType: command.type, commandState: command.state } }); + void emitAgentRunOtelSpan("session_send", active.run, process.env, { command, startTimeMs: startedAt, kind: 2, attributes: { "http.method": "POST", "http.route": "/api/v1/sessions/:sessionId/send", "http.status_code": 200, decision: "steer", reusedActiveRun: true } }); return sessionSendResponse({ sessionId: input.sessionId, decision: "steer", run: active.run, command, runnerJob: null, activeBefore: active, dryRun: false }); } @@ -840,7 +843,9 @@ async function sendToSession(input: { store: AgentRunStore; sessionId: string; b }; if (dryRun) return sessionSendPlan(input.sessionId, "turn", active, request, runBody); const run = await input.store.createRun(validateCreateRun(runBody)); + void emitAgentRunOtelSpan("run_created", run, process.env, { startTimeMs: startedAt, kind: 2, attributes: { "http.method": "POST", "http.route": "/api/v1/sessions/:sessionId/send", "http.status_code": 200, decision: "turn", backendProfile: run.backendProfile, providerId: run.providerId } }); const command = await input.store.createCommand(run.id, validateCreateCommand(commandBody)); + void emitAgentRunOtelSpan("command_created", run, process.env, { command, startTimeMs: startedAt, kind: 2, attributes: { "http.method": "POST", "http.route": "/api/v1/sessions/:sessionId/send", "http.status_code": 200, decision: "turn", commandType: command.type, commandState: command.state } }); let runnerJob: JsonValue = null; if (createRunnerJob) { runnerJob = await createKubernetesRunnerJob({ @@ -849,7 +854,10 @@ async function sendToSession(input: { store: AgentRunStore; sessionId: string; b input: { ...runnerJobBody, commandId: command.id } as never, defaults: runnerJobDefaultsForRequest(input.runnerJobDefaults, input.sourceCommit), }) as unknown as JsonValue; + const runnerJobRecord = asJsonRecord(runnerJob); + void emitAgentRunOtelSpan("runner_job_created", run, process.env, { command, startTimeMs: startedAt, kind: 2, attributes: { "http.method": "POST", "http.route": "/api/v1/sessions/:sessionId/send", "http.status_code": 200, decision: "turn", jobName: stringJsonValue(runnerJobRecord?.jobName), namespace: stringJsonValue(runnerJobRecord?.namespace) } }); } + void emitAgentRunOtelSpan("session_send", run, process.env, { command, startTimeMs: startedAt, kind: 2, attributes: { "http.method": "POST", "http.route": "/api/v1/sessions/:sessionId/send", "http.status_code": 200, decision: "turn", createRunnerJob } }); return sessionSendResponse({ sessionId: input.sessionId, decision: "turn", run, command, runnerJob, activeBefore: active, dryRun: false }); }