Skip to content

Commit 1a21bdf

Browse files
authored
Merge pull request #15400 from getsentry/prepare-release/9.1.0
meta(changelog): Update changelog for 9.1.0
2 parents 6894f8a + 973f241 commit 1a21bdf

File tree

98 files changed

+3148
-761
lines changed

Some content is hidden

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

98 files changed

+3148
-761
lines changed

.github/workflows/build.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ env:
5959
nx-Linux-${{ github.ref }}
6060
nx-Linux
6161
62+
# https://bsky.app/profile/joyeecheung.bsky.social/post/3lhy6o54fo22h
63+
# Apparently some of our CI failures are attributable to a corrupt v8 cache, causing v8 failures with: "Check failed: current == end_slot_index.".
64+
# This option both controls the `v8-compile-cache-lib` and `v8-compile-cache` packages.
65+
DISABLE_V8_COMPILE_CACHE: '1'
66+
6267
jobs:
6368
job_get_metadata:
6469
name: Get Metadata

CHANGELOG.md

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

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

13+
## 9.1.0
14+
15+
- feat(browser): Add `graphqlClientIntegration` ([#13783](https://github.com/getsentry/sentry-javascript/pull/13783))
16+
- feat(core): Allow for nested trpc context ([#15379](https://github.com/getsentry/sentry-javascript/pull/15379))
17+
- feat(core): Create types and utilities for span links ([#15375](https://github.com/getsentry/sentry-javascript/pull/15375))
18+
- feat(deps): bump @opentelemetry/instrumentation-pg from 0.50.0 to 0.51.0 ([#15273](https://github.com/getsentry/sentry-javascript/pull/15273))
19+
- feat(node): Extract Sentry-specific node-fetch instrumentation ([#15231](https://github.com/getsentry/sentry-javascript/pull/15231))
20+
- feat(vue): Support Pinia v3 ([#15383](https://github.com/getsentry/sentry-javascript/pull/15383))
21+
- fix(sveltekit): Avoid request body double read errors ([#15368](https://github.com/getsentry/sentry-javascript/pull/15368))
22+
- fix(sveltekit): Avoid top-level `vite` import ([#15371](https://github.com/getsentry/sentry-javascript/pull/15371))
23+
24+
Work in this release was contributed by @Zen-cronic and @filips-alpe. Thank you for your contribution!
25+
1326
## 9.0.1
1427

1528
- ref(flags): rename unleash integration param ([#15343](https://github.com/getsentry/sentry-javascript/pull/15343))
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const query = `query Test{
2+
people {
3+
name
4+
pet
5+
}
6+
}`;
7+
8+
const requestBody = JSON.stringify({ query });
9+
10+
fetch('http://sentry-test.io/foo', {
11+
method: 'POST',
12+
headers: {
13+
Accept: 'application/json',
14+
'Content-Type': 'application/json',
15+
},
16+
body: requestBody,
17+
});
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event } from '@sentry/core';
3+
4+
import { sentryTest } from '../../../../utils/fixtures';
5+
import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers';
6+
7+
// Duplicate from subject.js
8+
const query = `query Test{
9+
people {
10+
name
11+
pet
12+
}
13+
}`;
14+
const queryPayload = JSON.stringify({ query });
15+
16+
sentryTest('should update spans for GraphQL fetch requests', async ({ getLocalTestUrl, page }) => {
17+
if (shouldSkipTracingTest()) {
18+
return;
19+
}
20+
21+
const url = await getLocalTestUrl({ testDir: __dirname });
22+
23+
await page.route('**/foo', route => {
24+
return route.fulfill({
25+
status: 200,
26+
body: JSON.stringify({
27+
people: [
28+
{ name: 'Amy', pet: 'dog' },
29+
{ name: 'Jay', pet: 'cat' },
30+
],
31+
}),
32+
headers: {
33+
'Content-Type': 'application/json',
34+
},
35+
});
36+
});
37+
38+
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
39+
const requestSpans = eventData.spans?.filter(({ op }) => op === 'http.client');
40+
41+
expect(requestSpans).toHaveLength(1);
42+
43+
expect(requestSpans![0]).toMatchObject({
44+
description: 'POST http://sentry-test.io/foo (query Test)',
45+
parent_span_id: eventData.contexts?.trace?.span_id,
46+
span_id: expect.any(String),
47+
start_timestamp: expect.any(Number),
48+
timestamp: expect.any(Number),
49+
trace_id: eventData.contexts?.trace?.trace_id,
50+
status: 'ok',
51+
data: expect.objectContaining({
52+
type: 'fetch',
53+
'http.method': 'POST',
54+
'http.url': 'http://sentry-test.io/foo',
55+
url: 'http://sentry-test.io/foo',
56+
'server.address': 'sentry-test.io',
57+
'sentry.op': 'http.client',
58+
'sentry.origin': 'auto.http.browser',
59+
'graphql.document': queryPayload,
60+
}),
61+
});
62+
});
63+
64+
sentryTest('should update breadcrumbs for GraphQL fetch requests', async ({ getLocalTestUrl, page }) => {
65+
if (shouldSkipTracingTest()) {
66+
return;
67+
}
68+
69+
const url = await getLocalTestUrl({ testDir: __dirname });
70+
71+
await page.route('**/foo', route => {
72+
return route.fulfill({
73+
status: 200,
74+
body: JSON.stringify({
75+
people: [
76+
{ name: 'Amy', pet: 'dog' },
77+
{ name: 'Jay', pet: 'cat' },
78+
],
79+
}),
80+
headers: {
81+
'Content-Type': 'application/json',
82+
},
83+
});
84+
});
85+
86+
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
87+
88+
expect(eventData?.breadcrumbs?.length).toBe(1);
89+
90+
expect(eventData!.breadcrumbs![0]).toEqual({
91+
timestamp: expect.any(Number),
92+
category: 'fetch',
93+
type: 'http',
94+
data: {
95+
method: 'POST',
96+
status_code: 200,
97+
url: 'http://sentry-test.io/foo',
98+
__span: expect.any(String),
99+
'graphql.document': query,
100+
'graphql.operation': 'query Test',
101+
},
102+
});
103+
});
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as Sentry from '@sentry/browser';
2+
// Must import this like this to ensure the test transformation for CDN bundles works
3+
import { graphqlClientIntegration } from '@sentry/browser';
4+
5+
window.Sentry = Sentry;
6+
7+
Sentry.init({
8+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
9+
integrations: [
10+
Sentry.browserTracingIntegration(),
11+
graphqlClientIntegration({
12+
endpoints: ['http://sentry-test.io/foo'],
13+
}),
14+
],
15+
tracesSampleRate: 1,
16+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const xhr = new XMLHttpRequest();
2+
3+
xhr.open('POST', 'http://sentry-test.io/foo');
4+
xhr.setRequestHeader('Accept', 'application/json');
5+
xhr.setRequestHeader('Content-Type', 'application/json');
6+
7+
const query = `query Test{
8+
people {
9+
name
10+
pet
11+
}
12+
}`;
13+
14+
const requestBody = JSON.stringify({ query });
15+
xhr.send(requestBody);
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event } from '@sentry/core';
3+
4+
import { sentryTest } from '../../../../utils/fixtures';
5+
import { getFirstSentryEnvelopeRequest, shouldSkipTracingTest } from '../../../../utils/helpers';
6+
7+
// Duplicate from subject.js
8+
const query = `query Test{
9+
people {
10+
name
11+
pet
12+
}
13+
}`;
14+
const queryPayload = JSON.stringify({ query });
15+
16+
sentryTest('should update spans for GraphQL XHR requests', async ({ getLocalTestUrl, page }) => {
17+
if (shouldSkipTracingTest()) {
18+
return;
19+
}
20+
21+
const url = await getLocalTestUrl({ testDir: __dirname });
22+
23+
await page.route('**/foo', route => {
24+
return route.fulfill({
25+
status: 200,
26+
body: JSON.stringify({
27+
people: [
28+
{ name: 'Amy', pet: 'dog' },
29+
{ name: 'Jay', pet: 'cat' },
30+
],
31+
}),
32+
headers: {
33+
'Content-Type': 'application/json',
34+
},
35+
});
36+
});
37+
38+
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
39+
const requestSpans = eventData.spans?.filter(({ op }) => op === 'http.client');
40+
41+
expect(requestSpans).toHaveLength(1);
42+
43+
expect(requestSpans![0]).toMatchObject({
44+
description: 'POST http://sentry-test.io/foo (query Test)',
45+
parent_span_id: eventData.contexts?.trace?.span_id,
46+
span_id: expect.any(String),
47+
start_timestamp: expect.any(Number),
48+
timestamp: expect.any(Number),
49+
trace_id: eventData.contexts?.trace?.trace_id,
50+
status: 'ok',
51+
data: {
52+
type: 'xhr',
53+
'http.method': 'POST',
54+
'http.url': 'http://sentry-test.io/foo',
55+
url: 'http://sentry-test.io/foo',
56+
'server.address': 'sentry-test.io',
57+
'sentry.op': 'http.client',
58+
'sentry.origin': 'auto.http.browser',
59+
'graphql.document': queryPayload,
60+
},
61+
});
62+
});
63+
64+
sentryTest('should update breadcrumbs for GraphQL XHR requests', async ({ getLocalTestUrl, page }) => {
65+
if (shouldSkipTracingTest()) {
66+
return;
67+
}
68+
69+
const url = await getLocalTestUrl({ testDir: __dirname });
70+
71+
await page.route('**/foo', route => {
72+
return route.fulfill({
73+
status: 200,
74+
body: JSON.stringify({
75+
people: [
76+
{ name: 'Amy', pet: 'dog' },
77+
{ name: 'Jay', pet: 'cat' },
78+
],
79+
}),
80+
headers: {
81+
'Content-Type': 'application/json',
82+
},
83+
});
84+
});
85+
86+
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
87+
88+
expect(eventData?.breadcrumbs?.length).toBe(1);
89+
90+
expect(eventData!.breadcrumbs![0]).toEqual({
91+
timestamp: expect.any(Number),
92+
category: 'xhr',
93+
type: 'http',
94+
data: {
95+
method: 'POST',
96+
status_code: 200,
97+
url: 'http://sentry-test.io/foo',
98+
'graphql.document': query,
99+
'graphql.operation': 'query Test',
100+
},
101+
});
102+
});

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const IMPORTED_INTEGRATION_CDN_BUNDLE_PATHS: Record<string, string> = {
3636
reportingObserverIntegration: 'reportingobserver',
3737
feedbackIntegration: 'feedback',
3838
moduleMetadataIntegration: 'modulemetadata',
39+
graphqlClientIntegration: 'graphqlclient',
3940
// technically, this is not an integration, but let's add it anyway for simplicity
4041
makeMultiplexedTransport: 'multiplexedtransport',
4142
};

dev-packages/e2e-tests/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"clean": "rimraf tmp node_modules && yarn clean:test-applications && yarn clean:pnpm",
1717
"ci:build-matrix": "ts-node ./lib/getTestMatrix.ts",
1818
"ci:build-matrix-optional": "ts-node ./lib/getTestMatrix.ts --optional=true",
19-
"clean:test-applications": "rimraf --glob test-applications/**/{node_modules,dist,build,.next,.nuxt,.sveltekit,pnpm-lock.yaml,.last-run.json,test-results}",
19+
"clean:test-applications": "rimraf --glob test-applications/**/{node_modules,dist,build,.next,.nuxt,.sveltekit,.react-router,pnpm-lock.yaml,.last-run.json,test-results}",
2020
"clean:pnpm": "pnpm store prune"
2121
},
2222
"devDependencies": {

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,11 @@ export const appRouter = t.router({
115115
await new Promise(resolve => setTimeout(resolve, 400));
116116
return { success: true };
117117
}),
118-
crashSomething: procedure.mutation(() => {
119-
throw new Error('I crashed in a trpc handler');
120-
}),
118+
crashSomething: procedure
119+
.input(z.object({ nested: z.object({ nested: z.object({ nested: z.string() }) }) }))
120+
.mutation(() => {
121+
throw new Error('I crashed in a trpc handler');
122+
}),
121123
dontFindSomething: procedure.mutation(() => {
122124
throw new TRPCError({ code: 'NOT_FOUND', cause: new Error('Page not found') });
123125
}),

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,22 @@ test('Should record transaction and error for a crashing trpc handler', async ({
8787
],
8888
});
8989

90-
await expect(trpcClient.crashSomething.mutate()).rejects.toBeDefined();
90+
await expect(trpcClient.crashSomething.mutate({ nested: { nested: { nested: 'foobar' } } })).rejects.toBeDefined();
9191

9292
await expect(transactionEventPromise).resolves.toBeDefined();
9393
await expect(errorEventPromise).resolves.toBeDefined();
9494

9595
expect((await errorEventPromise).contexts?.trpc?.['procedure_type']).toBe('mutation');
9696
expect((await errorEventPromise).contexts?.trpc?.['procedure_path']).toBe('crashSomething');
97+
98+
// Should record nested context
99+
expect((await errorEventPromise).contexts?.trpc?.['input']).toEqual({
100+
nested: {
101+
nested: {
102+
nested: 'foobar',
103+
},
104+
},
105+
});
97106
});
98107

99108
test('Should record transaction and error for a trpc handler that returns a status code', async ({ baseURL }) => {
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
14+
# misc
15+
.DS_Store
16+
.env.local
17+
.env.development.local
18+
.env.test.local
19+
.env.production.local
20+
21+
npm-debug.log*
22+
yarn-debug.log*
23+
yarn-error.log*
24+
25+
/test-results/
26+
/playwright-report/
27+
/playwright/.cache/
28+
29+
!*.d.ts
30+
31+
# react router
32+
.react-router
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@sentry:registry=http://127.0.0.1:4873
2+
@sentry-internal:registry=http://127.0.0.1:4873
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
html,
2+
body {
3+
@media (prefers-color-scheme: dark) {
4+
color-scheme: dark;
5+
}
6+
}

0 commit comments

Comments
 (0)