Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
305ef4e
wip
Lms24 Sep 26, 2025
b67207b
types, serialization, integration WIP
Lms24 Oct 1, 2025
4781e73
create span v2 envelope
Lms24 Oct 1, 2025
9d610cc
exports
Lms24 Oct 2, 2025
8306a6e
apply ignorespans, improve beforesendspan, handle segment span being …
Lms24 Oct 2, 2025
d17c896
apply common attributes
Lms24 Oct 3, 2025
77193a3
linter really doesn't like me and I can't blame him
Lms24 Oct 3, 2025
ee7844a
apply scope contexts, extras, request data attributes
Lms24 Oct 3, 2025
bb37494
cleanup
Lms24 Oct 14, 2025
46eef81
changelog entry
Lms24 Oct 14, 2025
a70a643
size-limit bumps
Lms24 Oct 14, 2025
eb86585
fix lint, circular deps, size limit
Lms24 Oct 14, 2025
c09298f
bump preview version
Lms24 Oct 15, 2025
aa0e013
s/makeV2Callback/withStreamSpan
Lms24 Oct 15, 2025
2aef6a3
add todos for event processors and integration hooks
Lms24 Oct 15, 2025
b7152da
changelog
Lms24 Oct 16, 2025
f153e0b
export withStreamSpan from browser
Lms24 Oct 16, 2025
ae77ca1
changelog
Lms24 Oct 16, 2025
80471da
fix some attribute mishaps
Lms24 Oct 31, 2025
e9000f5
remove is_remote, add is_segment
Lms24 Nov 10, 2025
8bbbf7c
add `sentry.segment.id` common span attribute
Lms24 Nov 10, 2025
8d3d624
rip span kind
Lms24 Nov 12, 2025
b5f262a
restart ci
Lms24 Nov 12, 2025
a6c4840
does this fix size limit?
Lms24 Nov 21, 2025
25b181a
size limit once more
Lms24 Nov 21, 2025
38eeb2f
s/user.username/user.name
Lms24 Nov 25, 2025
37f5821
one more limit bump
Lms24 Nov 25, 2025
b496cd0
rewrite to `captureSpan`
Lms24 Nov 28, 2025
77e7cfc
capturespan
Lms24 Nov 28, 2025
7691526
add integration test for pageload span
Lms24 Dec 1, 2025
919389f
more integration tests
Lms24 Dec 1, 2025
e671e6f
span links test
Lms24 Dec 1, 2025
0c782f2
set web vitals as attributes in span-first
Lms24 Dec 2, 2025
3294f62
rewrite httpContext integration to use processSpan client hook
Lms24 Dec 2, 2025
2757dd1
minor lint stuff
Lms24 Dec 4, 2025
6595430
initial StreamingSpanExporter implementation for otel
Lms24 Dec 4, 2025
a53ac2e
rewrite pipeline to just always use spanJSonV2 because thanks OTel
Lms24 Dec 5, 2025
1176731
wip
Lms24 Dec 10, 2025
41a890a
add exporter
Lms24 Dec 10, 2025
5f86c3f
more contexts
Lms24 Dec 10, 2025
2e2c871
add unit tests for captureSpan pipeline and utils
Lms24 Dec 11, 2025
52023cb
add another test for scope attribute precedence over contexts
Lms24 Dec 12, 2025
60e3751
Potential fix for code scanning alert no. 424: Missing regular expres…
Lms24 Dec 12, 2025
404a42d
fix lint errors
Lms24 Dec 12, 2025
fe258a8
skip integration tests for cdn bundles
Lms24 Dec 12, 2025
0a5f3ef
fix missing exports of `withStreamSpan`
Lms24 Dec 12, 2025
e707e46
apply request data to segment span
Lms24 Dec 15, 2025
fd987a5
register a bunch of known contexts
Lms24 Dec 15, 2025
a9e3f2c
use new attribute serialization for spanv2
Lms24 Dec 15, 2025
9df1029
remove unused code
Lms24 Dec 15, 2025
8722c64
flush buffer when `Sentry.flush()` is called
Lms24 Dec 16, 2025
03f717c
extract span buffer to class, add serverSpanStreamingIntegration, use…
Lms24 Dec 16, 2025
a9d664a
raise size limits
Lms24 Dec 17, 2025
6c4c7e9
save some bytes in httpContext integration when tree-shaking tracing
Lms24 Dec 17, 2025
c86b2c0
fix test flakiness
Lms24 Dec 18, 2025
3a22597
fix regex
Lms24 Dec 18, 2025
0239f16
set `sentry.span.source` attribute
Lms24 Jan 9, 2026
b788ec7
update with improved span serialization logic from scope attribute PRs
Lms24 Jan 9, 2026
abb6fd3
remove redundant attribute serilaization functions
Lms24 Jan 9, 2026
8f18a3c
spanStreamingIntegration everywhere
Lms24 Jan 9, 2026
e4a2807
use `SpanBuffer` in browser
Lms24 Jan 9, 2026
27b145d
fixups and failing node integration tests :)
Lms24 Jan 14, 2026
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
57 changes: 32 additions & 25 deletions .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ module.exports = [
path: 'packages/browser/build/npm/esm/prod/index.js',
import: createImport('init'),
gzip: true,
limit: '25.5 KB',
limit: '26KB',
},
{
name: '@sentry/browser - with treeshaking flags',
path: 'packages/browser/build/npm/esm/prod/index.js',
import: createImport('init'),
gzip: true,
limit: '24.1 KB',
limit: '25 KB',
modifyWebpackConfig: function (config) {
const webpack = require('webpack');

Expand All @@ -38,7 +38,7 @@ module.exports = [
path: 'packages/browser/build/npm/esm/prod/index.js',
import: createImport('init', 'browserTracingIntegration'),
gzip: true,
limit: '42 KB',
limit: '43 KB',
},
{
name: '@sentry/browser (incl. Tracing, Profiling)',
Expand All @@ -47,6 +47,13 @@ module.exports = [
gzip: true,
limit: '48 KB',
},
// {
// name: '@sentry/browser (incl. Tracing Span-First)',
// path: 'packages/browser/build/npm/esm/index.js',
// import: createImport('init', 'browserTracingIntegration', 'spanStreamingIntegration'),
// gzip: true,
// limit: '44 KB',
// },
{
name: '@sentry/browser (incl. Tracing, Replay)',
path: 'packages/browser/build/npm/esm/prod/index.js',
Expand Down Expand Up @@ -82,35 +89,35 @@ module.exports = [
path: 'packages/browser/build/npm/esm/prod/index.js',
import: createImport('init', 'browserTracingIntegration', 'replayIntegration', 'replayCanvasIntegration'),
gzip: true,
limit: '85.5 KB',
limit: '87 KB',
},
{
name: '@sentry/browser (incl. Tracing, Replay, Feedback)',
path: 'packages/browser/build/npm/esm/prod/index.js',
import: createImport('init', 'browserTracingIntegration', 'replayIntegration', 'feedbackIntegration'),
gzip: true,
limit: '98 KB',
limit: '99 KB',
},
{
name: '@sentry/browser (incl. Feedback)',
path: 'packages/browser/build/npm/esm/prod/index.js',
import: createImport('init', 'feedbackIntegration'),
gzip: true,
limit: '42 KB',
limit: '43 KB',
},
{
name: '@sentry/browser (incl. sendFeedback)',
path: 'packages/browser/build/npm/esm/prod/index.js',
import: createImport('init', 'sendFeedback'),
gzip: true,
limit: '30 KB',
limit: '31 KB',
},
{
name: '@sentry/browser (incl. FeedbackAsync)',
path: 'packages/browser/build/npm/esm/prod/index.js',
import: createImport('init', 'feedbackAsyncIntegration'),
gzip: true,
limit: '35 KB',
limit: '36 KB',
},
{
name: '@sentry/browser (incl. Metrics)',
Expand Down Expand Up @@ -140,51 +147,51 @@ module.exports = [
import: createImport('init', 'ErrorBoundary'),
ignore: ['react/jsx-runtime'],
gzip: true,
limit: '27 KB',
limit: '28 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: '44.5 KB',
limit: '46 KB',
},
// Vue SDK (ESM)
{
name: '@sentry/vue',
path: 'packages/vue/build/esm/index.js',
import: createImport('init'),
gzip: true,
limit: '30 KB',
limit: '31 KB',
},
{
name: '@sentry/vue (incl. Tracing)',
path: 'packages/vue/build/esm/index.js',
import: createImport('init', 'browserTracingIntegration'),
gzip: true,
limit: '44 KB',
limit: '45 KB',
},
// Svelte SDK (ESM)
{
name: '@sentry/svelte',
path: 'packages/svelte/build/esm/index.js',
import: createImport('init'),
gzip: true,
limit: '25.5 KB',
limit: '26 KB',
},
// Browser CDN bundles
{
name: 'CDN Bundle',
path: createCDNPath('bundle.min.js'),
gzip: true,
limit: '28 KB',
limit: '28.5 KB',
},
{
name: 'CDN Bundle (incl. Tracing)',
path: createCDNPath('bundle.tracing.min.js'),
gzip: true,
limit: '43 KB',
limit: '44 KB',
},
{
name: 'CDN Bundle (incl. Tracing, Logs, Metrics)',
Expand All @@ -196,7 +203,7 @@ module.exports = [
name: 'CDN Bundle (incl. Tracing, Replay)',
path: createCDNPath('bundle.tracing.replay.min.js'),
gzip: true,
limit: '80 KB',
limit: '81 KB',
},
{
name: 'CDN Bundle (incl. Tracing, Replay, Feedback)',
Expand All @@ -210,14 +217,14 @@ module.exports = [
path: createCDNPath('bundle.min.js'),
gzip: false,
brotli: false,
limit: '82 KB',
limit: '83 KB',
},
{
name: 'CDN Bundle (incl. Tracing) - uncompressed',
path: createCDNPath('bundle.tracing.min.js'),
gzip: false,
brotli: false,
limit: '127 KB',
limit: '129 KB',
},
{
name: 'CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed',
Expand All @@ -231,7 +238,7 @@ module.exports = [
path: createCDNPath('bundle.tracing.replay.min.js'),
gzip: false,
brotli: false,
limit: '245 KB',
limit: '247 KB',
},
{
name: 'CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed',
Expand All @@ -247,7 +254,7 @@ module.exports = [
import: createImport('init'),
ignore: ['next/router', 'next/constants'],
gzip: true,
limit: '47 KB',
limit: '48 KB',
},
// SvelteKit SDK (ESM)
{
Expand All @@ -256,7 +263,7 @@ module.exports = [
import: createImport('init'),
ignore: ['$app/stores'],
gzip: true,
limit: '43 KB',
limit: '44 KB',
},
// Node-Core SDK (ESM)
{
Expand All @@ -265,7 +272,7 @@ module.exports = [
import: createImport('init'),
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
gzip: true,
limit: '52 KB',
limit: '53 KB',
},
// Node SDK (ESM)
{
Expand All @@ -274,14 +281,14 @@ module.exports = [
import: createImport('init'),
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
gzip: true,
limit: '163 KB',
limit: '166 KB',
},
{
name: '@sentry/node - without tracing',
path: 'packages/node/build/esm/index.js',
import: createImport('initWithoutDefaultIntegrations', 'getDefaultIntegrationsWithoutPerformance'),
gzip: true,
limit: '95 KB',
limit: '97 KB',
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
modifyWebpackConfig: function (config) {
const webpack = require('webpack');
Expand All @@ -304,7 +311,7 @@ module.exports = [
import: createImport('init'),
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
gzip: true,
limit: '111 KB',
limit: '112 KB',
},
];

Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
},
"angular.enable-strict-mode-prompt": false
}
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,16 @@ Work in this release was contributed by @hanseo0507. Thank you for your contribu

Work in this release was contributed by @0xbad0c0d3. Thank you for your contribution!

## 10.21.0-alpha.1

This release is a preview release for sending spans in browser via spanV2 instead of transaction event envelopes. All of this is experimental and subject to change. Use at your own risk. [More Details.](https://github.com/getsentry/sentry-javascript/pull/17852)

- export withStreamSpan from `@sentry/browser`

## 10.21.0-alpha.0

This release is a preview release for sending spans in browser via spanV2 instead of transaction event envelopes. All of this is experimental and subject to change. Use at your own risk. [More Details.](https://github.com/getsentry/sentry-javascript/pull/17852)

## 10.20.0

### Important Changes
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;

Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
traceLifecycle: 'stream',
integrations: [Sentry.browserTracingIntegration(), Sentry.spanStreamingIntegration()],
tracePropagationTargets: ['http://sentry-test-site.example'],
tracesSampleRate: 1,
sendDefaultPii: true,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
document.getElementById('go-background').addEventListener('click', () => {
setTimeout(() => {
Object.defineProperty(document, 'hidden', { value: true, writable: true });
const ev = document.createEvent('Event');
ev.initEvent('visibilitychange');
document.dispatchEvent(ev);
}, 250);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<button id="go-background">New Tab</button>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { expect } from '@playwright/test';
import { sentryTest } from '../../../utils/fixtures';
import { shouldSkipTracingTest, testingCdnBundle } from '../../../utils/helpers';
import { getSpanOp, waitForV2Spans } from '../../../utils/spanFirstUtils';

sentryTest('ends pageload span when the page goes to background', async ({ getLocalTestUrl, page }) => {
// for now, spanStreamingIntegration is only exported in the NPM package, so we skip the test for bundles.
if (shouldSkipTracingTest() || testingCdnBundle()) {
sentryTest.skip();
}

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

const spanPromise = waitForV2Spans(page, spans => !!spans.find(span => getSpanOp(span) === 'pageload'));

await page.goto(url);
await page.locator('#go-background').click();

const pageloadSpan = (await spanPromise).find(span => getSpanOp(span) === 'pageload');

expect(pageloadSpan?.status).toBe('error'); // a cancelled span previously mapped to status error with message cancelled.
expect(pageloadSpan?.attributes?.['sentry.op']?.value).toBe('pageload');
expect(pageloadSpan?.attributes?.['sentry.cancellation_reason']?.value).toBe('document.hidden');
});
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',
traceLifecycle: 'stream',
integrations: [Sentry.browserTracingIntegration(), Sentry.spanStreamingIntegration()],
tracePropagationTargets: ['http://sentry-test-site.example'],
tracesSampleRate: 1,
sendDefaultPii: true,
debug: true,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { expect } from '@playwright/test';
import type { Event } from '@sentry/core';
import { sentryTest } from '../../../utils/fixtures';
import {
envelopeRequestParser,
runScriptInSandbox,
shouldSkipTracingTest,
testingCdnBundle,
waitForErrorRequest,
} from '../../../utils/helpers';
import { getSpanOp, waitForV2Spans } from '../../../utils/spanFirstUtils';

sentryTest(
'puts the pageload span name onto an error event caught during pageload',
async ({ getLocalTestUrl, page, browserName }) => {
// for now, spanStreamingIntegration is only exported in the NPM package, so we skip the test for bundles.
// This test fails on Webkit as errors thrown from `runScriptInSandbox` are Script Errors and skipped by Sentry
if (shouldSkipTracingTest() || testingCdnBundle() || browserName === 'webkit') {
sentryTest.skip();
}

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

const errorEventPromise = waitForErrorRequest(page);
const spanPromise = waitForV2Spans(page, spans => !!spans.find(span => getSpanOp(span) === 'pageload'));

await page.goto(url);

await runScriptInSandbox(page, {
content: `
throw new Error('Error during pageload');
`,
});

const errorEvent = envelopeRequestParser<Event>(await errorEventPromise);
const pageloadSpan = (await spanPromise).find(span => getSpanOp(span) === 'pageload');

expect(pageloadSpan?.attributes?.['sentry.op']?.value).toEqual('pageload');
expect(errorEvent.exception?.values?.[0]).toBeDefined();

expect(pageloadSpan?.name).toEqual('/index.html');

expect(pageloadSpan?.status).toBe('error');
expect(pageloadSpan?.attributes?.['sentry.idle_span_finish_reason']?.value).toBe('idleTimeout');

expect(errorEvent.transaction).toEqual(pageloadSpan?.name);
},
);
12 changes: 12 additions & 0 deletions dev-packages/browser-integration-tests/suites/span-first/init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as Sentry from '@sentry/browser';

window.Sentry = Sentry;

Sentry.init({
dsn: 'https://public@dsn.ingest.sentry.io/1337',
traceLifecycle: 'stream',
integrations: [Sentry.browserTracingIntegration(), Sentry.spanStreamingIntegration()],
tracePropagationTargets: ['http://sentry-test-site.example'],
tracesSampleRate: 1,
sendDefaultPii: true,
});
Loading
Loading