Skip to content

Commit 15e0626

Browse files
committed
Merge remote-tracking branch 'origin/develop' into sig/nuxt-vite-server-bootstrap
# Conflicts: # CHANGELOG.md
2 parents 634bdac + 869b92c commit 15e0626

188 files changed

Lines changed: 5794 additions & 1692 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.cursor/BUGBOT.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ Keep reviews high-signal. Prefer actionable, high-confidence findings over specu
4949
- When calling any `startSpan` API (`startInactiveSpan`, `startSpanManual`, etc), always ensure that the following span attributes are set:
5050
- `SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN` (`'sentry.origin'`) with a proper span origin
5151
- a proper origin must only contain [a-z], [A-Z], [0-9], `_` and `.` characters.
52+
- a proper origin has at most four parts, `<type>.<category>.<integration_name>.<integration_part>`, and must not skip a part. `type` is `auto` or `manual`.
53+
- `category` must be a span op category (e.g. `http`, `db`, `queue`, `function`, `ai`, `ui`, `rpc`), matching the span's op. Flag origins that put a library or vendor in the category slot (e.g. `auto.kafkajs.producer` instead of `auto.queue.kafkajs.producer`).
54+
- the origin identifies the integration, not the tooling behind it. Flag leftover implementation markers like `otel` or `orchestrion` used as a part.
5255
- flag any non-conforming origin values as invalid and link to the trace origin specification (https://develop.sentry.dev/sdk/telemetry/traces/trace-origin/)
5356
- `SEMANTIC_ATTRIBUTE_SENTRY_OP` (`'sentry.op'`) with a proper span op
5457
- Span ops should be lower case only, and use snake_case. The `.` character is used to delimit op parts.
@@ -78,6 +81,7 @@ Keep reviews high-signal. Prefer actionable, high-confidence findings over specu
7881
- What to do instead: Use an existing reference to the scope or client. For example, this is possible in most `Integration` hooks.
7982
- Flag hard-coded attribute names and span ops (e.g. `'sentry.origin'`, `'sentry.op'`, `'http.request.method'`, `'db.system.name'`) when `@sentry/conventions` exports a constant for them. Use the constant from `@sentry/conventions/attributes` (e.g. `SENTRY_ORIGIN`, `SENTRY_OP`) or `@sentry/conventions/op` instead. Do not flag values that have no constant in `@sentry/conventions`.
8083
- Flag unnecessary `span.setAttribute(s)` calls: If data is already available at span start, it must be set via the `attributes` option of `startSpan`, `startSpanManual`, `startInactiveSpan` or `startIdleSpan` calls. This ensures that as much context as possible is available when `tracesSampler` or `ignoreSpans` SDK options are applied. If a `span.setAttribute(s)` call happens at a later time than right after span start and the attribute value can only be computed at that time, do not flag it.
84+
- Flag a new option on an integration for incoming HTTP requests that is not in `ServerRequestOptions` (`packages/core/src/integrations/http/server-request-options.ts`), when it applies to more than one runtime. These integrations are Node `httpIntegration`, Deno `denoHttpIntegration` and `denoServeIntegration`, Bun `bunHttpServerIntegration` and `bunServerIntegration`, and Cloudflare `httpServerIntegration`. Add the option to `ServerRequestOptions`, then support it in each runtime or list it as unsupported in that runtime's `CheckServerRequestOptions` check. Also flag a runtime option that matches a shared option in purpose but has a different name or meaning.
8185

8286
### Code quality
8387

‎.github/workflows/flaky-test-detector.yml‎

Lines changed: 0 additions & 71 deletions
This file was deleted.

‎.github/workflows/pr-review-reminder.yml‎

Lines changed: 0 additions & 37 deletions
This file was deleted.

‎AGENTS.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ Uses **Git Flow** (see `docs/gitflow.md`).
7979
- `Sentry.init()` follows one rule for repeated calls: the first call wins. See
8080
`docs/repeated-init.md` before you add or change an `init()`.
8181

82+
- Span origins must follow the [trace origin spec](https://develop.sentry.dev/sdk/telemetry/traces/trace-origin/):
83+
`<type>.<category>.<integration_name>.<integration_part>`, at most four parts, no skipped
84+
parts, only `[a-zA-Z0-9_]` within a part. `category` is the span op category
85+
(`auto.queue.kafkajs.producer`, not `auto.kafkajs.producer`). Don't encode tooling like
86+
`otel` or `orchestrion` in the origin.
87+
8288
## Linting & Formatting
8389

8490
- This project uses **Oxlint** and **Oxfmt** — NOT ESLint or Prettier

‎CHANGELOG.md‎

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott
66

7+
Work in this release was contributed by @faizansaiyed123, @itisrmk, @kunal649, @kyrylolvov, @seongwon030, and @larcane97. Thank you for your contributions!
8+
79
### Important Changes
810

911
- **feat(nuxt): Start the server SDK on the Nuxt Vite server (experimental) ([#25524](https://github.com/getsentry/sentry-javascript/pull/25524))**
@@ -12,7 +14,49 @@
1214

1315
Development mode, Cloudflare, automatic capture of server rendering errors, and connecting server and browser traces via HTML meta tags are not yet supported. This experimental support may change in minor releases.
1416

15-
Work in this release was contributed by @faizansaiyed123, @itisrmk, @seongwon030, and @kyrylolvov. Thank you for your contributions!
17+
- **feat(cloudflare): Add incoming request span options to `httpServerIntegration`**
18+
19+
Cloudflare's `httpServerIntegration` now accepts `ignoreIncomingRequests`, `ignoreStaticAssets`, `spans`, `onSpanCreated` and `onSpanEnd`, with the same meaning as in the Node, Deno and Bun integrations. The callbacks receive the web `Request`.
20+
21+
`ignoreStaticAssets` defaults to `true`, so workers no longer create spans for `GET` requests to common static assets such as `favicon.ico`, `robots.txt` or `*.js` files. To keep these spans, set `httpServerIntegration({ ignoreStaticAssets: false })`. Request spans also follow the client's tracing configuration by default, so the SDK does not start them when tracing is disabled. If `ignoreRequestBody` throws, the request no longer fails, and the SDK skips the body.
22+
23+
- **feat(node, bun, deno, cloudflare): Align portable exports across server SDKs**
24+
25+
Node, Bun, Deno and Cloudflare now export the same helpers from `@sentry/core` and `@sentry/server-utils` where they work on that runtime:
26+
27+
- Node and Bun now export `moduleMetadataIntegration`, `instrumentPostgresJsSql`, `instrumentCreateReactAgent`, `awsIntegration` and the `FlueOptions` type. `awsIntegration` was already in their default integrations.
28+
- Deno and Cloudflare now export `parameterize` and `instrumentStateGraphCompile`.
29+
- Bun and Cloudflare now export the `Log` and `LogSeverityLevel` types.
30+
- Deno now exports `fastifyIntegration`, which was already in its default integrations.
31+
32+
- **feat(cloudflare): Let users configure the channel integrations**
33+
34+
When the `@sentry/cloudflare/vite` plugin bundles an instrumented package (for example `pg` or `openai`), the SDK adds the matching integration with its default options. `@sentry/cloudflare` now exports these integrations, so you can set their options, for example in `instrument.server.ts`:
35+
36+
```ts
37+
export default Sentry.defineCloudflareOptions(env => ({
38+
dsn: env.SENTRY_DSN,
39+
integrations: [Sentry.openAIIntegration({ recordInputs: false, recordOutputs: false })],
40+
}));
41+
```
42+
43+
These integrations need the vite plugin. Without it, they record nothing, and with `debug: true` the SDK logs a warning.
44+
45+
- **ref(deno, bun): Use a shared request handler wrapper for `Deno.serve` and `Bun.serve`**
46+
47+
`Deno.serve` and `Bun.serve` now use the same request handler wrapper, which Cloudflare will also use. On both runtimes, errors in `OPTIONS` and `HEAD` requests now carry the request data, and the SDK keeps every `Set-Cookie` header of a response instead of only the last one.
48+
49+
For Deno users:
50+
51+
- When the source of a streamed response fails, the SDK now captures the error and marks the span as failed.
52+
- The SDK no longer reads a streamed response ahead of the client.
53+
54+
`Bun.serve` spans now follow the Sentry conventions for `http.server` spans, as on Node, Deno and Cloudflare:
55+
56+
- `url.template` is now `http.route`. Routes without parameters also get `http.route` and the `route` source.
57+
- `url.domain` is now `server.address`.
58+
- A request to `/` gets the `route` source and the name `GET /`.
59+
- Spans also get `user_agent.original` and `http.request.body.size`.
1660

1761
## 11.9.0
1862

@@ -203,6 +247,24 @@ Work in this release was contributed by @faizansaiyed123, @itisrmk, @seongwon030
203247

204248
Work in this release was contributed by @4ktLuffy, @adityareddy-dev, @dasilvaluis, @faizansaiyed123, @jpdefo, @Jxxunnn, @mikamikasuki, @philipatkinson, @rubas, and @Shubham-Padkonde. Thank you for your contributions!
205249

250+
- **feat(bun): Add incoming request options and request sessions to `bunServerIntegration`**
251+
252+
`bunServerIntegration` now accepts the same options as `denoServeIntegration`: `ignoreRequestBody`, `ignoreIncomingRequests`, `ignoreStaticAssets`, `spans`, `onSpanCreated`, `onSpanEnd`, `sessions` and `sessionFlushingDelayMS`. The callbacks receive the web `Request`.
253+
254+
`Bun.serve` now records a request session for each incoming request. Sessions are sent only when a `release` is set. To turn them off, set `bunServerIntegration({ sessions: false })`.
255+
256+
`ignoreStaticAssets` defaults to `true`, so `Bun.serve` no longer creates spans for `GET` requests to common static assets such as `favicon.ico`, `robots.txt` or `*.js` files. To keep these spans, set `bunServerIntegration({ ignoreStaticAssets: false })`. `Bun.serve` spans also follow the client's tracing configuration by default, so the integration does not start spans when tracing is disabled. Errors thrown for `OPTIONS` and `HEAD` requests are now captured.
257+
258+
- **feat(node): Add `onSpanEnd` to `httpIntegration`**
259+
260+
`httpIntegration` and `httpServerSpansIntegration` now accept `onSpanEnd`, a hook that runs when the response for an incoming request finishes, before its span ends. Use it to change the span based on the response. Deno and Bun already have this option.
261+
262+
- **feat(bun): Inject debug IDs and upload source maps in `sentryBunPlugin` ([#25670](https://github.com/getsentry/sentry-javascript/pull/25670))**
263+
264+
`sentryBunPlugin` from `@sentry/bun/plugin` now accepts the same options as `sentryEsbuildPlugin` (`org`, `project`, `authToken`, `release`, `sourcemaps`, ...). When `Bun.build` writes source maps to `outdir`, the plugin injects the debug ID that Bun writes into each bundle, injects the release, and uploads the source maps at the end of the build. You no longer need to run `sentry sourcemap inject` and `sentry sourcemap upload` after the build.
265+
266+
Like the other bundler plugins, `sentryBunPlugin` now sends build telemetry and injects the release it detects (for example, from git). To turn off telemetry, set `telemetry: false`.
267+
206268
## 11.8.0
207269

208270
### Important Changes
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import * as Sentry from '@sentry/browser';
2+
import { feedbackIntegration } from '@sentry/browser';
3+
4+
Sentry.init({
5+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
6+
integrations: [feedbackIntegration({ colorScheme: 'light' })],
7+
});
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { expect } from '@playwright/test';
2+
import { sentryTest } from '../../../utils/fixtures';
3+
import { shouldSkipFeedbackTest } from '../../../utils/helpers';
4+
5+
type CaptureWindow = Window & { framesWithoutFormAtCapture?: number };
6+
7+
// Whether the capture still shows the form depends on how busy the machine is, so this counts the frames the page
8+
// drew with the form hidden by the time the capture is requested instead.
9+
sentryTest(
10+
'draws two frames without the feedback form before it asks for the screen capture',
11+
async ({ getLocalTestUrl, page, browserName }) => {
12+
sentryTest.skip(shouldSkipFeedbackTest());
13+
sentryTest.skip(browserName !== 'chromium', 'The canvas screen-capture fixture requires Chromium.');
14+
15+
await page.addInitScript(() => {
16+
// The fixture runs over HTTP, but screenshot capture is stubbed below.
17+
Object.defineProperty(window, 'isSecureContext', { value: true });
18+
19+
let framesWithoutForm = 0;
20+
const countFrame = (): void => {
21+
const form = document
22+
.getElementById('sentry-feedback')
23+
?.shadowRoot?.querySelector('dialog.dialog')?.parentElement;
24+
if (form?.style.display === 'none') {
25+
framesWithoutForm += 1;
26+
}
27+
requestAnimationFrame(countFrame);
28+
};
29+
requestAnimationFrame(countFrame);
30+
31+
Object.defineProperty(navigator, 'mediaDevices', {
32+
value: {
33+
getDisplayMedia: async () => {
34+
(window as CaptureWindow).framesWithoutFormAtCapture = framesWithoutForm;
35+
const canvas = document.createElement('canvas');
36+
canvas.width = 1600;
37+
canvas.height = 1000;
38+
const ctx = canvas.getContext('2d')!;
39+
ctx.fillStyle = 'white';
40+
ctx.fillRect(0, 0, canvas.width, canvas.height);
41+
return canvas.captureStream();
42+
},
43+
},
44+
configurable: true,
45+
});
46+
});
47+
48+
await page.goto(await getLocalTestUrl({ testDir: __dirname, handleLazyLoadedFeedback: true }));
49+
await page.getByRole('button', { name: 'Report a Bug', exact: true }).click();
50+
await page.getByRole('button', { name: 'Add a screenshot', exact: true }).click();
51+
await expect(page.locator('#foreground')).toBeVisible();
52+
53+
const framesWithoutForm = await page.evaluate(() => (window as CaptureWindow).framesWithoutFormAtCapture);
54+
expect(framesWithoutForm).toBeGreaterThanOrEqual(2);
55+
},
56+
);

‎dev-packages/browser-integration-tests/suites/tracing/metrics/web-vitals-cls/test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ sentryTest('captures CLS as a streamed span with source attributes', async ({ ge
4343
const pageloadSpan = await pageloadSpanPromise;
4444

4545
expect(clsSpan.attributes[SENTRY_OP]).toEqual({ type: 'string', value: 'ui.webvital.cls' });
46-
expect(clsSpan.attributes[SENTRY_ORIGIN]).toEqual({ type: 'string', value: 'auto.http.browser.cls' });
46+
expect(clsSpan.attributes[SENTRY_ORIGIN]).toEqual({ type: 'string', value: 'auto.ui.browser.cls' });
4747
expect(clsSpan.attributes[SENTRY_EXCLUSIVE_TIME]).toEqual({ type: 'integer', value: 0 });
4848
expect(clsSpan.attributes[USER_AGENT_ORIGINAL]?.value).toEqual(expect.stringContaining('Chrome'));
4949

‎dev-packages/browser-integration-tests/suites/tracing/metrics/web-vitals-inp-late/test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ sentryTest(
101101
status: 'ok',
102102
attributes: {
103103
[SENTRY_IS_LOCALHOST]: { value: false, type: 'boolean' },
104-
[SENTRY_ORIGIN]: { value: 'auto.http.browser.inp', type: 'string' },
104+
[SENTRY_ORIGIN]: { value: 'auto.ui.browser.inp', type: 'string' },
105105
[SENTRY_OP]: { value: UI_INTERACTION_CLICK, type: 'string' },
106106
[UI_COMPONENT_NAME]: { value: 'NormalButton', type: 'string' },
107107
[BROWSER_WEB_VITAL_INP_TARGET]: { value: 'body > NormalButton', type: 'string' },

‎dev-packages/browser-integration-tests/suites/tracing/metrics/web-vitals-inp-navigate/test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ sentryTest(
101101
status: 'ok',
102102
attributes: {
103103
[SENTRY_IS_LOCALHOST]: { value: false, type: 'boolean' },
104-
[SENTRY_ORIGIN]: { value: 'auto.http.browser.inp', type: 'string' },
104+
[SENTRY_ORIGIN]: { value: 'auto.ui.browser.inp', type: 'string' },
105105
[SENTRY_OP]: { value: UI_INTERACTION_CLICK, type: 'string' },
106106
[UI_COMPONENT_NAME]: { value: 'NavigationLink', type: 'string' },
107107
[BROWSER_WEB_VITAL_INP_TARGET]: { value: 'body > nav#navigation > NavigationLink', type: 'string' },
@@ -192,7 +192,7 @@ sentryTest(
192192
status: 'ok',
193193
attributes: {
194194
[SENTRY_IS_LOCALHOST]: { value: false, type: 'boolean' },
195-
[SENTRY_ORIGIN]: { value: 'auto.http.browser.inp', type: 'string' },
195+
[SENTRY_ORIGIN]: { value: 'auto.ui.browser.inp', type: 'string' },
196196
[SENTRY_OP]: { value: UI_INTERACTION_CLICK, type: 'string' },
197197
[BROWSER_WEB_VITAL_INP_TARGET]: { value: 'body > nav#navigation > NavigationLink', type: 'string' },
198198
[SENTRY_EXCLUSIVE_TIME]: { value: inpValue, type: expect.stringMatching(/^(integer)|(double)$/) },

0 commit comments

Comments
 (0)