Skip to content

Conversation

@andreiborza
Copy link
Member

@andreiborza andreiborza commented Dec 2, 2025

Closes #18379

dependabot bot and others added 30 commits November 24, 2025 19:44
[Gitflow] Merge master into develop
It's often hard to notice when our Gitflow merge PRs fail due to merge
conflicts and the longer they are open the harder it will be to fix
these merge conflicts eventually.

e.g. #18314

This is an attempt at notifying us better when these happen by creating
an issue in our repo (did not actually test this yet so we might have to
go through some iterations 😅).

Idea by Abhi:
#18317 (review)
With this PR we stop breaking builds by simply re-exporting APIs that
make use of synchronous random APIs:
- `startSpan`
- `startSpanManual`
- `startInactiveSpan`

We do this with a naive approach of detecting a prod build phase and
returning a noop span in cases where we call these APIs. We hope to get
a more solid API for this from Vercel at some point so we can make this
more bulletproof. The current version will also still emit a warning in
webpack as the behaviour seems to change there.

This will only work for Turbopack as of now, as we still need to get rid
of build time instrumentation in webpack in order for this to work.

closes #17895
This PR is a result of
#18302. This ensures
that the types are checked throughout the development of the Cloudflare
SDK
#18322)

Fixes a bug reported in
#18318 where

```js
Sentry.logger.info('Test message', { key: 'value' }, { scope: customScope });
```

would not forward the `customScope` but instead drop the log all
together.
This PR adds parameterized routes for Remix SDK, similarly to the NextJS
SDK

Resolves: #16690
_Needs docs PR for the Vite plugin_

Adds automatic parameterization of Remix route IDs for transaction
naming. Converts internal Remix route file patterns to parameterized
paths similar to the other SDKs (`routes/user.$id` -> `/user/:id`).

- Created `sentryRemixVitePlugin` that extracts route information from
Remix builds and generates a manifest file containing route ID to
parameterized route mappings.
- Added `remixRouteParameterization.ts` with regex-based route
conversion that handles dynamic segments (`$param` → `:param`), splat
routes (`$` → `:*`), and nested routes.
- Updated both client and server instrumentation in `performance.tsx`
and `instrumentServer.ts` to use parameterized transaction names.
- It also works with Hydrogen

Vite plugin is used like:

```javascript
// vite.config.ts
import { defineConfig } from 'vite';
import { vitePlugin as remix } from '@remix-run/dev';
import { sentryRemixVitePlugin } from '@sentry/remix';

export default defineConfig({
  plugins: [
    remix(),
    sentryRemixVitePlugin({
      appDirPath: './app', // Default is 'app' in project root
    }),
  ],
});
```

Updated all Remix E2E test applications to expect parameterized route
names. Added new E2E test application `create-remix-app-v2-non-vite` for
testing backward compatibility for non-Vite builds - these continue to
use `routes/user.$id` format.

  ## Summary

| Route File | Example URL | Before | After (Server - All Apps) | After
(Client - Vite Plugin) |

|------------|-------------|--------|---------------------------|------------------------------|
| `_index.tsx` | `/` | `routes/_index` | `/` | `/` |
| `user.$id.tsx` | `/user/123` | `routes/user.$id` | `/user/:id` |
`/user/:id` |
| `users.$userId.posts.$postId.tsx` | `/users/123/posts/456` |
`routes/users.$userId.posts.$postId` | `/users/:userId/posts/:postId` |
`/users/:userId/posts/:postId` |
| `$.tsx` (splat) | `/docs/guide/intro` | `routes/$` | `/:*` | `/:*` |
| `docs.$.tsx` (scoped splat) | `/docs/guide/intro` | `routes/docs.$` |
`/docs/:*` | `/docs/:*` |

  ### Notes
- **Server-side**: Parameterization works automatically for all Remix
apps (Vite, non-Vite, Hydrogen, Express).
- **Client-side**: Requires the Vite plugin. Without it, client
transactions continue using route IDs (e.g., `routes/user.$id`).
This is part of the work done for supporting Next.js on cloudflare
workers in #14931, one of the issues is our flusher didn't take
cloudflare into account and the events were being cut off due to early
shutdowns by the worker environment.

We cannot use our core's `flushIfServerless` because it requires
explicit `cloudflareWaitUntil` to be passed down to it.

Also The symbol we are grabbing here is [specific to
opennext](https://github.com/opennextjs/opennextjs-cloudflare/blob/b53a046bd5c30e94a42e36b67747cefbf7785f9a/packages/cloudflare/src/cli/templates/init.ts#L17)
and isn't something that is globally available on the worker
environment. I had initially created #18330 because I mistook it for a
worker environment API thing.

So this PR adds that detection to Next.js since it is relevant here and
will use it if available, local tests show flushing is done correctly
and events aren't being cut off.
This PR adds support for LangChain v1.

## Changes

- LangChain v1 Response Metadata Extraction

- Updated response attribute extraction to support LangChain v1's
different data structure:

- Instrument ConfigurableModel from `chat_models/universal.cjs`

Quick context: 

The `initChatModel` unified API (introduced in LangChain v1) was not
being instrumented in CJS applications. This happened because:

1. `initChatModel` uses dynamic `import()` to load providers (even in
CJS mode)
2. OpenTelemetry's CJS instrumentation only hooks `require()`, not
dynamic `import()`
3. Provider packages like `@langchain/openai` were never being patched
when loaded via `initChatModel`

**Solution**: Added instrumentation for the main `langchain` package.
When `langchain/dist/chat_models/universal.cjs` is loaded, we patch the
`ConfigurableModel` prototype. Since `initChatModel` returns a
`ConfigurableModel` instance, it inherits the patched methods regardless
of how the provider is loaded.

This fix ensures `initChatModel` works in CJS applications without
requiring users to manually import provider packages.

- Add tests for node integrations tests testing v1 changes
- All existing tests continue to pass
- New v1 test suite validates:
    - Basic chat model spans with and without PII
    - Tool call instrumentation
    - Message truncation behavior
    - Timing issues with pre-imported clients
    - `initChatModel` API with OpenAI (now working in both ESM and CJS)

Closes https://linear.app/getsentry/issue/JS-1071/support-langchain-v1
…pan exists (#18328)

During investigation of [this
issue](#18296), we
discovered that `continueTrace` does not propagate the given trace ID if
it is called from within an already active span (in this instance this
happened because of the already active span started by the cloudflare
auto-instrumentation.

Solution: This PR resolves this behavior by setting the currently active
span to undefined when forking the propagation context in
`continueTrace`.

Tests:
- After introducing the fix one of the `@sentry/sveltekit` unit tests
started to fail. Not sure why this was triggered by this change, but I
fixed it by setting the `isSubRequest` property on the event instead of
the route, which seems correct to me.
- Added a unit test in `@sentry/core` that calls `continueTrace` inside
an active span and checks that the trace id is now propagated as we
would expect.
…#18338)

Just cleaning up, we won't be needing any of these. I am aware this is
breaking, but I think it's fine since we are still in alpha and these
are empty anyways.
We are exposing AI instrument methods for Langgraph enabling users to
use it directly from the browser SDK.
We are exposing AI instrument methods for Langchain enabling users to
use it directly from the browser SDK.
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to
6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/releases">actions/checkout's
releases</a>.</em></p>
<blockquote>
<h2>v6.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update README to include Node.js 24 support details and requirements
by <a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2248">actions/checkout#2248</a></li>
<li>Persist creds to a separate file by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2286">actions/checkout#2286</a></li>
<li>v6-beta by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2298">actions/checkout#2298</a></li>
<li>update readme/changelog for v6 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2311">actions/checkout#2311</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v5.0.0...v6.0.0">https://github.com/actions/checkout/compare/v5.0.0...v6.0.0</a></p>
<h2>v6-beta</h2>
<h2>What's Changed</h2>
<p>Updated persist-credentials to store the credentials under
<code>$RUNNER_TEMP</code> instead of directly in the local git
config.</p>
<p>This requires a minimum Actions Runner version of <a
href="https://github.com/actions/runner/releases/tag/v2.329.0">v2.329.0</a>
to access the persisted credentials for <a
href="https://docs.github.com/en/actions/tutorials/use-containerized-services/create-a-docker-container-action">Docker
container action</a> scenarios.</p>
<h2>v5.0.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Port v6 cleanup to v5 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2301">actions/checkout#2301</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v5...v5.0.1">https://github.com/actions/checkout/compare/v5...v5.0.1</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
<h2>V6.0.0</h2>
<ul>
<li>Persist creds to a separate file by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2286">actions/checkout#2286</a></li>
<li>Update README to include Node.js 24 support details and requirements
by <a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2248">actions/checkout#2248</a></li>
</ul>
<h2>V5.0.1</h2>
<ul>
<li>Port v6 cleanup to v5 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2301">actions/checkout#2301</a></li>
</ul>
<h2>V5.0.0</h2>
<ul>
<li>Update actions checkout to use node 24 by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2226">actions/checkout#2226</a></li>
</ul>
<h2>V4.3.1</h2>
<ul>
<li>Port v6 cleanup to v4 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2305">actions/checkout#2305</a></li>
</ul>
<h2>V4.3.0</h2>
<ul>
<li>docs: update README.md by <a
href="https://github.com/motss"><code>@​motss</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1971">actions/checkout#1971</a></li>
<li>Add internal repos for checking out multiple repositories by <a
href="https://github.com/mouismail"><code>@​mouismail</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1977">actions/checkout#1977</a></li>
<li>Documentation update - add recommended permissions to Readme by <a
href="https://github.com/benwells"><code>@​benwells</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2043">actions/checkout#2043</a></li>
<li>Adjust positioning of user email note and permissions heading by <a
href="https://github.com/joshmgross"><code>@​joshmgross</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2044">actions/checkout#2044</a></li>
<li>Update README.md by <a
href="https://github.com/nebuk89"><code>@​nebuk89</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2194">actions/checkout#2194</a></li>
<li>Update CODEOWNERS for actions by <a
href="https://github.com/TingluoHuang"><code>@​TingluoHuang</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2224">actions/checkout#2224</a></li>
<li>Update package dependencies by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2236">actions/checkout#2236</a></li>
</ul>
<h2>v4.2.2</h2>
<ul>
<li><code>url-helper.ts</code> now leverages well-known environment
variables by <a href="https://github.com/jww3"><code>@​jww3</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/1941">actions/checkout#1941</a></li>
<li>Expand unit test coverage for <code>isGhes</code> by <a
href="https://github.com/jww3"><code>@​jww3</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1946">actions/checkout#1946</a></li>
</ul>
<h2>v4.2.1</h2>
<ul>
<li>Check out other refs/* by commit if provided, fall back to ref by <a
href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1924">actions/checkout#1924</a></li>
</ul>
<h2>v4.2.0</h2>
<ul>
<li>Add Ref and Commit outputs by <a
href="https://github.com/lucacome"><code>@​lucacome</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1180">actions/checkout#1180</a></li>
<li>Dependency updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>- <a
href="https://redirect.github.com/actions/checkout/pull/1777">actions/checkout#1777</a>,
<a
href="https://redirect.github.com/actions/checkout/pull/1872">actions/checkout#1872</a></li>
</ul>
<h2>v4.1.7</h2>
<ul>
<li>Bump the minor-npm-dependencies group across 1 directory with 4
updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1739">actions/checkout#1739</a></li>
<li>Bump actions/checkout from 3 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1697">actions/checkout#1697</a></li>
<li>Check out other refs/* by commit by <a
href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1774">actions/checkout#1774</a></li>
<li>Pin actions/checkout's own workflows to a known, good, stable
version. by <a href="https://github.com/jww3"><code>@​jww3</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1776">actions/checkout#1776</a></li>
</ul>
<h2>v4.1.6</h2>
<ul>
<li>Check platform to set archive extension appropriately by <a
href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1732">actions/checkout#1732</a></li>
</ul>
<h2>v4.1.5</h2>
<ul>
<li>Update NPM dependencies by <a
href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1703">actions/checkout#1703</a></li>
<li>Bump github/codeql-action from 2 to 3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1694">actions/checkout#1694</a></li>
<li>Bump actions/setup-node from 1 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1696">actions/checkout#1696</a></li>
<li>Bump actions/upload-artifact from 2 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1695">actions/checkout#1695</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/actions/checkout/commit/1af3b93b6815bc44a9784bd300feb67ff0d1eeb3"><code>1af3b93</code></a>
update readme/changelog for v6 (<a
href="https://redirect.github.com/actions/checkout/issues/2311">#2311</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/71cf2267d89c5cb81562390fa70a37fa40b1305e"><code>71cf226</code></a>
v6-beta (<a
href="https://redirect.github.com/actions/checkout/issues/2298">#2298</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/069c6959146423d11cd0184e6accf28f9d45f06e"><code>069c695</code></a>
Persist creds to a separate file (<a
href="https://redirect.github.com/actions/checkout/issues/2286">#2286</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493"><code>ff7abcd</code></a>
Update README to include Node.js 24 support details and requirements (<a
href="https://redirect.github.com/actions/checkout/issues/2248">#2248</a>)</li>
<li>See full diff in <a
href="https://github.com/actions/checkout/compare/v5...v6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=5&new-version=6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Resolves: #18350

Fixes server validation errors for `contexts.trace.origin` values in the
React Router SDK.

---------

Co-authored-by: Lukas Stracke <lukas.stracke@sentry.io>
…port options (#18335)

Adds a new transport option to the Cloudflare provider, this allows
specifying a custom fetch implementation. This allows for [Workers
VPC](https://developers.cloudflare.com/workers-vpc/) to send into an
internal Sentry.

Example usage:
```js
export default Sentry.withSentry(
  (env: Env) => ({
    dsn: env.SENTRY_DSN,
    release: env.VERSION_METADATA.tag ?? env.VERSION_METADATA.id,
    transportOptions: {
      fetch: env.SENTRY_VPC_BRIDGE.fetch.bind(env.SENTRY_VPC_BRIDGE),
    },
  }),
  {
    async fetch(req, env) {
      return new Response("ok");
    },
};
```

---

Before submitting a pull request, please take a look at our

[Contributing](https://github.com/getsentry/sentry-javascript/blob/master/CONTRIBUTING.md)
guidelines and verify:

- [x] If you've added code that should be tested, please add tests.
- [x] Ensure your code lints and the test suite passes (`yarn lint`) &
(`yarn test`).
…are consumed (#18087)

Fixes:
https://linear.app/getsentry/issue/JS-1103/spans-are-not-flushed-to-dashboard-when-using-streamtext-with-vercel

The Cloudflare request wrapper was ending the root HTTP span immediately
when the handler returned a streaming Response (e.g.
`result.toTextStreamResponse()`). Since Vercel AI child spans only
finish after the stream is consumed by the client, they were filtered
out by Sentry's `isFullFinishedSpan` check, resulting in transactions
with 0 spans.

--------------

This PR implements a streaming response detection and handles this from
within the http handler:

1. Created `classifyResponseStreaming()` helper
- Detects streaming vs non streaming, via Content-Type (SSE),
Content-Length
   
2. Updated request wrapper
- Changed from `startSpan()` to `startSpanManual()` for manual span
control
   - Monitors streaming response consumption in background
   - Ends root span only after stream fully consumed by client
…sabled (#18337)

Currently, when using Sentry alongside a custom OpenTelemetry setup, any
spans started via our Sentry.startSpanX apis leak into the OpenTelemetry
setup even if tracing is disabled.

This fix suppresses tracing for span creation via our startSpanX apis
but ensures tracing is not suppressed within the callback so that for
example custom OTel spans created within Sentry.startSpanX calls are not
suppresed.

I update the `node-otel-without-tracing` e2e tests to reflect that no
Sentry spans leak into the OTLP endpoint, as well as trying this out
locally with an express app and Jaeger.

**Before** the fix, Sentry span leaks:
<img width="2608" height="1578" alt="Screenshot 2025-11-24 at 20 35 21"
src="https://github.com/user-attachments/assets/45284aac-b9c1-423d-b199-c1c9273d1980"
/>
<img width="2608" height="1578" alt="Screenshot 2025-11-24 at 20 34 53"
src="https://github.com/user-attachments/assets/ff1929e6-a195-4e4e-a45b-5bddf49a1c25"
/>
<hr>

**After** the fix, no Sentry span leakage
<img width="2608" height="1578" alt="Screenshot 2025-11-24 at 20 28 22"
src="https://github.com/user-attachments/assets/e6584c01-30ef-40f2-87bf-33ac1d81e302"
/>
<img width="2608" height="1578" alt="Screenshot 2025-11-24 at 20 28 32"
src="https://github.com/user-attachments/assets/4388bb01-9f7b-48ab-8bb4-c7129075c89c"
/>

Closes: #17826
This workflow checks PR descriptions (like this one) to see if it can
find an associated GitHub or Linear issue ID. If nothing is found, the
workflow will create a new GitHub Issue which will then be referenced in
this PR. As all other GitHub issues, this newly created one will then be
synced to Linear as well.

This will increase visibility of (community) PRs in external tools like
Linear.

Based on: getsentry/sentry-cocoa#6064 by
@stephanie-anderson

Closes #18364
…sport` (#10798)

Hoping to reduce complexity for setting up micro-frontends routing.

Also: I suppose we could just make Matcher argument optional instead of
exporting a separate function... that may be a cleaner design

---------

Co-authored-by: Luca Forstner <luca.forstner@sentry.io>
Co-authored-by: Andrei Borza <andrei.borza@sentry.io>
…act (#18369)

Export custom inits to send correct metadata with data sent from the
SDK.

Closes #18366
Currently `withMonitor()` reuses the same trace for all cron executions, 
making it impossible to distinguish between different runs in Sentry.

This patch adds an optional `isolateTrace: boolean` to `MonitorConfig`
that creates a separate trace for each monitor execution when enabled.

---------

Co-authored-by: Lukas Stracke <lukas.stracke@sentry.io>
It seems that the full URL of the issue was not checked against. This
now also allows full issue URLs (but only if they are in the `getsentry`
org). This came up in #18369
(closes #18360)

## Problem

In getsentry/sentry-mcp#652 we had to manually
wait for the flush to ensure that async operations completed before the
response was sent.

This was caused by the MCP server streaming data after the actual
request has been finished. When using the Cloudflare SDK with MCP
servers (or other streaming APIs), spans created during the streaming
phase were not being flushed properly because the `flush()` method would
complete before these async spans finished.

## Solution

During the request, when a span is created for the streaming call, we
now register listeners on the CloudflareClient for `spanStart` and
`spanEnd` events. The client tracks all pending spans and waits for them
to complete before flushing.

Specifically:
- Added `_pendingSpans` Set to track active span IDs
- Created a promise-based mechanism (`_spanCompletionPromise`) to wait
for all spans to complete
- Modified the `flush()` method to wait for pending spans before calling
`super.flush()`
- Added a timeout (default 5 seconds) to prevent indefinite waiting

## Test

Added a comprehensive E2E test application (`cloudflare-mcp`) that:
- Sets up a Cloudflare Worker with an MCP server
- Registers a tool that creates spans during execution
- Verifies that both the HTTP request span and the MCP tool call span
are properly sent to Sentry
- Validates span relationships (parent/child) and trace IDs

The test confirms that spans are now flushed correctly without manual
intervention.
… values during review (#18352)

based on the invalid origin values reported in
#18350 (and a bunch
more invalid values in other SDKs) let's make bugbot a bit smarter to
flag stuff like this in the future
…18361)

Bumps
[peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request)
from 7.0.8 to 7.0.9.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/peter-evans/create-pull-request/releases">peter-evans/create-pull-request's
releases</a>.</em></p>
<blockquote>
<h2>Create Pull Request v7.0.9</h2>
<p>⚙️ Fixes an <a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4228">incompatibility</a>
with the recently released <code>actions/checkout@v6</code>.</p>
<h2>What's Changed</h2>
<ul>
<li>~70 dependency updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a></li>
<li>docs: fix workaround description about <code>ready_for_review</code>
by <a href="https://github.com/ybiquitous"><code>@​ybiquitous</code></a>
in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/3939">peter-evans/create-pull-request#3939</a></li>
<li>Docs: <code>add-paths</code> default behavior by <a
href="https://github.com/joeflack4"><code>@​joeflack4</code></a> in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/3928">peter-evans/create-pull-request#3928</a></li>
<li>docs: update to create-github-app-token v2 by <a
href="https://github.com/Goooler"><code>@​Goooler</code></a> in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/4063">peter-evans/create-pull-request#4063</a></li>
<li>Fix compatibility with actions/checkout@v6 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/4230">peter-evans/create-pull-request#4230</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/joeflack4"><code>@​joeflack4</code></a>
made their first contribution in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/3928">peter-evans/create-pull-request#3928</a></li>
<li><a href="https://github.com/Goooler"><code>@​Goooler</code></a> made
their first contribution in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/4063">peter-evans/create-pull-request#4063</a></li>
<li><a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> made
their first contribution in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/4230">peter-evans/create-pull-request#4230</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/peter-evans/create-pull-request/compare/v7.0.8...v7.0.9">https://github.com/peter-evans/create-pull-request/compare/v7.0.8...v7.0.9</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/84ae59a2cdc2258d6fa0732dd66352dddae2a412"><code>84ae59a</code></a>
fix: compatibility with actions/checkout@v6 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4230">#4230</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/b4733b9419fd47bbfa1807b15627e17cd70b5b22"><code>b4733b9</code></a>
build(deps-dev): bump js-yaml from 4.1.0 to 4.1.1 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4222">#4222</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/0edc001d28a2959cd7a6b505629f1d82f0a6e67d"><code>0edc001</code></a>
build(deps-dev): bump the npm group with 2 updates (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4201">#4201</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/430aea0fb112656c3ac187e7a22b3604508ba3a7"><code>430aea0</code></a>
build(deps): bump the github-actions group with 3 updates (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4200">#4200</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/46cdba753c74545733b821043d64bd6925fc4da9"><code>46cdba7</code></a>
build(deps-dev): bump the npm group with 3 updates (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4185">#4185</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/b937339b17ca3e45ec14ebcafb879873b1ee8564"><code>b937339</code></a>
build(deps): bump the github-actions group with 2 updates (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4184">#4184</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/e9af275c3778a67411fcac2d613e8d4e9be452fd"><code>e9af275</code></a>
ci: update dependabot config</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/d3e081a03ae8d69301ed924bae10d70ea4af94d9"><code>d3e081a</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.127 to
18.19.128 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4178">#4178</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/9ec683ee07f9121fdf529b923931dd78d977a5c9"><code>9ec683e</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.125 to
18.19.127 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4165">#4165</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/65d8d10bf76513796c0f69457c2567b5da3b9626"><code>65d8d10</code></a>
build(deps-dev): bump ts-jest from 29.4.2 to 29.4.4 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4163">#4163</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/peter-evans/create-pull-request/compare/271a8d0340265f705b14b6d32b9829c1cb33d45e...84ae59a2cdc2258d6fa0732dd66352dddae2a412">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=peter-evans/create-pull-request&package-manager=github_actions&previous-version=7.0.8&new-version=7.0.9)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Comment on lines 163 to 173
}
},
);
}

// Non-streaming response - end span immediately and return original
span.end();
waitUntil?.(flush(2000));
return res;
});
},
);
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Streaming response spans never end if context is undefined, leading to lost transaction data.
Severity: CRITICAL | Confidence: High

🔍 Detailed Analysis

When wrapperOptions.context is undefined, waitUntil also becomes undefined. For streaming responses, the streamMonitor function, which contains span.end() in its finally block, is conditionally scheduled using waitUntil?.(streamMonitor). If waitUntil is undefined, streamMonitor is never executed, preventing span.end() from being called. This leaves the span open indefinitely and prevents events from being flushed, leading to lost transaction data and incomplete traces, particularly in scenarios like Astro prerendering (see GitHub issue #13217).

💡 Suggested Fix

Ensure span.end() is called reliably for streaming responses even when waitUntil is undefined. This might involve always awaiting streamMonitor or providing a synchronous fallback for span.end() if waitUntil is unavailable.

🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: packages/cloudflare/src/request.ts#L98-L173

Potential issue: When `wrapperOptions.context` is `undefined`, `waitUntil` also becomes
`undefined`. For streaming responses, the `streamMonitor` function, which contains
`span.end()` in its `finally` block, is conditionally scheduled using
`waitUntil?.(streamMonitor)`. If `waitUntil` is `undefined`, `streamMonitor` is never
executed, preventing `span.end()` from being called. This leaves the span open
indefinitely and prevents events from being flushed, leading to lost transaction data
and incomplete traces, particularly in scenarios like Astro prerendering (see GitHub
issue #13217).

Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 4859966

@github-actions
Copy link
Contributor

github-actions bot commented Dec 2, 2025

size-limit report 📦

Path Size % Change Change
@sentry/browser 24.8 kB added added
@sentry/browser - with treeshaking flags 23.31 kB added added
@sentry/browser (incl. Tracing) 41.54 kB added added
@sentry/browser (incl. Tracing, Profiling) 46.13 kB added added
@sentry/browser (incl. Tracing, Replay) 79.96 kB added added
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 69.69 kB added added
@sentry/browser (incl. Tracing, Replay with Canvas) 84.64 kB added added
@sentry/browser (incl. Tracing, Replay, Feedback) 96.88 kB added added
@sentry/browser (incl. Feedback) 41.48 kB added added
@sentry/browser (incl. sendFeedback) 29.49 kB added added
@sentry/browser (incl. FeedbackAsync) 34.47 kB added added
@sentry/react 26.52 kB added added
@sentry/react (incl. Tracing) 43.74 kB added added
@sentry/vue 29.25 kB added added
@sentry/vue (incl. Tracing) 43.34 kB added added
@sentry/svelte 24.82 kB added added
CDN Bundle 27.21 kB added added
CDN Bundle (incl. Tracing) 42.21 kB added added
CDN Bundle (incl. Tracing, Replay) 78.75 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback) 84.2 kB added added
CDN Bundle - uncompressed 79.96 kB added added
CDN Bundle (incl. Tracing) - uncompressed 125.34 kB added added
CDN Bundle (incl. Tracing, Replay) - uncompressed 241.37 kB added added
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 254.13 kB added added
@sentry/nextjs (client) 45.96 kB added added
@sentry/sveltekit (client) 41.9 kB added added
@sentry/node-core 51.27 kB added added
@sentry/node 159.44 kB added added
@sentry/node - without tracing 92.85 kB added added
@sentry/aws-serverless 108.14 kB added added

'server.address': {
type: 'string',
value: 'M6QX4Q5HKV.local',
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Test has hardcoded hostname that will fail in CI

The test expects a hardcoded hostname value 'M6QX4Q5HKV.local' for the server.address attribute, which is a developer's local machine hostname. This test will fail in CI and on any other developer's machine since the hostname will differ. The value should use expect.any(String) like other dynamic values in this test (e.g., sentry.sdk.version).

Additional Locations (2)

Fix in Cursor Fix in Web

dsn: process.env.E2E_TEST_DSN,
tunnel: 'http://localhost:3031/', // proxy server
tracesSampleRate: 1.0, // Capture 100% of the transactions, reduce in production!
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Duplicate Sentry.init with wrong tunnel port

The test application has two Sentry.init calls with conflicting tunnel ports. The entry.server.tsx uses tunnel: 'http://localhost:3031/' while instrument.server.cjs uses port 3032. The event proxy server runs on port 3032. Since instrument.server.cjs is loaded first via --require and entry.server.tsx initializes after, the second init call may override the correct tunnel configuration, causing server-side events to be sent to port 3031 where nothing is listening.

Additional Locations (1)

Fix in Cursor Fix in Web

@github-actions
Copy link
Contributor

github-actions bot commented Dec 2, 2025

node-overhead report 🧳

Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.

Scenario Requests/s % of Baseline Prev. Requests/s Change %
GET Baseline 9,328 - - added
GET With Sentry 1,748 19% - added
GET With Sentry (error only) 6,077 65% - added
POST Baseline 1,200 - - added
POST With Sentry 594 50% - added
POST With Sentry (error only) 1,055 88% - added
MYSQL Baseline 3,353 - - added
MYSQL With Sentry 475 14% - added
MYSQL With Sentry (error only) 2,728 81% - added

@andreiborza andreiborza merged commit 294527c into master Dec 2, 2025
396 of 398 checks passed
@andreiborza andreiborza deleted the prepare-release/10.28.0 branch December 2, 2025 14:31
JPeer264 added a commit that referenced this pull request Dec 2, 2025
…es (#18380)

We don't need to add tickets for our internal releases such as
#18378, [Gitflow
automations](#18255)
or [contributor
updates](#15156)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.