diff --git a/docs/platforms/javascript/guides/flue/cloudflare.mdx b/docs/platforms/javascript/guides/flue/cloudflare.mdx index e5c274aa0189db..42cf6c2daf05d9 100644 --- a/docs/platforms/javascript/guides/flue/cloudflare.mdx +++ b/docs/platforms/javascript/guides/flue/cloudflare.mdx @@ -62,7 +62,7 @@ export default defineConfig({ }); ``` -The plugin registers the Flue instrumentation for you at build time, so you don't write an `instrument()` call as you do on Node.js. It instruments the other libraries your tools call at the same point, so their spans land in the agent's trace. +The plugin is required. It registers the Flue instrumentation for you at build time, so you don't write an `instrument()` call as you do on Node.js. It also instruments Flue's model library, `@earendil-works/pi-ai`, which is where model call spans come from, and the other libraries your tools call, so their spans land in the agent's trace. Each Flue agent runs in its own Durable Object, which is a separate isolate from your Worker entry. `Sentry.init()` has to run inside it, so create a module that wraps the generated agent Durable Object: @@ -137,6 +137,7 @@ See [`dataCollection` documentation](../configuration/options/#dataCollection) f ## Troubleshooting - **The agent runs but nothing reaches Sentry.** Confirm each agent module re-exports `cloudflare` from your `src/sentry.ts`. This is the most common cause, and it fails silently. +- **Agent and tool spans arrive, but no model calls.** Confirm `sentryCloudflareVitePlugin()` is in your Vite config and that you build with Vite. The SDK logs `Flue model calls are not being traced` when the plugin didn't run. - **`instrument.server.ts` has no effect.** That convention needs a worker entry named in Wrangler's `main`. Flue supplies its own virtual entry instead, so the file is never picked up. Use the Durable Object wrapper above. - **Token and cost values are doubled.** Remove the `createOpenTelemetryInstrumentation` call left over from the `flue add tooling sentry` blueprint. diff --git a/docs/platforms/javascript/guides/flue/index.mdx b/docs/platforms/javascript/guides/flue/index.mdx index 5a87966bc49b94..fe4e3d0ef52860 100644 --- a/docs/platforms/javascript/guides/flue/index.mdx +++ b/docs/platforms/javascript/guides/flue/index.mdx @@ -120,9 +120,9 @@ import "./instrument.ts"; Call `instrument()` once, at module scope. On Cloudflare the Vite plugin registers the instrumentation at build time instead; on Node there's no equivalent, so this call is what installs it. -### Run With the Sentry Loader +### Start With the Sentry Loader -Libraries like database drivers, caches, and `dataloader` are instrumented by a module transform that has to be installed before your app loads them. A Flue build imports your dependencies before `src/instrument.ts` runs, so start the server with the Sentry loader to catch them: +The `instrument()` call only covers agent and tool spans. Model calls are traced through Flue's model library, `@earendil-works/pi-ai`, and so are your tools' database drivers, caches, and libraries like `dataloader`. All of these are instrumented by a module transform that has to be installed before your app loads them. A Flue build imports your dependencies before `src/instrument.ts` runs, so always start the server with the Sentry loader, in development and production: ```json {filename:package.json} { @@ -133,7 +133,11 @@ Libraries like database drivers, caches, and `dataloader` are instrumented by a } ``` -Agent, model, and tool spans arrive without this, as do outgoing HTTP requests. Everything instrumented through the module transform needs it. + + +Without the loader, your agents still record agent and tool spans, but no model calls (`gen_ai.chat` spans), so token usage and cost are missing. The SDK logs a warning on the first model call when this happens. + + @@ -162,6 +166,7 @@ See [`dataCollection` documentation](./configuration/options/#dataCollection) fo - **Token and cost values are doubled.** Remove the `createOpenTelemetryInstrumentation` call left over from the `flue add tooling sentry` blueprint. Flue emits its own model spans through it, so both it and the SDK count the same turn. - **No AI spans at all.** Confirm `instrument(Sentry.createFlueInstrumentation())` actually runs. Importing `src/instrument.ts` at the top of `src/app.ts` runs it during app startup, before any agent takes a turn. +- **Agent and tool spans arrive, but no model calls.** The server started without the Sentry loader. Confirm every script that starts the server, including `dev`, sets `NODE_OPTIONS='--import=@sentry/node/import'`. The SDK logs `Flue model calls are not being traced` when the loader is missing. diff --git a/includes/flue/what-gets-captured.mdx b/includes/flue/what-gets-captured.mdx index 90aeb1922e8a3b..5a964ba2af646f 100644 --- a/includes/flue/what-gets-captured.mdx +++ b/includes/flue/what-gets-captured.mdx @@ -8,9 +8,7 @@ Sentry's Flue integration maps Flue's runtime operations to Sentry operations fo | Model turn | `gen_ai.chat` | | Tool execution | `gen_ai.execute_tool` | -Spans are tagged with `sentry.origin: auto.ai.flue` and carry the model, token usage, and finish reasons for the turn. - -A `chat` span also carries `flue.turn.purpose`, which is how you tell a context-compaction turn from a user-facing one. There's no conventional attribute for that distinction. +Agent and tool spans are tagged with `sentry.origin: auto.ai.flue`. Model calls come from Sentry's pi-ai instrumentation, since Flue sends them through `@earendil-works/pi-ai`, so `chat` spans are tagged with `sentry.origin: auto.ai.pi_ai` and carry the model, token usage, and finish reasons for the call. A tool that throws is captured as an error and its span is marked failed. Flue catches the throw and hands it back to the model as a tool result, so the error is reported as handled.