Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ jobs:
- bundle_min
- bundle_replay
- bundle_tracing
- bundle_tracing_logs_metrics
- bundle_tracing_replay
- bundle_tracing_replay_feedback
- bundle_tracing_replay_feedback_min
Expand Down
29 changes: 21 additions & 8 deletions .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = [
path: 'packages/browser/build/npm/esm/prod/index.js',
import: createImport('init'),
gzip: true,
limit: '25 KB',
limit: '25.5 KB',
},
{
name: '@sentry/browser - with treeshaking flags',
Expand Down Expand Up @@ -148,7 +148,7 @@ module.exports = [
import: createImport('init', 'ErrorBoundary', 'reactRouterV6BrowserTracingIntegration'),
ignore: ['react/jsx-runtime'],
gzip: true,
limit: '44 KB',
limit: '44.5 KB',
},
// Vue SDK (ESM)
{
Expand All @@ -171,20 +171,26 @@ module.exports = [
path: 'packages/svelte/build/esm/index.js',
import: createImport('init'),
gzip: true,
limit: '25 KB',
limit: '25.5 KB',
},
// Browser CDN bundles
{
name: 'CDN Bundle',
path: createCDNPath('bundle.min.js'),
gzip: true,
limit: '27.5 KB',
limit: '28 KB',
},
{
name: 'CDN Bundle (incl. Tracing)',
path: createCDNPath('bundle.tracing.min.js'),
gzip: true,
limit: '42.5 KB',
limit: '43 KB',
},
{
name: 'CDN Bundle (incl. Tracing, Logs, Metrics)',
path: createCDNPath('bundle.tracing.logs.metrics.min.js'),
gzip: true,
limit: '44 KB',
},
{
name: 'CDN Bundle (incl. Tracing, Replay)',
Expand Down Expand Up @@ -213,6 +219,13 @@ module.exports = [
brotli: false,
limit: '127 KB',
},
{
name: 'CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed',
path: createCDNPath('bundle.tracing.logs.metrics.min.js'),
gzip: false,
brotli: false,
limit: '130 KB',
},
{
name: 'CDN Bundle (incl. Tracing, Replay) - uncompressed',
path: createCDNPath('bundle.tracing.replay.min.js'),
Expand All @@ -234,7 +247,7 @@ module.exports = [
import: createImport('init'),
ignore: ['next/router', 'next/constants'],
gzip: true,
limit: '46.5 KB',
limit: '47 KB',
},
// SvelteKit SDK (ESM)
{
Expand All @@ -243,7 +256,7 @@ module.exports = [
import: createImport('init'),
ignore: ['$app/stores'],
gzip: true,
limit: '42.5 KB',
limit: '43 KB',
},
// Node-Core SDK (ESM)
{
Expand All @@ -261,7 +274,7 @@ module.exports = [
import: createImport('init'),
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
gzip: true,
limit: '162.5 KB',
limit: '163 KB',
},
{
name: '@sentry/node - without tracing',
Expand Down
45 changes: 45 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,51 @@

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

## 10.34.0

### Important Changes

- **feat(core): Add option to enhance the fetch error message ([#18466](https://github.com/getsentry/sentry-javascript/pull/18466))**

You can now enable enhanced fetch error messages by setting the `enhancedFetchErrorMessage` option. When enabled, the SDK will include additional context in fetch error messages to help with debugging.

- **feat(nextjs): Add routeManifestInjection option to exclude routes from client bundle ([#18798](https://github.com/getsentry/sentry-javascript/pull/18798))**

A new `routeManifestInjection` option allows you to exclude sensitive routes from being injected into the client bundle.

- **feat(tanstackstart-react): Add `wrapMiddlewaresWithSentry` for manual middleware instrumentation ([#18680](https://github.com/getsentry/sentry-javascript/pull/18680))**

You can now wrap your middlewares using `wrapMiddlewaresWithSentry`, allowing you to trace middleware execution in your TanStack Start application.

```ts
import { createMiddleware } from '@tanstack/react-start';
import { wrapMiddlewaresWithSentry } from '@sentry/tanstackstart-react';

const loggingMiddleware = createMiddleware({ type: 'function' }).server(async ({ next }) => {
console.log('Request started');
return next();
});

export const [wrappedLoggingMiddleware] = wrapMiddlewaresWithSentry({ loggingMiddleware });
```

### Other Changes

- feat(browser): Add CDN bundle for `tracing.logs.metrics` ([#18784](https://github.com/getsentry/sentry-javascript/pull/18784))
- feat(core,node-core): Consolidate bun and node types with ServerRuntimeOptions ([#18734](https://github.com/getsentry/sentry-javascript/pull/18734))
- feat(nextjs): Remove tracing from generation function template ([#18733](https://github.com/getsentry/sentry-javascript/pull/18733))
- fix(core): Don't record outcomes for failed client reports ([#18808](https://github.com/getsentry/sentry-javascript/pull/18808))
- fix(deno,cloudflare): Prioritize name from params over name from options ([#18800](https://github.com/getsentry/sentry-javascript/pull/18800))
- fix(web-vitals): Add error handling for invalid object keys in `WeakMap` ([#18809](https://github.com/getsentry/sentry-javascript/pull/18809))

<details>
<summary><strong>Internal Changes</strong></summary>

- ref(nextjs): Split `withSentryConfig` ([#18777](https://github.com/getsentry/sentry-javascript/pull/18777))
- test(e2e): Pin @shopify/remix-oxygen to unblock ci ([#18811](https://github.com/getsentry/sentry-javascript/pull/18811))

</details>

## 10.33.0

### Important Changes
Expand Down
5 changes: 3 additions & 2 deletions dev-packages/browser-integration-tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ To filter tests by their title:

You can refer to [Playwright documentation](https://playwright.dev/docs/test-cli) for other CLI options.

You can set env variable `PW_BUNDLE` to set specific build or bundle to test against. Available options: `esm`, `cjs`,
`bundle`, `bundle_min`
You can set env variable `PW_BUNDLE` to set specific build or bundle to test against. Available options include: `esm`, `cjs`,
`bundle`, `bundle_min`, `bundle_tracing`, `bundle_tracing_logs_metrics`, `bundle_replay`, `bundle_tracing_replay_feedback`, and more.
See `package.json` scripts for the full list of `test:bundle:*` commands.

### Troubleshooting

Expand Down
3 changes: 3 additions & 0 deletions dev-packages/browser-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
"test:bundle:replay:min": "PW_BUNDLE=bundle_replay_min yarn test",
"test:bundle:tracing": "PW_BUNDLE=bundle_tracing yarn test",
"test:bundle:tracing:min": "PW_BUNDLE=bundle_tracing_min yarn test",
"test:bundle:tracing_logs_metrics": "PW_BUNDLE=bundle_tracing_logs_metrics yarn test",
"test:bundle:tracing_logs_metrics:min": "PW_BUNDLE=bundle_tracing_logs_metrics_min yarn test",
"test:bundle:tracing_logs_metrics:debug_min": "PW_BUNDLE=bundle_tracing_logs_metrics_debug_min yarn test",
"test:bundle:full": "PW_BUNDLE=bundle_tracing_replay_feedback yarn test",
"test:bundle:full:min": "PW_BUNDLE=bundle_tracing_replay_feedback_min yarn test",
"test:cjs": "PW_BUNDLE=cjs yarn test",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;

Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
enhanceFetchErrorMessages: false,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Based on possible TypeError exceptions from https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch

// Network error (e.g. ad-blocked, offline, page does not exist, ...)
window.networkError = () => {
fetch('http://sentry-test-external.io/does-not-exist');
};

window.networkErrorSubdomain = () => {
fetch('http://subdomain.sentry-test-external.io/does-not-exist');
};

window.networkErrorWithPort = () => {
fetch('http://sentry-test-external.io:3000/does-not-exist');
};

// Invalid header also produces TypeError
window.invalidHeaderName = () => {
fetch('http://sentry-test-external.io/invalid-header-name', { headers: { 'C ontent-Type': 'text/xml' } });
};

// Invalid header value also produces TypeError
window.invalidHeaderValue = () => {
fetch('http://sentry-test-external.io/invalid-header-value', { headers: ['Content-Type', 'text/html', 'extra'] });
};

// Invalid URL scheme
window.invalidUrlScheme = () => {
fetch('blub://sentry-test-external.io/invalid-scheme');
};

// URL includes credentials
window.credentialsInUrl = () => {
fetch('https://user:password@sentry-test-external.io/credentials-in-url');
};

// Invalid mode
window.invalidMode = () => {
fetch('https://sentry-test-external.io/invalid-mode', { mode: 'navigate' });
};

// Invalid request method
window.invalidMethod = () => {
fetch('http://sentry-test-external.io/invalid-method', { method: 'CONNECT' });
};

// No-cors mode with cors-required method
window.noCorsMethod = () => {
fetch('http://sentry-test-external.io/no-cors-method', { mode: 'no-cors', method: 'PUT' });
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { expect } from '@playwright/test';
import { sentryTest } from '../../../utils/fixtures';
import { envelopeRequestParser, waitForErrorRequest } from '../../../utils/helpers';

sentryTest(
'enhanceFetchErrorMessages: false: enhances error for Sentry while preserving original',
async ({ getLocalTestUrl, page, browserName }) => {
const url = await getLocalTestUrl({ testDir: __dirname });
const reqPromise = waitForErrorRequest(page);
const pageErrorPromise = new Promise<string>(resolve => {
page.on('pageerror', error => {
resolve(error.message);
});
});

await page.goto(url);
await page.evaluate('networkError()');

const [req, pageErrorMessage] = await Promise.all([reqPromise, pageErrorPromise]);
const eventData = envelopeRequestParser(req);
const originalErrorMap: Record<string, string> = {
chromium: 'Failed to fetch',
webkit: 'Load failed',
firefox: 'NetworkError when attempting to fetch resource.',
};

const originalError = originalErrorMap[browserName];

expect(pageErrorMessage).toContain(originalError);
expect(pageErrorMessage).not.toContain('sentry-test-external.io');

expect(eventData.exception?.values).toHaveLength(1);
expect(eventData.exception?.values?.[0]).toMatchObject({
type: 'TypeError',
value: originalError,
mechanism: {
handled: false,
type: 'auto.browser.global_handlers.onunhandledrejection',
},
});
},
);

sentryTest(
'enhanceFetchErrorMessages: false: enhances subdomain errors',
async ({ getLocalTestUrl, page, browserName }) => {
const url = await getLocalTestUrl({ testDir: __dirname });
const reqPromise = waitForErrorRequest(page);
const pageErrorPromise = new Promise<string>(resolve => page.on('pageerror', error => resolve(error.message)));

await page.goto(url);
await page.evaluate('networkErrorSubdomain()');

const [req, pageErrorMessage] = await Promise.all([reqPromise, pageErrorPromise]);
const eventData = envelopeRequestParser(req);

const originalErrorMap: Record<string, string> = {
chromium: 'Failed to fetch',
webkit: 'Load failed',
firefox: 'NetworkError when attempting to fetch resource.',
};

const originalError = originalErrorMap[browserName];

expect(pageErrorMessage).toContain(originalError);
expect(pageErrorMessage).not.toContain('subdomain.sentry-test-external.io');
expect(eventData.exception?.values).toHaveLength(1);
expect(eventData.exception?.values?.[0]).toMatchObject({
type: 'TypeError',
value: originalError,
mechanism: {
handled: false,
type: 'auto.browser.global_handlers.onunhandledrejection',
},
});
},
);

sentryTest(
'enhanceFetchErrorMessages: false: includes port in hostname',
async ({ getLocalTestUrl, page, browserName }) => {
const url = await getLocalTestUrl({ testDir: __dirname });
const reqPromise = waitForErrorRequest(page);

const pageErrorPromise = new Promise<string>(resolve => page.on('pageerror', error => resolve(error.message)));

await page.goto(url);
await page.evaluate('networkErrorWithPort()');

const [req, pageErrorMessage] = await Promise.all([reqPromise, pageErrorPromise]);
const eventData = envelopeRequestParser(req);

const originalErrorMap: Record<string, string> = {
chromium: 'Failed to fetch',
webkit: 'Load failed',
firefox: 'NetworkError when attempting to fetch resource.',
};

const originalError = originalErrorMap[browserName];

expect(pageErrorMessage).toContain(originalError);
expect(pageErrorMessage).not.toContain('sentry-test-external.io:3000');
expect(eventData.exception?.values).toHaveLength(1);
expect(eventData.exception?.values?.[0]).toMatchObject({
type: 'TypeError',
value: originalError,
mechanism: {
handled: false,
type: 'auto.browser.global_handlers.onunhandledrejection',
},
});
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;

Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
enhanceFetchErrorMessages: 'report-only',
});
Loading
Loading