Skip to content

Commit b5b0027

Browse files
committed
Merge branch 'develop' into timfish/feat/new-anr
2 parents 455d77a + 4e7c7ef commit b5b0027

File tree

127 files changed

+1729
-592
lines changed

Some content is hidden

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

127 files changed

+1729
-592
lines changed

.github/actions/install-playwright/action.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ runs:
3434
working-directory: ${{ inputs.cwd }}
3535

3636
- name: Install Playwright system dependencies only (cached)
37-
run: npx playwright install-deps ${{ inputs.browsers || 'chromium webkit firefox' }}
37+
env:
38+
PLAYWRIGHT_BROWSERS: ${{ inputs.browsers || 'chromium webkit firefox' }}
39+
run: npx playwright install-deps "$PLAYWRIGHT_BROWSERS"
3840
if: steps.playwright-cache.outputs.cache-hit == 'true'
3941
shell: bash
4042
working-directory: ${{ inputs.cwd }}

.size-limit.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ module.exports = [
120120
import: createImport('init', 'ErrorBoundary', 'reactRouterV6BrowserTracingIntegration'),
121121
ignore: ['react/jsx-runtime'],
122122
gzip: true,
123-
limit: '40.5 KB',
123+
limit: '41 KB',
124124
},
125125
// Vue SDK (ESM)
126126
{
@@ -215,7 +215,7 @@ module.exports = [
215215
import: createImport('init'),
216216
ignore: ['$app/stores'],
217217
gzip: true,
218-
limit: '39 KB',
218+
limit: '40 KB',
219219
},
220220
// Node SDK (ESM)
221221
{

CHANGELOG.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,47 @@
44

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

7+
## 9.29.0
8+
9+
### Important Changes
10+
11+
- **feat(browser): Update `web-vitals` to 5.0.2 ([#16492](https://github.com/getsentry/sentry-javascript/pull/16492))**
12+
13+
This release upgrades the `web-vitals` library to version 5.0.2. This upgrade could slightly change the collected web vital values and potentially also influence alerts and performance scores in the Sentry UI.
14+
15+
### Other Changes
16+
17+
- feat(deps): Bump @sentry/rollup-plugin from 3.4.0 to 3.5.0 ([#16524](https://github.com/getsentry/sentry-javascript/pull/16524))
18+
- feat(ember): Stop warning for `onError` usage ([#16547](https://github.com/getsentry/sentry-javascript/pull/16547))
19+
- feat(node): Allow to force activate `vercelAiIntegration` ([#16551](https://github.com/getsentry/sentry-javascript/pull/16551))
20+
- feat(node): Introduce `ignoreLayersType` option to koa integration ([#16553](https://github.com/getsentry/sentry-javascript/pull/16553))
21+
- fix(browser): Ensure `suppressTracing` does not leak when async ([#16545](https://github.com/getsentry/sentry-javascript/pull/16545))
22+
- fix(vue): Ensure root component render span always ends ([#16488](https://github.com/getsentry/sentry-javascript/pull/16488))
23+
24+
## 9.28.1
25+
26+
- feat(deps): Bump @sentry/cli from 2.45.0 to 2.46.0 ([#16516](https://github.com/getsentry/sentry-javascript/pull/16516))
27+
- fix(nextjs): Avoid tracing calls to symbolication server on dev ([#16533](https://github.com/getsentry/sentry-javascript/pull/16533))
28+
- fix(sveltekit): Add import attribute for node exports ([#16528](https://github.com/getsentry/sentry-javascript/pull/16528))
29+
30+
Work in this release was contributed by @eltigerchino. Thank you for your contribution!
31+
32+
## 9.28.0
33+
34+
### Important Changes
35+
36+
- **feat(nestjs): Stop creating spans for `TracingInterceptor` ([#16501](https://github.com/getsentry/sentry-javascript/pull/16501))**
37+
38+
With this change we stop creating spans for `TracingInterceptor` as this interceptor only serves as an internal helper and adds noise for the user.
39+
40+
- **feat(node): Update vercel ai spans as per new conventions ([#16497](https://github.com/getsentry/sentry-javascript/pull/16497))**
41+
42+
This feature ships updates to the span names and ops to better match OpenTelemetry. This should make them more easily accessible to the new agents module view we are building.
43+
44+
### Other Changes
45+
46+
- fix(sveltekit): Export `vercelAIIntegration` from `@sentry/node` ([#16496](https://github.com/getsentry/sentry-javascript/pull/16496))
47+
748
Work in this release was contributed by @agrattan0820. Thank you for your contribution!
849

950
## 9.27.0

dev-packages/browser-integration-tests/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@sentry-internal/browser-integration-tests",
3-
"version": "9.27.0",
3+
"version": "9.29.0",
44
"main": "index.js",
55
"license": "MIT",
66
"engines": {
@@ -42,7 +42,7 @@
4242
"@babel/preset-typescript": "^7.16.7",
4343
"@playwright/test": "~1.50.0",
4444
"@sentry-internal/rrweb": "2.34.0",
45-
"@sentry/browser": "9.27.0",
45+
"@sentry/browser": "9.29.0",
4646
"@supabase/supabase-js": "2.49.3",
4747
"axios": "1.8.2",
4848
"babel-loader": "^8.2.2",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
// Create measures BEFORE SDK initializes
4+
5+
// Create a measure with detail
6+
const measure = performance.measure('restricted-test-measure', {
7+
start: performance.now(),
8+
end: performance.now() + 1,
9+
detail: { test: 'initial-value' },
10+
});
11+
12+
// Simulate Firefox's permission denial by overriding the detail getter
13+
// This mimics the actual Firefox behavior where accessing detail throws
14+
Object.defineProperty(measure, 'detail', {
15+
get() {
16+
throw new DOMException('Permission denied to access object', 'SecurityError');
17+
},
18+
configurable: false,
19+
enumerable: true,
20+
});
21+
22+
window.Sentry = Sentry;
23+
24+
Sentry.init({
25+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
26+
integrations: [
27+
Sentry.browserTracingIntegration({
28+
idleTimeout: 9000,
29+
}),
30+
],
31+
tracesSampleRate: 1,
32+
});
33+
34+
// Also create a normal measure to ensure SDK still works
35+
performance.measure('normal-measure', {
36+
start: performance.now(),
37+
end: performance.now() + 50,
38+
detail: 'this-should-work',
39+
});
40+
41+
// Create a measure with complex detail object
42+
performance.measure('complex-detail-measure', {
43+
start: performance.now(),
44+
end: performance.now() + 25,
45+
detail: {
46+
nested: {
47+
array: [1, 2, 3],
48+
object: {
49+
key: 'value',
50+
},
51+
},
52+
metadata: {
53+
type: 'test',
54+
version: '1.0',
55+
tags: ['complex', 'nested', 'object'],
56+
},
57+
},
58+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event } from '@sentry/core';
3+
import { sentryTest } from '../../../../utils/fixtures';
4+
import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers';
5+
6+
// This is a regression test for https://github.com/getsentry/sentry-javascript/issues/16347
7+
8+
sentryTest(
9+
'should handle permission denial gracefully and still create measure spans',
10+
async ({ getLocalTestUrl, page, browserName }) => {
11+
// Skip test on webkit because we can't validate the detail in the browser
12+
if (shouldSkipTracingTest() || browserName === 'webkit') {
13+
sentryTest.skip();
14+
}
15+
16+
const url = await getLocalTestUrl({ testDir: __dirname });
17+
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
18+
19+
// Find all measure spans
20+
const measureSpans = eventData.spans?.filter(({ op }) => op === 'measure');
21+
expect(measureSpans?.length).toBe(3); // All three measures should create spans
22+
23+
// Test 1: Verify the restricted-test-measure span exists but has no detail
24+
const restrictedMeasure = measureSpans?.find(span => span.description === 'restricted-test-measure');
25+
expect(restrictedMeasure).toBeDefined();
26+
expect(restrictedMeasure?.data).toMatchObject({
27+
'sentry.op': 'measure',
28+
'sentry.origin': 'auto.resource.browser.metrics',
29+
});
30+
31+
// Verify no detail attributes were added due to the permission error
32+
const restrictedDataKeys = Object.keys(restrictedMeasure?.data || {});
33+
const restrictedDetailKeys = restrictedDataKeys.filter(key => key.includes('detail'));
34+
expect(restrictedDetailKeys).toHaveLength(0);
35+
36+
// Test 2: Verify the normal measure still captures detail correctly
37+
const normalMeasure = measureSpans?.find(span => span.description === 'normal-measure');
38+
expect(normalMeasure).toBeDefined();
39+
expect(normalMeasure?.data).toMatchObject({
40+
'sentry.browser.measure.detail': 'this-should-work',
41+
'sentry.op': 'measure',
42+
'sentry.origin': 'auto.resource.browser.metrics',
43+
});
44+
45+
// Test 3: Verify the complex detail object is captured correctly
46+
const complexMeasure = measureSpans?.find(span => span.description === 'complex-detail-measure');
47+
expect(complexMeasure).toBeDefined();
48+
expect(complexMeasure?.data).toMatchObject({
49+
'sentry.op': 'measure',
50+
'sentry.origin': 'auto.resource.browser.metrics',
51+
// The entire nested object is stringified as a single value
52+
'sentry.browser.measure.detail.nested': JSON.stringify({
53+
array: [1, 2, 3],
54+
object: {
55+
key: 'value',
56+
},
57+
}),
58+
'sentry.browser.measure.detail.metadata': JSON.stringify({
59+
type: 'test',
60+
version: '1.0',
61+
tags: ['complex', 'nested', 'object'],
62+
}),
63+
});
64+
},
65+
);

dev-packages/browser-integration-tests/suites/tracing/metrics/pageload-measure-spans/init.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ performance.measure('Next.js-before-hydration', {
1010
window.Sentry = Sentry;
1111

1212
Sentry.init({
13-
debug: true,
1413
dsn: 'https://public@dsn.ingest.sentry.io/1337',
1514
integrations: [
1615
Sentry.browserTracingIntegration({

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { sentryTest } from '../../../../utils/fixtures';
44
import {
55
getFirstSentryEnvelopeRequest,
66
getMultipleSentryEnvelopeRequests,
7+
hidePage,
78
properFullEnvelopeRequestParser,
89
shouldSkipTracingTest,
910
} from '../../../../utils/helpers';
@@ -33,9 +34,7 @@ sentryTest('should capture an INP click event span after pageload', async ({ bro
3334
await page.waitForTimeout(500);
3435

3536
// Page hide to trigger INP
36-
await page.evaluate(() => {
37-
window.dispatchEvent(new Event('pagehide'));
38-
});
37+
await hidePage(page);
3938

4039
// Get the INP span envelope
4140
const spanEnvelope = (await spanEnvelopePromise)[0];

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { sentryTest } from '../../../../utils/fixtures';
44
import {
55
getFirstSentryEnvelopeRequest,
66
getMultipleSentryEnvelopeRequests,
7+
hidePage,
78
properFullEnvelopeRequestParser,
89
shouldSkipTracingTest,
910
} from '../../../../utils/helpers';
@@ -35,9 +36,7 @@ sentryTest(
3536
await page.waitForTimeout(500);
3637

3738
// Page hide to trigger INP
38-
await page.evaluate(() => {
39-
window.dispatchEvent(new Event('pagehide'));
40-
});
39+
await hidePage(page);
4140

4241
// Get the INP span envelope
4342
const spanEnvelope = (await spanEnvelopePromise)[0];

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { SpanEnvelope } from '@sentry/core';
33
import { sentryTest } from '../../../../utils/fixtures';
44
import {
55
getMultipleSentryEnvelopeRequests,
6+
hidePage,
67
properFullEnvelopeRequestParser,
78
shouldSkipTracingTest,
89
} from '../../../../utils/helpers';
@@ -33,9 +34,7 @@ sentryTest(
3334
await page.waitForTimeout(500);
3435

3536
// Page hide to trigger INP
36-
await page.evaluate(() => {
37-
window.dispatchEvent(new Event('pagehide'));
38-
});
37+
await hidePage(page);
3938

4039
// Get the INP span envelope
4140
const spanEnvelope = (await spanEnvelopePromise)[0];

0 commit comments

Comments
 (0)