diff --git a/docs/platforms/javascript/common/agent-tracing/openai.mdx b/docs/platforms/javascript/common/agent-tracing/openai.mdx index abfdd61bb2a9dd..7cdb6b5b749c94 100644 --- a/docs/platforms/javascript/common/agent-tracing/openai.mdx +++ b/docs/platforms/javascript/common/agent-tracing/openai.mdx @@ -104,7 +104,7 @@ supported: ); ``` - If you call OpenAI from a Durable Object over RPC, set `enableRpcTracePropagation: true` on **both** the Worker (caller) and the DO (receiver). Wrap the DO with `instrumentDurableObjectWithSentry`. See RPC Trace Propagation. + If you call OpenAI from a Durable Object over RPC, set `rpcTracePropagationBindings` on both sides. On the Worker, list the Durable Object's binding. On the Durable Object, set the option to an empty array. Wrap the Durable Object with `instrumentDurableObjectWithSentry`. See RPC Trace Propagation. For multi-turn Conversations and the User column, see Tracking Conversations (`setConversationId` / `setUser`). diff --git a/docs/platforms/javascript/common/configuration/options.mdx b/docs/platforms/javascript/common/configuration/options.mdx index f4243ce6f2fa95..6a57dbed970387 100644 --- a/docs/platforms/javascript/common/configuration/options.mdx +++ b/docs/platforms/javascript/common/configuration/options.mdx @@ -575,6 +575,32 @@ If you want to disable trace propagation, you can set this option to `[]`. + + + + +Controls which bindings on `env` receive tracing data over [RPC calls](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/rpc/) to Durable Objects and other Workers. RPC has no headers, so the SDK appends the trace context as a trailing argument that an instrumented receiver strips again before your method runs. + +String entries must match a binding name exactly, so `"DB"` matches `"DB"` but not `"MY_DB"`. Use a regular expression for pattern matching. + +Setting this option, with any value, also lets the Worker continue a trace that arrives on an incoming RPC call. So a Worker that both calls and receives needs only this one option. Setting an empty array, the Worker is a receiver that propagates nothing, and an entry for a binding the Worker never calls is ignored. Because unused entries are harmless, one list can serve every Worker and Durable Object in a deployment. + +Only list bindings whose receiver runs Sentry. Anywhere else the trailing argument survives as a real parameter, which changes what your method was called with. See RPC Trace Propagation. + +Propagation over `stub.fetch()` and service binding `fetch()` uses HTTP headers, so `tracePropagationTargets` covers it instead. + + + + + +**Deprecated:** Use `rpcTracePropagationBindings` instead, which names the bindings you call rather than propagating to all of them. This option will be removed in the next major version. + +Propagates trace context over every RPC call on `env`, including bindings whose receiver doesn't run Sentry and therefore never strips the trailing argument again. + + + + + If set to `true`, the SDK will only continue a trace if the organization ID of the incoming trace found in the diff --git a/docs/platforms/javascript/guides/cloudflare/agent-tracing/agents-sdk.mdx b/docs/platforms/javascript/guides/cloudflare/agent-tracing/agents-sdk.mdx index 36d99b814d086a..82fbb3876e713a 100644 --- a/docs/platforms/javascript/guides/cloudflare/agent-tracing/agents-sdk.mdx +++ b/docs/platforms/javascript/guides/cloudflare/agent-tracing/agents-sdk.mdx @@ -27,12 +27,15 @@ export const MyAgent = Sentry.instrumentAgentWithSentry( (env: Env) => ({ dsn: "___PUBLIC_DSN___", tracesSampleRate: 1.0, - enableRpcTracePropagation: true, + // Lets the agent continue a trace sent over RPC. See RPC Trace Propagation. + rpcTracePropagationBindings: [], }), MyAgentBase ); ``` +The Worker that calls the agent names its binding in `rpcTracePropagationBindings`. See RPC Trace Propagation. + `instrumentAgentWithSentry` works with `Agent` from `agents`, `AIChatAgent` from `@cloudflare/ai-chat`, and `McpAgent` from `agents/mcp`. When you build with the Sentry Cloudflare Vite plugin's `autoInstrumentation`, the plugin detects and wraps Agent classes automatically. ## Conversation IDs diff --git a/docs/platforms/javascript/guides/cloudflare/features/vite-plugin.mdx b/docs/platforms/javascript/guides/cloudflare/features/vite-plugin.mdx index 5cd59556c6a746..e760be1efdf987 100644 --- a/docs/platforms/javascript/guides/cloudflare/features/vite-plugin.mdx +++ b/docs/platforms/javascript/guides/cloudflare/features/vite-plugin.mdx @@ -113,6 +113,18 @@ export const MyAgent = Sentry.instrumentAgentWithSentry( Use `instrumentDurableObjectWithSentry` for a plain Durable Object or `instrumentWorkflowWithSentry` for a Workflow. +#### Derived RPC Trace Propagation + + + +The plugin knows which bindings point at classes it wrapped itself: Durable Object bindings without a `script_name`, and service bindings naming this Worker. Those receivers are guaranteed to strip the trailing trace argument again, so the plugin adds their binding names to `rpcTracePropagationBindings`, which covers the calling and the receiving side alike. Traces then connect across RPC calls within one deployment, with no configuration of your own. + +Bindings to *other* Workers stay opt-in, because their receivers may not run Sentry. List those yourself in `instrument.server.*`; whatever you list is added on top of the derived names. See RPC Trace Propagation. + +The plugin derives only the classes it wrapped itself. A class you wrapped by hand, or one re-exported from another module, runs on its own options and stays out. + +This applies to Vite builds only. At runtime a `DurableObjectNamespace` exposes no origin and a `Fetcher` does not say which service it points at, so a plain wrangler build still has to list its bindings. + ## Options @@ -143,7 +155,7 @@ Experimental options that may change or be removed without notice. -Automatically wraps your Worker at build time so you don't have to edit your entry. The plugin reads your wrangler config, wraps the default export with `Sentry.withSentry()` (sourcing options from a co-located `instrument.server.*` file, falling back to `env`), and wraps configured classes with the matching helper: Durable Objects with `instrumentDurableObjectWithSentry`, Workflows with `instrumentWorkflowWithSentry`, and Agents SDK classes with `instrumentAgentWithSentry` (SDK version 10.69.0 or higher). Both `vite build` and `vite dev` are instrumented. +Automatically wraps your Worker at build time so you don't have to edit your entry. The plugin reads your wrangler config, wraps the default export with `Sentry.withSentry()` (sourcing options from a co-located `instrument.server.*` file, falling back to `env`), and wraps configured classes with the matching helper: Durable Objects with `instrumentDurableObjectWithSentry`, Workflows with `instrumentWorkflowWithSentry`, and Agents SDK classes with `instrumentAgentWithSentry` (SDK version 10.69.0 or higher). Both `vite build` and `vite dev` are instrumented. The plugin also adds the bindings that resolve to the wrapped classes to `rpcTracePropagationBindings` (SDK version 10.72.0 or higher). diff --git a/platform-includes/distributed-tracing/how-to-use/javascript.cloudflare.mdx b/platform-includes/distributed-tracing/how-to-use/javascript.cloudflare.mdx index 4efdba89fc5e78..47d4f89bdaf8ec 100644 --- a/platform-includes/distributed-tracing/how-to-use/javascript.cloudflare.mdx +++ b/platform-includes/distributed-tracing/how-to-use/javascript.cloudflare.mdx @@ -1,17 +1,17 @@ The Sentry Cloudflare SDK automatically propagates traces for incoming and outgoing HTTP requests if you've setup the SDK to send traces. -For RPC calls within Cloudflare (Worker-to-Durable Object, Worker-to-Worker via service bindings), trace propagation must be explicitly enabled. See [RPC Trace Propagation](#rpc-trace-propagation) below. +For RPC calls within Cloudflare (Worker-to-Durable Object, Worker-to-Worker via service bindings), you name the bindings that should carry the trace. See [RPC Trace Propagation](#rpc-trace-propagation) below. ### RPC Trace Propagation -By default, traces are not propagated across [RPC calls](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/rpc/) between Workers and Durable Objects. This is because [Cap'n Proto](https://capnproto.org/) (which powers Cloudflare RPC) has no native support for headers or metadata. +By default, traces are not propagated across [RPC calls](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/rpc/) between Workers and Durable Objects. This is because [Cap'n Proto](https://capnproto.org/) (which powers Cloudflare RPC) has no native support for headers or metadata. The SDK carries the trace context in a trailing argument instead, and the receiving SDK strips it before your method runs. -To enable trace propagation for RPC method calls, set `enableRpcTracePropagation: true` on **both** the caller and receiver sides. +That trailing argument is why propagation is opt-in per binding: only a Sentry-instrumented receiver strips it again. List the bindings whose receiver you know runs Sentry in `rpcTracePropagationBindings` (SDK version 10.72.0 or higher). Setting the option also turns on the receiver side, so a Worker that both calls and receives needs nothing else. - - RPC trace propagation requires instrumenting the environment bindings, which adds overhead to every RPC call. Only enable this option if you need distributed tracing across service boundaries. + + If you build with the Sentry Cloudflare Vite plugin and its `autoInstrumentation` option, the plugin configures the bindings that point at classes in the same Worker. You only need to list bindings to other Workers. **Worker Side (Caller):** @@ -23,7 +23,8 @@ export default Sentry.withSentry( (env) => ({ dsn: env.SENTRY_DSN, tracesSampleRate: 1.0, - enableRpcTracePropagation: true, + // Propagate to `env.MY_DURABLE_OBJECT` and every `env.SVC_*` binding + rpcTracePropagationBindings: ["MY_DURABLE_OBJECT", /^SVC_/], }), { async fetch(request, env, ctx) { @@ -39,8 +40,16 @@ export default Sentry.withSentry( ); ``` +Strings match a binding name exactly, so `"DB"` does not also match `MY_DB`. Use a regular expression for pattern matching. For the full definition, see `rpcTracePropagationBindings`. + + + A Worker that is not instrumented with Sentry never strips the trailing trace argument, so your method sees an extra parameter it was not called with. This is harmless for methods with fixed parameter lists, but changes behavior if your method uses rest parameters `(...args)` or reads `arguments.length`. Leave those bindings off the list. + + **Durable Object Side (Receiver):** +The receiver continues the trace it is sent, creates a span per RPC method, and strips the trailing argument, so your method signatures are unaffected. A Durable Object that only receives opts in with an empty list. + ```typescript import * as Sentry from "@sentry/cloudflare"; @@ -54,17 +63,14 @@ export const MyDurableObject = Sentry.instrumentDurableObjectWithSentry( (env: Env) => ({ dsn: env.SENTRY_DSN, tracesSampleRate: 1.0, - enableRpcTracePropagation: true, + // Receive traces over RPC, but propagate to nothing when calling out + rpcTracePropagationBindings: [], }), MyDurableObjectBase ); ``` -The SDK propagates trace context (`sentry-trace` and `baggage`) by appending a trailing argument to outgoing RPC calls. The receiving SDK automatically strips it before your method is executed. Your method signatures are unaffected. - - - If the receiving Worker is not instrumented with Sentry (or `enableRpcTracePropagation` is not enabled), the trailing trace argument won't be stripped and will be passed through to your method. This is harmless for methods with fixed parameter lists, but may cause unexpected behavior if your method relies on rest parameters `(...args)` or `arguments.length`. - +Listing bindings here does no harm, so you can reuse the caller's list and share one options object across the whole deployment. Every name on it already points at a Sentry receiver, and a binding the Durable Object never calls is simply never matched. ### Custom Instrumentation