Skip to content

Commit

Permalink
Merge pull request #13988 from getsentry/prerelease/8.35.0-beta.0
Browse files Browse the repository at this point in the history
meta: Prepare prelease of 8.35.0-beta.0
  • Loading branch information
billyvg authored Oct 15, 2024
2 parents 5a5523e + 97aff96 commit 4c741ea
Show file tree
Hide file tree
Showing 78 changed files with 1,985 additions and 476 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/external-contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
&& github.event.pull_request.author_association != 'COLLABORATOR'
&& github.event.pull_request.author_association != 'MEMBER'
&& github.event.pull_request.author_association != 'OWNER'
&& endsWith(github.actor, '[bot]') == false
&& endsWith(github.event.pull_request.user.login, '[bot]') == false
steps:
- uses: actions/checkout@v4
- name: Set up Node
Expand Down
2 changes: 1 addition & 1 deletion .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ module.exports = [
path: 'packages/browser/build/npm/esm/index.js',
import: createImport('init', 'browserTracingIntegration', 'replayIntegration', 'feedbackIntegration'),
gzip: true,
limit: '91 KB',
limit: '95 KB',
},
{
name: '@sentry/browser (incl. Tracing, Replay, Feedback, metrics)',
Expand Down
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,46 @@

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

## 8.35.0-beta.0

### Important Changes

- **feat(core): Make stream instrumentation opt-in
([#13951](https://github.com/getsentry/sentry-javascript/pull/13951))**

This change adds a new option `trackFetchStreamPerformance` to the browser tracing integration. Only when set to `true`,
Sentry will instrument streams via fetch.

Work in this release was contributed by @ZakrepaShe and @zhiyan114. Thank you for your contributions!

### Other Changes

- chore(node): Bump `@opentelemetry/instrumentation-express` to `0.43.0`
([#13948](https://github.com/getsentry/sentry-javascript/pull/13948))
- ci: Ensure we check correctly for bot users ([#13955](https://github.com/getsentry/sentry-javascript/pull/13955))
- dev(e2e): Fix nestjs version constraint ([#13964](https://github.com/getsentry/sentry-javascript/pull/13964))
- feat(node): Expose `suppressTracing` API ([#13875](https://github.com/getsentry/sentry-javascript/pull/13875))
- feat(node): Implement Sentry-specific http instrumentation
([#13763](https://github.com/getsentry/sentry-javascript/pull/13763))
- feat(nuxt): Add Rollup plugin to wrap server entry with `import()`
([#13945](https://github.com/getsentry/sentry-javascript/pull/13945))
- feat(replay): Do not log "timeout while trying to read resp body" as exception
([#13965](https://github.com/getsentry/sentry-javascript/pull/13965))
- feat(vue): Add Pinia plugin ([#13841](https://github.com/getsentry/sentry-javascript/pull/13841))
- fix: Ensure type for `init` is correct in meta frameworks
([#13938](https://github.com/getsentry/sentry-javascript/pull/13938))
- fix(module): keep version for node ESM package ([#13922](https://github.com/getsentry/sentry-javascript/pull/13922))
- fix(replay): Fix onError sampling when loading an expired buffered session
([#13962](https://github.com/getsentry/sentry-javascript/pull/13962))
- ref: Add external contributor to CHANGELOG.md ([#13956](https://github.com/getsentry/sentry-javascript/pull/13956))
- ref: Add external contributor to CHANGELOG.md ([#13959](https://github.com/getsentry/sentry-javascript/pull/13959))
- test(browser): Add test for current DSC transaction name updating behavior
([#13953](https://github.com/getsentry/sentry-javascript/pull/13953))
- test(loader): Update Loader Script & test error in `sentryOnLoad`
([#13952](https://github.com/getsentry/sentry-javascript/pull/13952))
- test(node): Add tests for current DSC transaction name updating behavior
([#13961](https://github.com/getsentry/sentry-javascript/pull/13961))

## 8.34.0

### Important Changes
Expand Down
2 changes: 1 addition & 1 deletion dev-packages/browser-integration-tests/fixtures/loader.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// we define sentryOnLoad in template
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Sentry.captureException('Test exception');
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script>
window.sentryOnLoad = function () {
Sentry.init({
tracesSampleRate: 0.123,
});

throw new Error('sentryOnLoad error');
};
</script>
</head>
<body></body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { expect } from '@playwright/test';

import { sentryTest } from '../../../../utils/fixtures';
import { envelopeRequestParser, waitForErrorRequestOnUrl } from '../../../../utils/helpers';

sentryTest(
'sentryOnLoad callback is called before Sentry.onLoad() and handles errors in handler',
async ({ getLocalTestUrl, page }) => {
const errors: string[] = [];

page.on('console', msg => {
if (msg.type() === 'error') {
errors.push(msg.text());
}
});

const url = await getLocalTestUrl({ testDir: __dirname });
const req = await waitForErrorRequestOnUrl(page, url);

const eventData = envelopeRequestParser(req);

expect(eventData.message).toBe('Test exception');

expect(await page.evaluate('Sentry.getClient().getOptions().tracesSampleRate')).toEqual(0.123);

expect(errors).toEqual([
'Error while calling `sentryOnLoad` handler:',
expect.stringContaining('Error: sentryOnLoad error'),
]);
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;

Sentry.init({
dsn: 'https://[email protected]/1337',
integrations: [Sentry.browserTracingIntegration({ instrumentNavigation: false, instrumentPageLoad: false })],
tracesSampleRate: 1,
tracePropagationTargets: ['example.com'],
release: '1.1.1',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const btnStartSpan = document.getElementById('btnStartSpan');
const btnUpdateName = document.getElementById('btnUpdateName');
const btnMakeRequest = document.getElementById('btnMakeRequest');
const btnCaptureError = document.getElementById('btnCaptureError');
const btnEndSpan = document.getElementById('btnEndSpan');

btnStartSpan.addEventListener('click', () => {
Sentry.startSpanManual(
{ name: 'test-root-span', attributes: { [Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url' } },
async span => {
window.__traceId = span.spanContext().traceId;
await new Promise(resolve => {
btnEndSpan.addEventListener('click', resolve);
});
span.end();
},
);
});

let updateCnt = 0;
btnUpdateName.addEventListener('click', () => {
const span = Sentry.getActiveSpan();
const rootSpan = Sentry.getRootSpan(span);
rootSpan.updateName(`updated-root-span-${++updateCnt}`);
rootSpan.setAttribute(Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'route');
});

btnMakeRequest.addEventListener('click', () => {
fetch('https://example.com/api');
});

btnCaptureError.addEventListener('click', () => {
Sentry.captureException(new Error('test-error'));
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<button id="btnStartSpan">Start Span</button>
<button id="btnUpdateName">Update Name</button>
<button id="btnMakeRequest">Make Request</button>
<button id="btnCaptureError">Capture Error</button>
<button id="btnEndSpan">End Span</button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import { expect } from '@playwright/test';
import type { Page } from '@playwright/test';
import type { DynamicSamplingContext } from '@sentry/types';
import { sentryTest } from '../../../utils/fixtures';
import type { EventAndTraceHeader } from '../../../utils/helpers';
import {
eventAndTraceHeaderRequestParser,
getMultipleSentryEnvelopeRequests,
shouldSkipTracingTest,
} from '../../../utils/helpers';

sentryTest('updates the DSC when the txn name is updated and high-quality', async ({ getLocalTestUrl, page }) => {
if (shouldSkipTracingTest()) {
sentryTest.skip();
}

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

await page.goto(url);

/*
Test Steps:
1. Start new span with LQ txn name (source: url)
2. Make request and check that baggage has no transaction name
3. Capture error and check that envelope trace header has no transaction name
4. Update span name and source to HQ (source: route)
5. Make request and check that baggage has HQ txn name
6. Capture error and check that envelope trace header has HQ txn name
7. Update span name again with HQ name (source: route)
8. Make request and check that baggage has updated HQ txn name
9. Capture error and check that envelope trace header has updated HQ txn name
10. End span and check that envelope trace header has updated HQ txn name
11. Make another request and check that there's no span information in baggage
12. Capture an error and check that envelope trace header has no span information
*/

// 1
await page.locator('#btnStartSpan').click();
const traceId = await page.evaluate(() => {
return (window as any).__traceId;
});

expect(traceId).toMatch(/^[0-9a-f]{32}$/);

// 2
const baggageItems = await makeRequestAndGetBaggageItems(page);
expect(baggageItems).toEqual([
'sentry-environment=production',
'sentry-public_key=public',
'sentry-release=1.1.1',
'sentry-sample_rate=1',
'sentry-sampled=true',
`sentry-trace_id=${traceId}`,
]);

// 3
const errorEnvelopeTraceHeader = await captureErrorAndGetEnvelopeTraceHeader(page);
expect(errorEnvelopeTraceHeader).toEqual({
environment: 'production',
public_key: 'public',
release: '1.1.1',
sample_rate: '1',
sampled: 'true',
trace_id: traceId,
});

// 4
await page.locator('#btnUpdateName').click();

// 5
const baggageItemsAfterUpdate = await makeRequestAndGetBaggageItems(page);
expect(baggageItemsAfterUpdate).toEqual([
'sentry-environment=production',
'sentry-public_key=public',
'sentry-release=1.1.1',
'sentry-sample_rate=1',
'sentry-sampled=true',
`sentry-trace_id=${traceId}`,
'sentry-transaction=updated-root-span-1',
]);

// 6
const errorEnvelopeTraceHeaderAfterUpdate = await captureErrorAndGetEnvelopeTraceHeader(page);
expect(errorEnvelopeTraceHeaderAfterUpdate).toEqual({
environment: 'production',
public_key: 'public',
release: '1.1.1',
sample_rate: '1',
sampled: 'true',
trace_id: traceId,
transaction: 'updated-root-span-1',
});

// 7
await page.locator('#btnUpdateName').click();

// 8
const baggageItemsAfterSecondUpdate = await makeRequestAndGetBaggageItems(page);
expect(baggageItemsAfterSecondUpdate).toEqual([
'sentry-environment=production',
'sentry-public_key=public',
'sentry-release=1.1.1',
'sentry-sample_rate=1',
'sentry-sampled=true',
`sentry-trace_id=${traceId}`,
'sentry-transaction=updated-root-span-2',
]);

// 9
const errorEnvelopeTraceHeaderAfterSecondUpdate = await captureErrorAndGetEnvelopeTraceHeader(page);
expect(errorEnvelopeTraceHeaderAfterSecondUpdate).toEqual({
environment: 'production',
public_key: 'public',
release: '1.1.1',
sample_rate: '1',
sampled: 'true',
trace_id: traceId,
transaction: 'updated-root-span-2',
});

// 10
const txnEventPromise = getMultipleSentryEnvelopeRequests<EventAndTraceHeader>(
page,
1,
{ envelopeType: 'transaction' },
eventAndTraceHeaderRequestParser,
);

await page.locator('#btnEndSpan').click();

const [txnEvent, txnEnvelopeTraceHeader] = (await txnEventPromise)[0];
expect(txnEnvelopeTraceHeader).toEqual({
environment: 'production',
public_key: 'public',
release: '1.1.1',
sample_rate: '1',
sampled: 'true',
trace_id: traceId,
transaction: 'updated-root-span-2',
});

expect(txnEvent.transaction).toEqual('updated-root-span-2');

// 11
const baggageItemsAfterEnd = await makeRequestAndGetBaggageItems(page);
expect(baggageItemsAfterEnd).toEqual([
'sentry-environment=production',
'sentry-public_key=public',
'sentry-release=1.1.1',
`sentry-trace_id=${traceId}`,
]);

// 12
const errorEnvelopeTraceHeaderAfterEnd = await captureErrorAndGetEnvelopeTraceHeader(page);
expect(errorEnvelopeTraceHeaderAfterEnd).toEqual({
environment: 'production',
public_key: 'public',
release: '1.1.1',
trace_id: traceId,
});
});

async function makeRequestAndGetBaggageItems(page: Page): Promise<string[]> {
const requestPromise = page.waitForRequest('https://example.com/*');
await page.locator('#btnMakeRequest').click();
const request = await requestPromise;

const baggage = await request.headerValue('baggage');

return baggage?.split(',').sort() ?? [];
}

async function captureErrorAndGetEnvelopeTraceHeader(page: Page): Promise<DynamicSamplingContext | undefined> {
const errorEventPromise = getMultipleSentryEnvelopeRequests<EventAndTraceHeader>(
page,
1,
{ envelopeType: 'event' },
eventAndTraceHeaderRequestParser,
);

await page.locator('#btnCaptureError').click();

const [, errorEnvelopeTraceHeader] = (await errorEventPromise)[0];
return errorEnvelopeTraceHeader;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const errorBtn = document.getElementById('errorBtn');
errorBtn.addEventListener('click', () => {
throw new Error(`Sentry Test Error ${Math.random()}`);
});

const fetchBtn = document.getElementById('fetchBtn');
fetchBtn.addEventListener('click', async () => {
await fetch('http://example.com');
});

const xhrBtn = document.getElementById('xhrBtn');
xhrBtn.addEventListener('click', () => {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com');
xhr.send();
});
Loading

0 comments on commit 4c741ea

Please sign in to comment.