Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/platforms/javascript/common/agent-tracing/openai.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 <PlatformLink to="/features/durableobject/">`instrumentDurableObjectWithSentry`</PlatformLink>. See <PlatformLink to="/tracing/distributed-tracing/#rpc-trace-propagation">RPC Trace Propagation</PlatformLink>.
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 <PlatformLink to="/features/durableobject/">`instrumentDurableObjectWithSentry`</PlatformLink>. See <PlatformLink to="/tracing/distributed-tracing/#rpc-trace-propagation">RPC Trace Propagation</PlatformLink>.

For multi-turn Conversations and the User column, see <PlatformLink to="/agent-tracing/#tracking-conversations">Tracking Conversations</PlatformLink> (`setConversationId` / `setUser`).

Expand Down
26 changes: 26 additions & 0 deletions docs/platforms/javascript/common/configuration/options.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,32 @@ If you want to disable trace propagation, you can set this option to `[]`.

</SdkOption>

<PlatformSection supported={['javascript.cloudflare']}>

<SdkOption name="rpcTracePropagationBindings" type='Array<string | RegExp>' availableSince='10.72.0'>

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 <PlatformLink to="/tracing/distributed-tracing/#rpc-trace-propagation">RPC Trace Propagation</PlatformLink>.

Propagation over `stub.fetch()` and service binding `fetch()` uses HTTP headers, so `tracePropagationTargets` covers it instead.

</SdkOption>

<SdkOption name="enableRpcTracePropagation" type='boolean' defaultValue='false' availableSince='10.49.0'>

**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.

</SdkOption>

</PlatformSection>

<SdkOption name="strictTraceContinuation" type='boolean' defaultValue='false' categorySupported={["server", "serverless"]}>

If set to `true`, the SDK will only continue a trace if the organization ID of the incoming trace found in the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <PlatformLink to="/tracing/distributed-tracing/#rpc-trace-propagation">RPC Trace Propagation</PlatformLink>.

`instrumentAgentWithSentry` works with `Agent` from `agents`, `AIChatAgent` from `@cloudflare/ai-chat`, and `McpAgent` from `agents/mcp`. When you build with the <PlatformLink to="/features/vite-plugin/">Sentry Cloudflare Vite plugin</PlatformLink>'s `autoInstrumentation`, the plugin detects and wraps Agent classes automatically.

## Conversation IDs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

<AvailableSince version="10.72.0" />

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 <PlatformLink to="/tracing/distributed-tracing/#rpc-trace-propagation">RPC Trace Propagation</PlatformLink>.

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

<SdkOption name="wranglerConfigPath" type="string" availableSince="10.69.0">
Expand Down Expand Up @@ -143,7 +155,7 @@ Experimental options that may change or be removed without notice.

<SdkOption name="_experimental.autoInstrumentation" type="boolean" defaultValue="false">

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).

</SdkOption>

Expand Down
Original file line number Diff line number Diff line change
@@ -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

<AvailableSince version="10.52.0" />

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.

<Alert level="warning" title="Performance Consideration">
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.
<Alert>
If you build with the <PlatformLink to="/features/vite-plugin/">Sentry Cloudflare Vite plugin</PlatformLink> 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.
</Alert>

**Worker Side (Caller):**
Expand All @@ -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) {
Expand All @@ -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 <PlatformLink to="/configuration/options/#rpcTracePropagationBindings">`rpcTracePropagationBindings`</PlatformLink>.

<Alert level="warning" title="Only List Receivers You Control">
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.
</Alert>

**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";

Expand All @@ -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.

<Alert>
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`.
</Alert>
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

Expand Down
Loading