Skip to content

Commit 9a98d98

Browse files
authored
Merge pull request #14244 from getsentry/prepare-release/8.38.0
meta(changelog): Update changelog for 8.38.0
2 parents d7ed9d3 + ad1f938 commit 9a98d98

File tree

90 files changed

+2001
-372
lines changed

Some content is hidden

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

90 files changed

+2001
-372
lines changed

.github/workflows/external-contributors.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ jobs:
4141
# This token is scoped to Daniel Griesser
4242
# If we used the default GITHUB_TOKEN, the resulting PR would not trigger CI :(
4343
token: ${{ secrets.REPO_SCOPED_TOKEN }}
44-
commit-message: "ref: Add external contributor to CHANGELOG.md"
45-
title: "ref: Add external contributor to CHANGELOG.md"
44+
commit-message: "chore: Add external contributor to CHANGELOG.md"
45+
title: "chore: Add external contributor to CHANGELOG.md"
4646
branch: 'external-contributor/patch-${{ github.event.pull_request.user.login }}'
4747
base: 'develop'
4848
delete-branch: true

.size-limit.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ module.exports = [
7979
path: 'packages/browser/build/npm/esm/index.js',
8080
import: createImport('init', 'browserTracingIntegration', 'replayIntegration', 'replayCanvasIntegration'),
8181
gzip: true,
82-
limit: '78.1 KB',
82+
limit: '78.2 KB',
8383
},
8484
{
8585
name: '@sentry/browser (incl. Tracing, Replay, Feedback)',

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,26 @@
1010

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

13+
## 8.38.0
14+
15+
- docs: Improve docstrings for node otel integrations ([#14217](https://github.com/getsentry/sentry-javascript/pull/14217))
16+
- feat(browser): Add moduleMetadataIntegration lazy loading support ([#13817](https://github.com/getsentry/sentry-javascript/pull/13817))
17+
- feat(core): Add trpc path to context in trpcMiddleware ([#14218](https://github.com/getsentry/sentry-javascript/pull/14218))
18+
- feat(deps): Bump @opentelemetry/instrumentation-amqplib from 0.42.0 to 0.43.0 ([#14230](https://github.com/getsentry/sentry-javascript/pull/14230))
19+
- feat(deps): Bump @sentry/cli from 2.37.0 to 2.38.2 ([#14232](https://github.com/getsentry/sentry-javascript/pull/14232))
20+
- feat(node): Add `knex` integration ([#13526](https://github.com/getsentry/sentry-javascript/pull/13526))
21+
- feat(node): Add `tedious` integration ([#13486](https://github.com/getsentry/sentry-javascript/pull/13486))
22+
- feat(utils): Single implementation to fetch debug ids ([#14199](https://github.com/getsentry/sentry-javascript/pull/14199))
23+
- fix(browser): Avoid recording long animation frame spans starting before their parent span ([#14186](https://github.com/getsentry/sentry-javascript/pull/14186))
24+
- fix(node): Include `debug_meta` with ANR events ([#14203](https://github.com/getsentry/sentry-javascript/pull/14203))
25+
- fix(nuxt): Fix dynamic import rollup plugin to work with latest nitro ([#14243](https://github.com/getsentry/sentry-javascript/pull/14243))
26+
- fix(react): Support wildcard routes on React Router 6 ([#14205](https://github.com/getsentry/sentry-javascript/pull/14205))
27+
- fix(spotlight): Export spotlightBrowserIntegration from the main browser package ([#14208](https://github.com/getsentry/sentry-javascript/pull/14208))
28+
- ref(browser): Ensure start time of interaction root and child span is aligned ([#14188](https://github.com/getsentry/sentry-javascript/pull/14188))
29+
- ref(nextjs): Make build-time value injection turbopack compatible ([#14081](https://github.com/getsentry/sentry-javascript/pull/14081))
30+
31+
Work in this release was contributed by @grahamhency, @Zen-cronic, @gilisho and @phuctm97. Thank you for your contributions!
32+
1333
## 8.37.1
1434

1535
- feat(deps): Bump @opentelemetry/instrumentation from 0.53.0 to 0.54.0 for @sentry/opentelemetry ([#14187](https://github.com/getsentry/sentry-javascript/pull/14187))
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
Sentry.init({
4+
dsn: 'https://[email protected]/1337',
5+
integrations: [],
6+
});
7+
8+
window.Sentry = {
9+
...Sentry,
10+
// Ensure this is _not_ set
11+
moduleMetadataIntegration: undefined,
12+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
window._testLazyLoadIntegration = async function run() {
2+
const integration = await window.Sentry.lazyLoadIntegration('moduleMetadataIntegration');
3+
4+
window.Sentry.getClient()?.addIntegration(integration());
5+
6+
window._integrationLoaded = true;
7+
};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { expect } from '@playwright/test';
2+
import { SDK_VERSION } from '@sentry/browser';
3+
4+
import { sentryTest } from '../../../../utils/fixtures';
5+
6+
sentryTest('it allows to lazy load the moduleMetadata integration', async ({ getLocalTestUrl, page }) => {
7+
const url = await getLocalTestUrl({ testDir: __dirname });
8+
9+
await page.route(`https://browser.sentry-cdn.com/${SDK_VERSION}/modulemetadata.min.js`, route => {
10+
return route.fulfill({
11+
status: 200,
12+
contentType: 'application/javascript;',
13+
body: "window.Sentry.moduleMetadataIntegration = () => ({ name: 'ModuleMetadata' })",
14+
});
15+
});
16+
17+
await page.goto(url);
18+
19+
const hasIntegration = await page.evaluate('!!window.Sentry.getClient()?.getIntegrationByName("ModuleMetadata")');
20+
expect(hasIntegration).toBe(false);
21+
22+
const scriptTagsBefore = await page.evaluate<number>('document.querySelectorAll("script").length');
23+
24+
await page.evaluate('window._testLazyLoadIntegration()');
25+
await page.waitForFunction('window._integrationLoaded');
26+
27+
const scriptTagsAfter = await page.evaluate<number>('document.querySelectorAll("script").length');
28+
29+
const hasIntegration2 = await page.evaluate('!!window.Sentry.getClient()?.getIntegrationByName("ModuleMetadata")');
30+
expect(hasIntegration2).toBe(true);
31+
32+
expect(scriptTagsAfter).toBe(scriptTagsBefore + 1);
33+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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+
instrumentPageLoad: false,
13+
enableInp: false,
14+
}),
15+
],
16+
tracesSampleRate: 1,
17+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
window.history.pushState({}, '', `#myHeading`);
12+
}
13+
14+
const button = document.getElementById('clickme');
15+
16+
console.log('button', button);
17+
18+
button.addEventListener('click', handleClick);
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+
<button id="clickme">
8+
click me to start the long animation!
9+
</button>
10+
11+
<h1 id="myHeading">My Heading</h1>
12+
</body>
13+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event } from '@sentry/types';
3+
4+
import { sentryTest } from '../../../../utils/fixtures';
5+
import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers';
6+
7+
sentryTest(
8+
"doesn't capture long animation frame that starts before a navigation.",
9+
async ({ browserName, getLocalTestPath, page }) => {
10+
// Long animation frames only work on chrome
11+
if (shouldSkipTracingTest() || browserName !== 'chromium') {
12+
sentryTest.skip();
13+
}
14+
15+
const url = await getLocalTestPath({ testDir: __dirname });
16+
17+
await page.goto(url);
18+
19+
const navigationTransactionEventPromise = getFirstSentryEnvelopeRequest<Event>(page);
20+
21+
await page.locator('#clickme').click();
22+
23+
const navigationTransactionEvent = await navigationTransactionEventPromise;
24+
25+
expect(navigationTransactionEvent.contexts?.trace?.op).toBe('navigation');
26+
27+
const loafSpans = navigationTransactionEvent.spans?.filter(s => s.op?.startsWith('ui.long-animation-frame'));
28+
29+
expect(loafSpans?.length).toEqual(0);
30+
},
31+
);

dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/long-tasks-before-navigation/init.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,4 @@ Sentry.init({
1515
}),
1616
],
1717
tracesSampleRate: 1,
18-
debug: true,
1918
});

dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/long-tasks-before-navigation/subject.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ longTaskButton?.addEventListener('click', () => {
1313
}
1414

1515
// trigger a navigation in the same event loop tick
16-
window.history.pushState({}, '', '/#myHeading');
16+
window.history.pushState({}, '', '#myHeading');
1717
});

dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/long-tasks-before-navigation/test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ sentryTest(
1515

1616
await page.goto(url);
1717

18+
const navigationTransactionEventPromise = getFirstSentryEnvelopeRequest<Event>(page);
19+
1820
await page.locator('#myButton').click();
1921

20-
const navigationTransactionEvent = await getFirstSentryEnvelopeRequest<Event>(page, url);
22+
const navigationTransactionEvent = await navigationTransactionEventPromise;
2123

2224
expect(navigationTransactionEvent.contexts?.trace?.op).toBe('navigation');
2325

dev-packages/browser-integration-tests/utils/generatePlugin.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const IMPORTED_INTEGRATION_CDN_BUNDLE_PATHS: Record<string, string> = {
3737
reportingObserverIntegration: 'reportingobserver',
3838
sessionTimingIntegration: 'sessiontiming',
3939
feedbackIntegration: 'feedback',
40+
moduleMetadataIntegration: 'modulemetadata',
4041
};
4142

4243
const BUNDLE_PATHS: Record<string, Record<string, string>> = {

dev-packages/e2e-tests/test-applications/nextjs-t3/tests/trpc-error.test.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ test('should capture error with trpc context', async ({ page }) => {
1212
const trpcError = await errorEventPromise;
1313

1414
expect(trpcError).toBeDefined();
15-
expect(trpcError.contexts.trpc).toBeDefined();
16-
expect(trpcError.contexts.trpc.procedure_type).toEqual('mutation');
17-
expect(trpcError.contexts.trpc.input).toEqual({ name: 'I love dogs' });
15+
expect(trpcError.contexts?.trpc).toBeDefined();
16+
expect(trpcError.contexts?.trpc?.procedure_type).toEqual('mutation');
17+
expect(trpcError.contexts?.trpc?.procedure_path).toBe('post.throwError');
18+
expect(trpcError.contexts?.trpc?.input).toEqual({ name: 'I love dogs' });
1819
});
1920

2021
test('should create transaction with trpc input for error', async ({ page }) => {
@@ -26,9 +27,5 @@ test('should create transaction with trpc input for error', async ({ page }) =>
2627
await page.click('#error-button');
2728

2829
const trpcTransaction = await trpcTransactionPromise;
29-
3030
expect(trpcTransaction).toBeDefined();
31-
expect(trpcTransaction.contexts.trpc).toBeDefined();
32-
expect(trpcTransaction.contexts.trpc.procedure_type).toEqual('mutation');
33-
expect(trpcTransaction.contexts.trpc.input).toEqual({ name: 'I love dogs' });
3431
});

dev-packages/e2e-tests/test-applications/nextjs-t3/tests/trpc-mutation.test.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,4 @@ test('should create transaction with trpc input for mutation', async ({ page })
1313
const trpcTransaction = await trpcTransactionPromise;
1414

1515
expect(trpcTransaction).toBeDefined();
16-
expect(trpcTransaction.contexts.trpc).toBeDefined();
17-
expect(trpcTransaction.contexts.trpc.procedure_type).toEqual('mutation');
18-
expect(trpcTransaction.contexts.trpc.input).toEqual({ name: 'I love dogs' });
1916
});

dev-packages/e2e-tests/test-applications/node-express/tests/trpc.test.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,6 @@ test('Should record span for trpc query', async ({ baseURL }) => {
3333
description: `trpc/getSomething`,
3434
}),
3535
);
36-
37-
expect(transaction.contexts?.trpc).toMatchObject({
38-
procedure_type: 'query',
39-
input: 'foobar',
40-
});
4136
});
4237

4338
test('Should record transaction for trpc mutation', async ({ baseURL }) => {
@@ -70,10 +65,6 @@ test('Should record transaction for trpc mutation', async ({ baseURL }) => {
7065
description: `trpc/createSomething`,
7166
}),
7267
);
73-
74-
expect(transaction.contexts?.trpc).toMatchObject({
75-
procedure_type: 'mutation',
76-
});
7768
});
7869

7970
test('Should record transaction and error for a crashing trpc handler', async ({ baseURL }) => {
@@ -100,6 +91,9 @@ test('Should record transaction and error for a crashing trpc handler', async ({
10091

10192
await expect(transactionEventPromise).resolves.toBeDefined();
10293
await expect(errorEventPromise).resolves.toBeDefined();
94+
95+
expect((await errorEventPromise).contexts?.trpc?.['procedure_type']).toBe('mutation');
96+
expect((await errorEventPromise).contexts?.trpc?.['procedure_path']).toBe('crashSomething');
10397
});
10498

10599
test('Should record transaction and error for a trpc handler that returns a status code', async ({ baseURL }) => {

dev-packages/e2e-tests/test-applications/react-router-6/tests/sse.test.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,12 @@ test('Waits for sse streaming when sse has been explicitly aborted', async ({ pa
6666
expect(resolveBodyDuration).toBe(0);
6767

6868
// validate abort error was thrown by inspecting console
69-
const consoleBreadcrumb = rootSpan.breadcrumbs?.find(breadcrumb => breadcrumb.category === 'console');
70-
expect(consoleBreadcrumb?.message).toBe('Could not fetch sse AbortError: BodyStreamBuffer was aborted');
69+
expect(rootSpan.breadcrumbs).toContainEqual(
70+
expect.objectContaining({
71+
category: 'console',
72+
message: 'Could not fetch sse AbortError: BodyStreamBuffer was aborted',
73+
}),
74+
);
7175
});
7276

7377
test('Aborts when stream takes longer than 5s, by not updating the span duration', async ({ page }) => {

dev-packages/e2e-tests/test-applications/react-send-to-sentry/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"@types/react-dom": "18.0.0",
1010
"react": "18.2.0",
1111
"react-dom": "18.2.0",
12-
"react-router-dom": "^6.4.1",
12+
"react-router-dom": "6.4.1",
1313
"react-scripts": "5.0.1",
1414
"typescript": "4.9.5"
1515
},

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"graphql": "^16.3.0",
5151
"http-terminator": "^3.2.0",
5252
"ioredis": "^5.4.1",
53+
"knex": "^2.5.1",
5354
"kafkajs": "2.2.4",
5455
"lru-memoizer": "2.3.0",
5556
"mongodb": "^3.7.3",
@@ -65,6 +66,7 @@
6566
"redis-4": "npm:redis@^4.6.14",
6667
"reflect-metadata": "0.2.1",
6768
"rxjs": "^7.8.1",
69+
"tedious": "^18.6.1",
6870
"yargs": "^16.2.0"
6971
},
7072
"devDependencies": {

dev-packages/node-integration-tests/suites/anr/basic.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ const assert = require('assert');
33

44
const Sentry = require('@sentry/node');
55

6+
global._sentryDebugIds = { [new Error().stack]: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa' };
7+
68
setTimeout(() => {
79
process.exit();
810
}, 10000);

dev-packages/node-integration-tests/suites/anr/basic.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import * as crypto from 'crypto';
33

44
import * as Sentry from '@sentry/node';
55

6+
global._sentryDebugIds = { [new Error().stack]: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa' };
7+
68
setTimeout(() => {
79
process.exit();
810
}, 10000);

dev-packages/node-integration-tests/suites/anr/test.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { Event } from '@sentry/types';
12
import { conditionalTest } from '../../utils';
23
import { cleanupChildProcesses, createRunner } from '../../utils/runner';
34

@@ -64,17 +65,33 @@ const ANR_EVENT_WITH_SCOPE = {
6465
]),
6566
};
6667

68+
const ANR_EVENT_WITH_DEBUG_META: Event = {
69+
...ANR_EVENT_WITH_SCOPE,
70+
debug_meta: {
71+
images: [
72+
{
73+
type: 'sourcemap',
74+
debug_id: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa',
75+
code_file: expect.stringContaining('basic.'),
76+
},
77+
],
78+
},
79+
};
80+
6781
conditionalTest({ min: 16 })('should report ANR when event loop blocked', () => {
6882
afterAll(() => {
6983
cleanupChildProcesses();
7084
});
7185

7286
test('CJS', done => {
73-
createRunner(__dirname, 'basic.js').withMockSentryServer().expect({ event: ANR_EVENT_WITH_SCOPE }).start(done);
87+
createRunner(__dirname, 'basic.js').withMockSentryServer().expect({ event: ANR_EVENT_WITH_DEBUG_META }).start(done);
7488
});
7589

7690
test('ESM', done => {
77-
createRunner(__dirname, 'basic.mjs').withMockSentryServer().expect({ event: ANR_EVENT_WITH_SCOPE }).start(done);
91+
createRunner(__dirname, 'basic.mjs')
92+
.withMockSentryServer()
93+
.expect({ event: ANR_EVENT_WITH_DEBUG_META })
94+
.start(done);
7895
});
7996

8097
test('blocked indefinitely', done => {

0 commit comments

Comments
 (0)