Skip to content

Commit 9a25dad

Browse files
authored
Merge pull request #12932 from getsentry/prepare-release/8.18.0
meta: Update CHANGELOG for 8.18.0
2 parents af760a7 + c57e363 commit 9a25dad

File tree

193 files changed

+3000
-492
lines changed

Some content is hidden

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

193 files changed

+3000
-492
lines changed

.github/workflows/canary.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ env:
1818
${{ github.workspace }}/node_modules
1919
${{ github.workspace }}/packages/*/node_modules
2020
${{ github.workspace }}/dev-packages/*/node_modules
21+
${{ github.workspace }}/packages/utils/build
2122
2223
permissions:
2324
contents: read

.github/workflows/external-contributors.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: "CI: Mention external contributors"
22
on:
3-
pull_request:
3+
pull_request_target:
44
types:
55
- closed
66
branches:
@@ -18,7 +18,7 @@ jobs:
1818
&& github.event.pull_request.author_association != 'COLLABORATOR'
1919
&& github.event.pull_request.author_association != 'MEMBER'
2020
&& github.event.pull_request.author_association != 'OWNER'
21-
&& github.actor != 'dependabot[bot]'
21+
&& endsWith(github.actor, '[bot]') == false
2222
steps:
2323
- uses: actions/checkout@v4
2424
- name: Set up Node

.size-limit.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ module.exports = [
177177
path: createCDNPath('bundle.tracing.replay.min.js'),
178178
gzip: false,
179179
brotli: false,
180-
limit: '220 KB',
180+
limit: '230 KB',
181181
},
182182
{
183183
name: 'CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed',

CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,38 @@
88

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

11+
## 8.18.0
12+
13+
### Important Changes
14+
15+
- **ref: Deprecate `enableTracing` (12897)**
16+
17+
The `enableTracing` option has been deprecated and will be removed in the next major version. We recommend removing it
18+
in favor of the `tracesSampleRate` and `tracesSampler` options. If you want to enable performance monitoring, please set
19+
the `tracesSampleRate` to a sample rate of your choice, or provide a sampling function as `tracesSampler` option
20+
instead. If you want to disable performance monitoring, remove the `tracesSampler` and `tracesSampleRate` options.
21+
22+
### Other Changes
23+
24+
- feat(node): Expose `exclude` and `include` options for ESM loader (#12910)
25+
- feat(browser): Add user agent to INP standalone span attributes (#12896)
26+
- feat(nextjs): Add `experimental_captureRequestError` for `onRequestError` hook (#12885)
27+
- feat(replay): Bump `rrweb` to 2.25.0 (#12478)
28+
- feat(tracing): Add long animation frame tracing (#12646)
29+
- fix: Cleanup hooks when they are not used anymore (#12852)
30+
- fix(angular): Guard `ErrorEvent` check in ErrorHandler to avoid throwing in Node environments (#12892)
31+
- fix(inp): Ensure INP spans have correct transaction (#12871)
32+
- fix(nestjs): Do not make SentryTraced() decorated functions async (#12879)
33+
- fix(nextjs): Support automatic instrumentation for app directory with custom page extensions (#12858)
34+
- fix(node): Ensure correct URL is passed to `ignoreIncomingRequests` callback (#12929)
35+
- fix(otel): Do not add `otel.kind: INTERNAL` attribute (#12841)
36+
- fix(solidstart): Set proper sentry origin for solid router integration when used in solidstart sdk (#12919)
37+
- fix(sveltekit): Add Vite peer dep for proper type resolution (#12926)
38+
- fix(tracing): Ensure you can pass `null` as `parentSpan` in `startSpan*` (#12928)
39+
- ref(core): Small bundle size improvement (#12830)
40+
41+
Work in this release was contributed by @GitSquared and @mcous. Thank you for your contributions!
42+
1143
## 8.17.0
1244

1345
- feat: Upgrade OTEL deps (#12809)

CONTRIBUTING.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ able to use it. From the top level of the repo, there are three commands availab
4040
dependencies (`utils`, `core`, `browser`, etc), and all packages which depend on it (currently `gatsby` and `nextjs`))
4141
- `yarn build:dev:watch`, which runs `yarn build:dev` in watch mode (recommended)
4242

43+
Note: Due to package incompatibilities between Python versions, building native binaries currently requires a Python
44+
version <3.12.
45+
4346
You can also run a production build via `yarn build`, which will build everything except for the tarballs for publishing
4447
to NPM. You can use this if you want to bundle Sentry yourself. The build output can be found in the packages `build/`
4548
folder, e.g. `packages/browser/build`. Bundled files can be found in `packages/browser/build/bundles`. Note that there

MIGRATION.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,7 @@ Removed top-level exports: `enableAnrDetection`, `Anr`, `deepReadDirSync`, `runW
711711
- [Removal of `enableAnrDetection` and `Anr` class](./MIGRATION.md#removal-of-enableanrdetection-and-anr-class)
712712
- [Removal of `deepReadDirSync` method](./MIGRATION.md#removal-of-deepreaddirsync-method)
713713
- [Removal of `runWithAsyncContext` method](./MIGRATION.md#removal-of-runwithasynccontext-method)
714+
- [Removal of `Apollo` integration](./MIGRATION.md#removal-of-apollo-integration)
714715
715716
#### Removal of `enableAnrDetection` and `Anr` class
716717
@@ -737,6 +738,21 @@ Sentry.withIsolationScope(() => {
737738
});
738739
```
739740
741+
#### Removal of Apollo integration
742+
743+
The Apollo integration has been removed in `8.x` as `8.x` automatically adds GraphQL support via `graphqlIntegration`
744+
which is automatically enabled.
745+
746+
```js
747+
// before (v7)
748+
Sentry.init({
749+
integrations: [Sentry.integrations.Apollo()],
750+
});
751+
752+
// after (v8)
753+
Sentry.init({});
754+
```
755+
740756
### Next.js SDK
741757
742758
Removed top-level exports: `withSentryApi`, `withSentryAPI`, `withSentryGetServerSideProps`, `withSentryGetStaticProps`,

biome.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@
4343
".angular/**",
4444
"angular.json",
4545
"ember/instance-initializers/**",
46-
"ember/types.d.ts"
46+
"ember/types.d.ts",
47+
".output",
48+
".vinxi"
4749
]
4850
},
4951
"files": {

dev-packages/browser-integration-tests/suites/replay/canvas/manualSnapshot/template.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
function draw() {
1414
const canvas = document.getElementById("canvas");
1515
if (canvas.getContext) {
16-
console.log('has canvas')
1716
const ctx = canvas.getContext("2d");
1817

1918
ctx.fillRect(25, 25, 100, 100);

dev-packages/browser-integration-tests/suites/replay/canvas/records/template.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
function draw() {
1414
const canvas = document.getElementById("canvas");
1515
if (canvas.getContext) {
16-
console.log('has canvas')
1716
const ctx = canvas.getContext("2d");
1817

1918
ctx.fillRect(25, 25, 100, 100);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(() => {
2+
const startTime = Date.now();
3+
4+
function getElasped() {
5+
const time = Date.now();
6+
return time - startTime;
7+
}
8+
9+
while (getElasped() < 101) {
10+
//
11+
}
12+
})();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
5+
Sentry.init({
6+
dsn: 'https://[email protected]/1337',
7+
integrations: [
8+
Sentry.browserTracingIntegration({ enableLongTask: false, enableLongAnimationFrame: false, idleTimeout: 9000 }),
9+
],
10+
tracesSampleRate: 1,
11+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
</head>
6+
<body>
7+
<div>Rendered Before Long Animation Frame</div>
8+
<script src="https://example.com/path/to/script.js"></script>
9+
</body>
10+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import type { Route } from '@playwright/test';
2+
import { expect } from '@playwright/test';
3+
import type { Event } from '@sentry/types';
4+
5+
import { sentryTest } from '../../../../utils/fixtures';
6+
import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers';
7+
8+
sentryTest(
9+
'should not capture long animation frame when flag is disabled.',
10+
async ({ browserName, getLocalTestPath, page }) => {
11+
// Long animation frames only work on chrome
12+
if (shouldSkipTracingTest() || browserName !== 'chromium') {
13+
sentryTest.skip();
14+
}
15+
16+
await page.route('**/path/to/script.js', (route: Route) =>
17+
route.fulfill({ path: `${__dirname}/assets/script.js` }),
18+
);
19+
20+
const url = await getLocalTestPath({ testDir: __dirname });
21+
22+
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
23+
const uiSpans = eventData.spans?.filter(({ op }) => op?.startsWith('ui'));
24+
25+
expect(uiSpans?.length).toBe(0);
26+
},
27+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
function getElapsed(startTime) {
2+
const time = Date.now();
3+
return time - startTime;
4+
}
5+
6+
function handleClick() {
7+
const startTime = Date.now();
8+
while (getElapsed(startTime) < 105) {
9+
//
10+
}
11+
}
12+
13+
function start() {
14+
const startTime = Date.now();
15+
while (getElapsed(startTime) < 105) {
16+
//
17+
}
18+
}
19+
20+
// trigger 2 long-animation-frame events
21+
// one from the top-level and the other from an event-listener
22+
start();
23+
24+
const button = document.getElementById('clickme');
25+
button.addEventListener('click', handleClick);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
5+
Sentry.init({
6+
dsn: 'https://[email protected]/1337',
7+
integrations: [
8+
Sentry.browserTracingIntegration({
9+
idleTimeout: 9000,
10+
enableLongTask: false,
11+
enableLongAnimationFrame: true,
12+
}),
13+
],
14+
tracesSampleRate: 1,
15+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
</head>
6+
<body>
7+
<div>Rendered Before Long Animation Frame</div>
8+
<button id="clickme">
9+
click me to start the long animation!
10+
</button>
11+
<script src="https://example.com/path/to/script.js"></script>
12+
</body>
13+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import type { Route } from '@playwright/test';
2+
import { expect } from '@playwright/test';
3+
import type { Event } from '@sentry/types';
4+
5+
import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/browser';
6+
import { sentryTest } from '../../../../utils/fixtures';
7+
import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers';
8+
9+
sentryTest(
10+
'should capture long animation frame for top-level script.',
11+
async ({ browserName, getLocalTestPath, page }) => {
12+
// Long animation frames only work on chrome
13+
if (shouldSkipTracingTest() || browserName !== 'chromium') {
14+
sentryTest.skip();
15+
}
16+
17+
await page.route('**/path/to/script.js', (route: Route) =>
18+
route.fulfill({ path: `${__dirname}/assets/script.js` }),
19+
);
20+
21+
const url = await getLocalTestPath({ testDir: __dirname });
22+
23+
const promise = getFirstSentryEnvelopeRequest<Event>(page);
24+
25+
await page.goto(url);
26+
27+
await new Promise(resolve => setTimeout(resolve, 1000));
28+
29+
const eventData = await promise;
30+
31+
const uiSpans = eventData.spans?.filter(({ op }) => op?.startsWith('ui.long-animation-frame'));
32+
33+
expect(uiSpans?.length).toEqual(1);
34+
35+
const [topLevelUISpan] = uiSpans || [];
36+
expect(topLevelUISpan).toEqual(
37+
expect.objectContaining({
38+
op: 'ui.long-animation-frame',
39+
description: 'Main UI thread blocked',
40+
parent_span_id: eventData.contexts?.trace?.span_id,
41+
data: {
42+
'code.filepath': 'https://example.com/path/to/script.js',
43+
'browser.script.source_char_position': 0,
44+
'browser.script.invoker': 'https://example.com/path/to/script.js',
45+
'browser.script.invoker_type': 'classic-script',
46+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'ui.long-animation-frame',
47+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',
48+
},
49+
}),
50+
);
51+
const start = topLevelUISpan.start_timestamp ?? 0;
52+
const end = topLevelUISpan.timestamp ?? 0;
53+
const duration = end - start;
54+
55+
expect(duration).toBeGreaterThanOrEqual(0.1);
56+
expect(duration).toBeLessThanOrEqual(0.15);
57+
},
58+
);
59+
60+
sentryTest(
61+
'should capture long animation frame for event listener.',
62+
async ({ browserName, getLocalTestPath, page }) => {
63+
// Long animation frames only work on chrome
64+
if (shouldSkipTracingTest() || browserName !== 'chromium') {
65+
sentryTest.skip();
66+
}
67+
68+
await page.route('**/path/to/script.js', (route: Route) =>
69+
route.fulfill({ path: `${__dirname}/assets/script.js` }),
70+
);
71+
72+
const url = await getLocalTestPath({ testDir: __dirname });
73+
74+
const promise = getFirstSentryEnvelopeRequest<Event>(page);
75+
76+
await page.goto(url);
77+
78+
// trigger long animation frame function
79+
await page.getByRole('button').click();
80+
81+
await new Promise(resolve => setTimeout(resolve, 1000));
82+
83+
const eventData = await promise;
84+
85+
const uiSpans = eventData.spans?.filter(({ op }) => op?.startsWith('ui.long-animation-frame'));
86+
87+
expect(uiSpans?.length).toEqual(2);
88+
89+
// ignore the first ui span (top-level long animation frame)
90+
const [, eventListenerUISpan] = uiSpans || [];
91+
92+
expect(eventListenerUISpan).toEqual(
93+
expect.objectContaining({
94+
op: 'ui.long-animation-frame',
95+
description: 'Main UI thread blocked',
96+
parent_span_id: eventData.contexts?.trace?.span_id,
97+
data: {
98+
'browser.script.invoker': 'BUTTON#clickme.onclick',
99+
'browser.script.invoker_type': 'event-listener',
100+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'ui.long-animation-frame',
101+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',
102+
},
103+
}),
104+
);
105+
const start = eventListenerUISpan.start_timestamp ?? 0;
106+
const end = eventListenerUISpan.timestamp ?? 0;
107+
const duration = end - start;
108+
109+
expect(duration).toBeGreaterThanOrEqual(0.1);
110+
expect(duration).toBeLessThanOrEqual(0.15);
111+
},
112+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(() => {
2+
const startTime = Date.now();
3+
4+
function getElasped() {
5+
const time = Date.now();
6+
return time - startTime;
7+
}
8+
9+
while (getElasped() < 101) {
10+
//
11+
}
12+
})();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
5+
Sentry.init({
6+
dsn: 'https://[email protected]/1337',
7+
integrations: [
8+
Sentry.browserTracingIntegration({ enableLongTask: true, enableLongAnimationFrame: true, idleTimeout: 9000 }),
9+
],
10+
tracesSampleRate: 1,
11+
});

0 commit comments

Comments
 (0)