Skip to content

Commit

Permalink
Merge pull request #12236 from getsentry/prepare-release/8.5.0
Browse files Browse the repository at this point in the history
meta: Add CHANGELOG entry for `8.5.0`
  • Loading branch information
Lms24 committed May 27, 2024
2 parents 672cdd7 + f32f88d commit 27a47f2
Show file tree
Hide file tree
Showing 147 changed files with 3,027 additions and 714 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -436,8 +436,6 @@ jobs:
env:
DEPENDENCY_CACHE_KEY: ${{ needs.job_build.outputs.dependency_cache_key }}
- name: Run tests
env:
NODE_VERSION: 16
run: yarn test-ci-browser
- name: Compute test coverage
uses: codecov/codecov-action@v4
Expand Down Expand Up @@ -1005,7 +1003,9 @@ jobs:
'create-remix-app-express-vite-dev',
'debug-id-sourcemaps',
'node-express-esm-loader',
'node-express-esm-preload',
'node-express-esm-without-loader',
'node-express-cjs-preload',
'nextjs-app-dir',
'nextjs-14',
'nextjs-15',
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/canary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ jobs:
strategy:
fail-fast: false
matrix:
scenario: [ember-release, embroider-optimized, ember-4.0]
# scenario: [ember-release, embroider-optimized, ember-4.0]
scenario: [ember-4.0]
steps:
- name: 'Check out current commit'
uses: actions/checkout@v4
Expand Down
16 changes: 16 additions & 0 deletions .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@ module.exports = [
gzip: true,
limit: '87 KB',
},
{
name: '@sentry/browser (incl. Tracing, Replay, Feedback, metrics)',
path: 'packages/browser/build/npm/esm/index.js',
import: createImport('init', 'browserTracingIntegration', 'replayIntegration', 'feedbackIntegration', 'metrics'),
gzip: true,
limit: '100 KB',
},
{
name: '@sentry/browser (incl. metrics)',
path: 'packages/browser/build/npm/esm/index.js',
import: createImport('init', 'metrics'),
gzip: true,
limit: '40 KB',
},
{
name: '@sentry/browser (incl. Feedback)',
path: 'packages/browser/build/npm/esm/index.js',
Expand All @@ -83,13 +97,15 @@ module.exports = [
name: '@sentry/react',
path: 'packages/react/build/esm/index.js',
import: createImport('init', 'ErrorBoundary'),
ignore: ['react/jsx-runtime'],
gzip: true,
limit: '27 KB',
},
{
name: '@sentry/react (incl. Tracing)',
path: 'packages/react/build/esm/index.js',
import: createImport('init', 'ErrorBoundary', 'reactRouterV6BrowserTracingIntegration'),
ignore: ['react/jsx-runtime'],
gzip: true,
limit: '37 KB',
},
Expand Down
53 changes: 53 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,59 @@

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

## 8.5.0

### Important Changes

- **feat(react): Add React 19 to peer deps (#12207)**

This release adds support for React 19 in the `@sentry/react` SDK package.

- **feat(node): Add `@sentry/node/preload` hook (#12213)**

This release adds a new way to initialize `@sentry/node`, which allows you to use the SDK with performance
instrumentation even if you cannot call `Sentry.init()` at the very start of your app.

First, run the SDK like this:

```bash
node --require @sentry/node/preload ./app.js
```

Now, you can initialize and import the rest of the SDK later or asynchronously:

```js
const express = require('express');
const Sentry = require('@sentry/node');

const dsn = await getSentryDsn();
Sentry.init({ dsn });
```

For more details, head over to the
[PR Description of the new feature](https://github.com/getsentry/sentry-javascript/pull/12213). Our docs will be updated
soon with a new guide.

### Other Changes

- feat(browser): Do not include metrics in base CDN bundle (#12230)
- feat(core): Add `startNewTrace` API (#12138)
- feat(core): Allow to pass custom scope to `captureFeedback()` (#12216)
- feat(core): Only allow `SerializedSession` in session envelope items (#11979)
- feat(nextjs): Use Vercel's `waitUntil` to defer freezing of Vercel Lambdas (#12133)
- feat(node): Ensure manual OTEL setup works (#12214)
- fix(aws-serverless): Avoid minifying `Module._resolveFilename` in Lambda layer bundle (#12232)
- fix(aws-serverless): Ensure lambda layer uses default export from `ImportInTheMiddle` (#12233)
- fix(browser): Improve browser extension error message check (#12146)
- fix(browser): Remove optional chaining in INP code (#12196)
- fix(nextjs): Don't report React postpone errors (#12194)
- fix(nextjs): Use global scope for generic event filters (#12205)
- fix(node): Add origin to redis span (#12201)
- fix(node): Change import of `@prisma/instrumentation` to use default import (#12185)
- fix(node): Only import `inspector` asynchronously (#12231)
- fix(replay): Update matcher for hydration error detection to new React docs (#12209)
- ref(profiling-node): Add warning when using non-LTS node (#12211)

## 8.4.0

### Important Changes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { expect } from '@playwright/test';

import { sentryTest } from '../../utils/fixtures';
import { getFirstSentryEnvelopeRequest, properEnvelopeRequestParser } from '../../utils/helpers';
import { sentryTest } from '../../../utils/fixtures';
import {
getFirstSentryEnvelopeRequest,
properEnvelopeRequestParser,
shouldSkipMetricsTest,
} from '../../../utils/helpers';

sentryTest('collects metrics', async ({ getLocalTestUrl, page }) => {
if (shouldSkipMetricsTest()) {
sentryTest.skip();
}

const url = await getLocalTestUrl({ testDir: __dirname });

const statsdBuffer = await getFirstSentryEnvelopeRequest<Uint8Array>(page, url, properEnvelopeRequestParser);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;

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

// This should not fail
Sentry.metrics.increment('increment');
Sentry.metrics.distribution('distribution', 42);
Sentry.metrics.gauge('gauge', 5);
Sentry.metrics.set('set', 'nope');
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { expect } from '@playwright/test';

import { sentryTest } from '../../../utils/fixtures';
import { shouldSkipMetricsTest } from '../../../utils/helpers';

sentryTest('exports shim metrics integration for non-tracing bundles', async ({ getLocalTestPath, page }) => {
// Skip in tracing tests
if (!shouldSkipMetricsTest()) {
sentryTest.skip();
}

const consoleMessages: string[] = [];
page.on('console', msg => consoleMessages.push(msg.text()));

let requestCount = 0;
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
requestCount++;
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: 'test-id' }),
});
});

const url = await getLocalTestPath({ testDir: __dirname });

await page.goto(url);

expect(requestCount).toBe(0);
expect(consoleMessages).toEqual([
'You are using metrics even though this bundle does not include tracing.',
'You are using metrics even though this bundle does not include tracing.',
'You are using metrics even though this bundle does not include tracing.',
'You are using metrics even though this bundle does not include tracing.',
]);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const newTraceBtn = document.getElementById('newTrace');
newTraceBtn.addEventListener('click', async () => {
Sentry.startNewTrace(() => {
Sentry.startSpan({ op: 'ui.interaction.click', name: 'new-trace' }, async () => {
await fetch('http://example.com');
});
});
});

const oldTraceBtn = document.getElementById('oldTrace');
oldTraceBtn.addEventListener('click', async () => {
Sentry.startSpan({ op: 'ui.interaction.click', name: 'old-trace' }, async () => {
await fetch('http://example.com');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<button id="oldTrace">Old Trace</button>
<button id="newTrace">new Trace</button>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { expect } from '@playwright/test';
import { sentryTest } from '../../../../utils/fixtures';
import type { EventAndTraceHeader } from '../../../../utils/helpers';
import {
eventAndTraceHeaderRequestParser,
getFirstSentryEnvelopeRequest,
getMultipleSentryEnvelopeRequests,
shouldSkipTracingTest,
} from '../../../../utils/helpers';

sentryTest(
'creates a new trace if `startNewTrace` is called and leaves old trace valid outside the callback',
async ({ getLocalTestUrl, page }) => {
if (shouldSkipTracingTest()) {
sentryTest.skip();
}

const url = await getLocalTestUrl({ testDir: __dirname });

await page.route('http://example.com/**', route => {
return route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({}),
});
});

const [pageloadEvent, pageloadTraceHeaders] = await getFirstSentryEnvelopeRequest<EventAndTraceHeader>(
page,
url,
eventAndTraceHeaderRequestParser,
);

const pageloadTraceContext = pageloadEvent.contexts?.trace;

expect(pageloadEvent.type).toEqual('transaction');

expect(pageloadTraceContext).toMatchObject({
op: 'pageload',
trace_id: expect.stringMatching(/^[0-9a-f]{32}$/),
span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
});
expect(pageloadTraceContext).not.toHaveProperty('parent_span_id');

expect(pageloadTraceHeaders).toEqual({
environment: 'production',
public_key: 'public',
sample_rate: '1',
sampled: 'true',
trace_id: pageloadTraceContext?.trace_id,
});

const transactionPromises = getMultipleSentryEnvelopeRequests<EventAndTraceHeader>(
page,
2,
{ envelopeType: 'transaction' },
eventAndTraceHeaderRequestParser,
);

await page.locator('#newTrace').click();
await page.locator('#oldTrace').click();

const [txnEvent1, txnEvent2] = await transactionPromises;

const [newTraceTransactionEvent, newTraceTransactionTraceHeaders] =
txnEvent1[0].transaction === 'new-trace' ? txnEvent1 : txnEvent2;
const [oldTraceTransactionEvent, oldTraceTransactionTraceHeaders] =
txnEvent1[0].transaction === 'old-trace' ? txnEvent1 : txnEvent2;

const newTraceTransactionTraceContext = newTraceTransactionEvent.contexts?.trace;
expect(newTraceTransactionTraceContext).toMatchObject({
op: 'ui.interaction.click',
trace_id: expect.stringMatching(/^[0-9a-f]{32}$/),
span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
});

expect(newTraceTransactionTraceHeaders).toEqual({
environment: 'production',
public_key: 'public',
sample_rate: '1',
sampled: 'true',
trace_id: newTraceTransactionTraceContext?.trace_id,
transaction: 'new-trace',
});

const oldTraceTransactionEventTraceContext = oldTraceTransactionEvent.contexts?.trace;
expect(oldTraceTransactionEventTraceContext).toMatchObject({
op: 'ui.interaction.click',
trace_id: expect.stringMatching(/^[0-9a-f]{32}$/),
span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
});

expect(oldTraceTransactionTraceHeaders).toEqual({
environment: 'production',
public_key: 'public',
sample_rate: '1',
sampled: 'true',
trace_id: oldTraceTransactionTraceHeaders?.trace_id,
// transaction: 'old-trace', <-- this is not in the DSC because the DSC is continued from the pageload transaction
// which does not have a `transaction` field because its source is URL.
});

expect(oldTraceTransactionEventTraceContext?.trace_id).toEqual(pageloadTraceContext?.trace_id);
expect(newTraceTransactionTraceContext?.trace_id).not.toEqual(pageloadTraceContext?.trace_id);
},
);
14 changes: 13 additions & 1 deletion dev-packages/browser-integration-tests/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ export function shouldSkipTracingTest(): boolean {
}

/**
* We can only test replay tests in certain bundles/packages:
* We can only test feedback tests in certain bundles/packages:
* - NPM (ESM, CJS)
* - CDN bundles that contain the Replay integration
*
Expand All @@ -252,6 +252,18 @@ export function shouldSkipFeedbackTest(): boolean {
return bundle != null && !bundle.includes('feedback') && !bundle.includes('esm') && !bundle.includes('cjs');
}

/**
* We can only test metrics tests in certain bundles/packages:
* - NPM (ESM, CJS)
* - CDN bundles that include tracing
*
* @returns `true` if we should skip the metrics test
*/
export function shouldSkipMetricsTest(): boolean {
const bundle = process.env.PW_BUNDLE as string | undefined;
return bundle != null && !bundle.includes('tracing') && !bundle.includes('esm') && !bundle.includes('cjs');
}

/**
* Waits until a number of requests matching urlRgx at the given URL arrive.
* If the timout option is configured, this function will abort waiting, even if it hasn't reveived the configured
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as Sentry from '@sentry/nextjs';

export default async function Page({
searchParams,
}: {
searchParams: { id?: string };
}) {
try {
console.log(searchParams.id); // Accessing a field on searchParams will throw the PPR error
} catch (e) {
Sentry.captureException(e); // This error should not be reported
await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for any async event processors to run
await Sentry.flush();
throw e;
}

return <div>This server component will throw a PPR error that we do not want to catch.</div>;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
const { withSentryConfig } = require('@sentry/nextjs');

/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig = {
experimental: {
ppr: true,
},
};

module.exports = withSentryConfig(nextConfig, {
silent: true,
Expand Down
Loading

0 comments on commit 27a47f2

Please sign in to comment.