From 1da08c3242b531e0f987fff10ab05786a9061c81 Mon Sep 17 00:00:00 2001 From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com> Date: Sat, 29 Aug 2026 00:24:47 -0700 Subject: [PATCH] Annotate session init spans with catalog size counts --- apps/cloud/src/mcp/session-durable-object.ts | 27 ++++++++++++++++++- .../src/mcp/agent-session-durable-object.ts | 21 ++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/apps/cloud/src/mcp/session-durable-object.ts b/apps/cloud/src/mcp/session-durable-object.ts index 6b9963eb8..f6746ccf7 100644 --- a/apps/cloud/src/mcp/session-durable-object.ts +++ b/apps/cloud/src/mcp/session-durable-object.ts @@ -43,7 +43,11 @@ import { type McpExecutionOwnerRoute, } from "@executor-js/cloudflare/mcp/execution-owner-directory"; import { mcpSessionStub } from "@executor-js/cloudflare/mcp/session-stub"; -import { buildExecuteDescription, type ResumeResponse } from "@executor-js/execution"; +import { + buildExecuteDescription, + parseIntegrationInventory, + type ResumeResponse, +} from "@executor-js/execution"; import { acquireBuildSlot, type BuildSlotHandle } from "./session-build-semaphore"; // The DO meters executions just like the HTTP `/api/*` plane: it builds its @@ -182,6 +186,16 @@ const smokeRenderArtifactAfterQuickJsPreload: typeof smokeRenderArtifact = async // --------------------------------------------------------------------------- export class McpSessionDOSqlite extends McpAgentSessionDOBase { + // Set once per `buildMcpServer` call, read back by `sessionFootprintAttributes` + // so the counts land on the base's `McpSessionDO.init` span alongside + // `mcp.isolate.*` residency — see the comment at the `parseIntegrationInventory` + // call site below for why this is free to compute. + private lastSessionFootprint: Record = {}; + + protected override sessionFootprintAttributes(): Record { + return this.lastSessionFootprint; + } + protected override sessionTimeoutMs(): number { return positiveMilliseconds(env.MCP_SESSION_TIMEOUT_MS) ?? super.sessionTimeoutMs(); } @@ -327,6 +341,17 @@ export class McpSessionDOSqlite extends McpAgentSessionDOBase; + /** + * Cheap, count-only proxies for what the runtime `buildMcpServer` just built + * holds — e.g. connected-integration counts — attributed alongside + * `residencyAttributes()` on the same `McpSessionDO.init` span so per-session + * memory footprint is queryable next to isolate residency without a + * cross-span join. Empty by default: a host that has nothing free to read + * (or nothing beyond what `buildMcpServer` already returns) need not + * override this. MUST stay O(1)/O(count) over already-materialized state — + * never trigger a new query or serialize a catalog to compute these. + */ + protected sessionFootprintAttributes(): Record { + return {}; + } + protected withTelemetry( effect: Effect.Effect, _incoming?: IncomingTraceHeaders, @@ -1001,7 +1015,12 @@ export abstract class McpAgentSessionDOBase< // The gauge on the way up. Paired with the same attributes on // `mcp.session.idle_runtime_dispose`, this is what shows whether idle // sessions are actually giving their runtimes back in production. - yield* Effect.annotateCurrentSpan(residencyAttributes()); + // `sessionFootprintAttributes()` rides the same span so a heavy session + // can be attributed to what it holds, not just counted. + yield* Effect.annotateCurrentSpan({ + ...residencyAttributes(), + ...self.sessionFootprintAttributes(), + }); // Last statement, and pure bookkeeping: the runtime above is already // installed and serving. Losing the timestamp/alarm write to a platform // reset must not undo any of it — the in-memory clock is already set and