Skip to content

Commit 6a52c1c

Browse files
authored
Merge branch 'develop' into tool-calls-anthropic
2 parents 74c18ee + dfdc3b0 commit 6a52c1c

File tree

185 files changed

+6170
-1354
lines changed

Some content is hidden

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

185 files changed

+6170
-1354
lines changed

.github/workflows/build.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -954,7 +954,7 @@ jobs:
954954
- name: Build E2E app
955955
working-directory: ${{ runner.temp }}/test-application
956956
timeout-minutes: 7
957-
run: pnpm ${{ matrix.build-command || 'test:build' }}
957+
run: ${{ matrix.build-command || 'pnpm test:build' }}
958958

959959
- name: Install Playwright
960960
uses: ./.github/actions/install-playwright
@@ -965,7 +965,7 @@ jobs:
965965
- name: Run E2E test
966966
working-directory: ${{ runner.temp }}/test-application
967967
timeout-minutes: 10
968-
run: pnpm test:assert
968+
run: ${{ matrix.assert-command || 'pnpm test:assert' }}
969969

970970
- name: Upload Playwright Traces
971971
uses: actions/upload-artifact@v4
@@ -1075,7 +1075,7 @@ jobs:
10751075
- name: Build E2E app
10761076
working-directory: ${{ runner.temp }}/test-application
10771077
timeout-minutes: 7
1078-
run: pnpm ${{ matrix.build-command || 'test:build' }}
1078+
run: ${{ matrix.build-command || 'pnpm test:build' }}
10791079

10801080
- name: Install Playwright
10811081
uses: ./.github/actions/install-playwright
@@ -1086,7 +1086,7 @@ jobs:
10861086
- name: Run E2E test
10871087
working-directory: ${{ runner.temp }}/test-application
10881088
timeout-minutes: 10
1089-
run: pnpm ${{ matrix.assert-command || 'test:assert' }}
1089+
run: ${{ matrix.assert-command || 'pnpm test:assert' }}
10901090

10911091
- name: Pre-process E2E Test Dumps
10921092
if: failure()

.size-limit.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ module.exports = [
8282
path: 'packages/browser/build/npm/esm/index.js',
8383
import: createImport('init', 'browserTracingIntegration', 'replayIntegration', 'feedbackIntegration'),
8484
gzip: true,
85-
limit: '95 KB',
85+
limit: '96 KB',
8686
},
8787
{
8888
name: '@sentry/browser (incl. Feedback)',
@@ -233,7 +233,7 @@ module.exports = [
233233
import: createImport('init'),
234234
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
235235
gzip: true,
236-
limit: '149 KB',
236+
limit: '150 KB',
237237
},
238238
{
239239
name: '@sentry/node - without tracing',

CHANGELOG.md

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,96 @@
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 @Karibash. Thank you for your contribution!
7+
## 10.7.0
8+
9+
### Important Changes
10+
11+
- **feat(cloudflare): Add `instrumentPrototypeMethods` option to instrument RPC methods for DurableObjects ([#17424](https://github.com/getsentry/sentry-javascript/pull/17424))**
12+
13+
By default, `Sentry.instrumentDurableObjectWithSentry` will not wrap any RPC methods on the prototype. To enable wrapping for RPC methods, set `instrumentPrototypeMethods` to `true` or, if performance is a concern, a list of only the methods you want to instrument:
14+
15+
```js
16+
class MyDurableObjectBase extends DurableObject<Env> {
17+
method1() {
18+
// ...
19+
}
20+
21+
method2() {
22+
// ...
23+
}
24+
25+
method3() {
26+
// ...
27+
}
28+
}
29+
// Export your named class as defined in your wrangler config
30+
export const MyDurableObject = Sentry.instrumentDurableObjectWithSentry(
31+
(env: Env) => ({
32+
dsn: "https://ac49b7af3017c458bd12dab9b3328bfc@o4508482761982032.ingest.de.sentry.io/4508482780987481",
33+
tracesSampleRate: 1.0,
34+
instrumentPrototypeMethods: ['method1', 'method3'],
35+
}),
36+
MyDurableObjectBase,
37+
);
38+
```
39+
40+
## Other Changes
41+
42+
- feat(aws): Add support for streaming handlers ([#17463](https://github.com/getsentry/sentry-javascript/pull/17463))
43+
- feat(core): Stream responses Anthropic AI ([#17460](https://github.com/getsentry/sentry-javascript/pull/17460))
44+
- feat(deps): bump @opentelemetry/instrumentation-aws-sdk from 0.56.0 to 0.57.0 ([#17455](https://github.com/getsentry/sentry-javascript/pull/17455))
45+
- feat(deps): bump @opentelemetry/instrumentation-dataloader from 0.21.0 to 0.21.1 ([#17457](https://github.com/getsentry/sentry-javascript/pull/17457))
46+
- feat(deps): bump @opentelemetry/instrumentation-kafkajs from 0.12.0 to 0.13.0 ([#17469](https://github.com/getsentry/sentry-javascript/pull/17469))
47+
- feat(deps): bump @opentelemetry/instrumentation-mysql2 from 0.49.0 to 0.50.0 ([#17459](https://github.com/getsentry/sentry-javascript/pull/17459))
48+
- feat(deps): bump @prisma/instrumentation from 6.13.0 to 6.14.0 ([#17466](https://github.com/getsentry/sentry-javascript/pull/17466))
49+
- feat(deps): bump @sentry/cli from 2.51.1 to 2.52.0 ([#17458](https://github.com/getsentry/sentry-javascript/pull/17458))
50+
- feat(deps): bump @sentry/rollup-plugin from 4.1.0 to 4.1.1 ([#17456](https://github.com/getsentry/sentry-javascript/pull/17456))
51+
- feat(deps): bump @sentry/webpack-plugin from 4.1.0 to 4.1.1 ([#17467](https://github.com/getsentry/sentry-javascript/pull/17467))
52+
- feat(replay): Add option to skip `requestAnimationFrame` for canvas snapshots ([#17380](https://github.com/getsentry/sentry-javascript/pull/17380))
53+
54+
<details>
55+
<summary> <strong>Internal Changes</strong> </summary>
56+
57+
- test(aws): Run E2E tests in all supported Node versions ([#17446](https://github.com/getsentry/sentry-javascript/pull/17446))
58+
59+
</details>
60+
61+
## 10.6.0
62+
63+
### Important Changes
64+
65+
- **feat(node): Add Anthropic AI integration ([#17348](https://github.com/getsentry/sentry-javascript/pull/17348))**
66+
67+
This release adds support for automatically tracing Anthropic AI SDK requests, providing better observability for AI-powered applications.
68+
69+
- **fix(core): Instrument invoke_agent root span, and support Vercel `ai` v5 ([#17395](https://github.com/getsentry/sentry-javascript/pull/17395))**
70+
71+
This release makes the Sentry `vercelAiIntegration` compatible with version 5 of Vercel `ai`.
72+
73+
- **docs(nuxt): Remove beta notice ([#17400](https://github.com/getsentry/sentry-javascript/pull/17400))**
74+
75+
The Sentry Nuxt SDK is now considered stable and no longer in beta!
76+
77+
### Other Changes
78+
79+
- feat(astro): Align options with shared build time options type ([#17396](https://github.com/getsentry/sentry-javascript/pull/17396))
80+
- feat(aws): Add support for automatic wrapping in ESM ([#17407](https://github.com/getsentry/sentry-javascript/pull/17407))
81+
- feat(node): Add an instrumentation interface for Hono ([#17366](https://github.com/getsentry/sentry-javascript/pull/17366))
82+
- fix(browser): Use `DedicatedWorkerGlobalScope` global object type in `registerWebWorker` ([#17447](https://github.com/getsentry/sentry-javascript/pull/17447))
83+
- fix(core): Only consider ingest endpoint requests when checking `isSentryRequestUrl` ([#17393](https://github.com/getsentry/sentry-javascript/pull/17393))
84+
- fix(node): Fix preloading of instrumentation ([#17403](https://github.com/getsentry/sentry-javascript/pull/17403))
85+
86+
<details>
87+
<summary> <strong>Internal Changes</strong> </summary>
88+
89+
- chore: Add external contributor to CHANGELOG.md ([#17449](https://github.com/getsentry/sentry-javascript/pull/17449))
90+
- chore(deps): bump astro from 4.16.18 to 4.16.19 in /dev-packages/e2e-tests/test-applications/astro-4 ([#17434](https://github.com/getsentry/sentry-javascript/pull/17434))
91+
- test(e2e/firebase): Fix firebase e2e test failing due to outdated rules file ([#17448](https://github.com/getsentry/sentry-javascript/pull/17448))
92+
- test(nextjs): Fix canary tests ([#17416](https://github.com/getsentry/sentry-javascript/pull/17416))
93+
- test(nuxt): Don't rely on flushing for lowQualityTransactionFilter ([#17406](https://github.com/getsentry/sentry-javascript/pull/17406))
94+
- test(solidstart): Don't rely on flushing for lowQualityTransactionFilter ([#17408](https://github.com/getsentry/sentry-javascript/pull/17408))
95+
96+
</details>
897

998
## 10.5.0
1099

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": "10.5.0",
3+
"version": "10.7.0",
44
"main": "index.js",
55
"license": "MIT",
66
"engines": {
@@ -43,7 +43,7 @@
4343
"@babel/preset-typescript": "^7.16.7",
4444
"@playwright/test": "~1.53.2",
4545
"@sentry-internal/rrweb": "2.34.0",
46-
"@sentry/browser": "10.5.0",
46+
"@sentry/browser": "10.7.0",
4747
"@supabase/supabase-js": "2.49.3",
4848
"axios": "1.8.2",
4949
"babel-loader": "^8.2.2",
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import * as Sentry from '@sentry/browser';
2+
import { browserProfilingIntegration } from '@sentry/browser';
3+
4+
window.Sentry = Sentry;
5+
6+
Sentry.init({
7+
dsn: 'https://[email protected]/1337',
8+
integrations: [browserProfilingIntegration()],
9+
tracesSampleRate: 1,
10+
profilesSampleRate: 1,
11+
});
12+
13+
function fibonacci(n) {
14+
if (n <= 1) {
15+
return n;
16+
}
17+
return fibonacci(n - 1) + fibonacci(n - 2);
18+
}
19+
20+
await Sentry.startSpanManual({ name: 'root-fibonacci-2', parentSpan: null, forceTransaction: true }, async span => {
21+
fibonacci(30);
22+
23+
// Timeout to prevent flaky tests. Integration samples every 20ms, if function is too fast it might not get sampled
24+
await new Promise(resolve => setTimeout(resolve, 21));
25+
span.end();
26+
});
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import { expect } from '@playwright/test';
2+
import type { Event, Profile } from '@sentry/core';
3+
import { sentryTest } from '../../../utils/fixtures';
4+
import {
5+
properEnvelopeRequestParser,
6+
shouldSkipTracingTest,
7+
waitForTransactionRequestOnUrl,
8+
} from '../../../utils/helpers';
9+
10+
sentryTest(
11+
'does not send profile envelope when document-policy is not set',
12+
async ({ page, getLocalTestUrl, browserName }) => {
13+
if (shouldSkipTracingTest() || browserName !== 'chromium') {
14+
// Profiling only works when tracing is enabled
15+
sentryTest.skip();
16+
}
17+
18+
const url = await getLocalTestUrl({ testDir: __dirname });
19+
20+
const req = await waitForTransactionRequestOnUrl(page, url);
21+
const transactionEvent = properEnvelopeRequestParser<Event>(req, 0);
22+
const profileEvent = properEnvelopeRequestParser<Profile>(req, 1);
23+
24+
expect(transactionEvent).toBeDefined();
25+
expect(profileEvent).toBeUndefined();
26+
},
27+
);
28+
29+
sentryTest('sends profile envelope in legacy mode', async ({ page, getLocalTestUrl, browserName }) => {
30+
if (shouldSkipTracingTest() || browserName !== 'chromium') {
31+
// Profiling only works when tracing is enabled
32+
sentryTest.skip();
33+
}
34+
35+
const url = await getLocalTestUrl({ testDir: __dirname, responseHeaders: { 'Document-Policy': 'js-profiling' } });
36+
37+
const req = await waitForTransactionRequestOnUrl(page, url);
38+
const profileEvent = properEnvelopeRequestParser<Profile>(req, 1);
39+
expect(profileEvent).toBeDefined();
40+
41+
const profile = profileEvent.profile;
42+
expect(profileEvent.profile).toBeDefined();
43+
44+
expect(profile.samples).toBeDefined();
45+
expect(profile.stacks).toBeDefined();
46+
expect(profile.frames).toBeDefined();
47+
expect(profile.thread_metadata).toBeDefined();
48+
49+
// Samples
50+
expect(profile.samples.length).toBeGreaterThanOrEqual(2);
51+
for (const sample of profile.samples) {
52+
expect(typeof sample.elapsed_since_start_ns).toBe('string');
53+
expect(sample.elapsed_since_start_ns).toMatch(/^\d+$/); // Numeric string
54+
expect(parseInt(sample.elapsed_since_start_ns, 10)).toBeGreaterThanOrEqual(0);
55+
56+
expect(typeof sample.stack_id).toBe('number');
57+
expect(sample.stack_id).toBeGreaterThanOrEqual(0);
58+
expect(sample.thread_id).toBe('0'); // Should be main thread
59+
}
60+
61+
// Stacks
62+
expect(profile.stacks.length).toBeGreaterThan(0);
63+
for (const stack of profile.stacks) {
64+
expect(Array.isArray(stack)).toBe(true);
65+
for (const frameIndex of stack) {
66+
expect(typeof frameIndex).toBe('number');
67+
expect(frameIndex).toBeGreaterThanOrEqual(0);
68+
expect(frameIndex).toBeLessThan(profile.frames.length);
69+
}
70+
}
71+
72+
// Frames
73+
expect(profile.frames.length).toBeGreaterThan(0);
74+
for (const frame of profile.frames) {
75+
expect(frame).toHaveProperty('function');
76+
expect(frame).toHaveProperty('abs_path');
77+
expect(frame).toHaveProperty('lineno');
78+
expect(frame).toHaveProperty('colno');
79+
80+
expect(typeof frame.function).toBe('string');
81+
expect(typeof frame.abs_path).toBe('string');
82+
expect(typeof frame.lineno).toBe('number');
83+
expect(typeof frame.colno).toBe('number');
84+
}
85+
86+
const functionNames = profile.frames.map(frame => frame.function).filter(name => name !== '');
87+
88+
if ((process.env.PW_BUNDLE || '').endsWith('min')) {
89+
// Function names are minified in minified bundles
90+
expect(functionNames.length).toBeGreaterThan(0);
91+
expect((functionNames as string[]).every(name => name?.length > 0)).toBe(true); // Just make sure they're not empty strings
92+
} else {
93+
expect(functionNames).toEqual(
94+
expect.arrayContaining([
95+
'_startRootSpan',
96+
'withScope',
97+
'createChildOrRootSpan',
98+
'startSpanManual',
99+
'startProfileForSpan',
100+
'startJSSelfProfile',
101+
]),
102+
);
103+
}
104+
105+
expect(profile.thread_metadata).toHaveProperty('0');
106+
expect(profile.thread_metadata['0']).toHaveProperty('name');
107+
expect(profile.thread_metadata['0'].name).toBe('main');
108+
109+
// Test that profile duration makes sense (should be > 20ms based on test setup)
110+
const startTime = parseInt(profile.samples[0].elapsed_since_start_ns, 10);
111+
const endTime = parseInt(profile.samples[profile.samples.length - 1].elapsed_since_start_ns, 10);
112+
const durationNs = endTime - startTime;
113+
const durationMs = durationNs / 1_000_000; // Convert ns to ms
114+
115+
// Should be at least 20ms based on our setTimeout(21) in the test
116+
expect(durationMs).toBeGreaterThan(20);
117+
});

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export type TestFixtures = {
3535
skipRouteHandler?: boolean;
3636
skipDsnRouteHandler?: boolean;
3737
handleLazyLoadedFeedback?: boolean;
38+
responseHeaders?: Record<string, string>;
3839
}) => Promise<string>;
3940
forceFlushReplay: () => Promise<string>;
4041
enableConsole: () => void;
@@ -59,7 +60,13 @@ const sentryTest = base.extend<TestFixtures>({
5960

6061
getLocalTestUrl: ({ page }, use) => {
6162
return use(
62-
async ({ testDir, skipRouteHandler = false, skipDsnRouteHandler = false, handleLazyLoadedFeedback = false }) => {
63+
async ({
64+
testDir,
65+
skipRouteHandler = false,
66+
skipDsnRouteHandler = false,
67+
handleLazyLoadedFeedback = false,
68+
responseHeaders = {},
69+
}) => {
6370
const pagePath = `${TEST_HOST}/index.html`;
6471

6572
const tmpDir = path.join(testDir, 'dist', crypto.randomUUID());
@@ -86,7 +93,9 @@ const sentryTest = base.extend<TestFixtures>({
8693
const file = route.request().url().split('/').pop();
8794
const filePath = path.resolve(tmpDir, `./${file}`);
8895

89-
return fs.existsSync(filePath) ? route.fulfill({ path: filePath }) : route.continue();
96+
return fs.existsSync(filePath)
97+
? route.fulfill({ path: filePath, headers: responseHeaders })
98+
: route.continue();
9099
});
91100

92101
if (handleLazyLoadedFeedback) {

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
feedbackIntegration: 'feedback',
3737
moduleMetadataIntegration: 'modulemetadata',
3838
graphqlClientIntegration: 'graphqlclient',
39+
browserProfilingIntegration: 'browserprofiling',
3940
// technically, this is not an integration, but let's add it anyway for simplicity
4041
makeMultiplexedTransport: 'multiplexedtransport',
4142
};

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const envelopeParser = (request: Request | null): unknown[] => {
2929
});
3030
};
3131

32+
// Rather use the `properEnvelopeRequestParser`, as the `envelopeParser` does not follow the envelope spec.
3233
export const envelopeRequestParser = <T = SentryEvent>(request: Request | null, envelopeIndex = 2): T => {
3334
return envelopeParser(request)[envelopeIndex] as T;
3435
};
@@ -79,8 +80,12 @@ function getEventAndTraceHeader(envelope: EventEnvelope): EventAndTraceHeader {
7980
return [event, trace];
8081
}
8182

82-
export const properEnvelopeRequestParser = <T = SentryEvent>(request: Request | null, envelopeIndex = 1): T => {
83-
return properEnvelopeParser(request)[0]?.[envelopeIndex] as T;
83+
export const properEnvelopeRequestParser = <T = SentryEvent>(
84+
request: Request | null,
85+
envelopeItemIndex: number,
86+
envelopeIndex = 1, // 1 is usually the payload of the envelope (0 is the header)
87+
): T => {
88+
return properEnvelopeParser(request)[envelopeItemIndex]?.[envelopeIndex] as T;
8489
};
8590

8691
export const properFullEnvelopeRequestParser = <T extends Envelope>(request: Request | null): T => {

dev-packages/bundle-analyzer-scenarios/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@sentry-internal/bundle-analyzer-scenarios",
3-
"version": "10.5.0",
3+
"version": "10.7.0",
44
"description": "Scenarios to test bundle analysis with",
55
"repository": "git://github.com/getsentry/sentry-javascript.git",
66
"homepage": "https://github.com/getsentry/sentry-javascript/tree/master/dev-packages/bundle-analyzer-scenarios",

0 commit comments

Comments
 (0)