Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
a218427
ref(eslint-plugin-sdk): Improve `no-unsafe-random-apis` rule (#25123)
Lms24 Oct 7, 2026
fa38591
Merge pull request #25128 from getsentry/master
github-actions[bot] Oct 7, 2026
5c75501
test(node): Add streamed span collection helpers (#25131)
nicohrubec Oct 7, 2026
ce18d90
test(node): Port OpenAI integration tests to span streaming (#25081)
nicohrubec Oct 7, 2026
96b56c5
test(node): Port Bedrock tests to span streaming (#25086)
nicohrubec Oct 7, 2026
9400a38
test(node): Port Anthropic integration tests to span streaming (#25082)
nicohrubec Oct 7, 2026
edb8113
test(node): Port LangGraph tests to span streaming (#25085)
nicohrubec Oct 7, 2026
145e48b
test(node): Port Google GenAI tests to span streaming (#25083)
nicohrubec Oct 7, 2026
02892e6
test(node): Port LangChain tests to span streaming (#25084)
nicohrubec Oct 7, 2026
d3e5b7b
test(node): Port Mastra tests to span streaming (#25087)
nicohrubec Oct 7, 2026
f8abf00
fix(server-utils): Record LangGraph span I/O for non-MessagesAnnotati…
zkasuran Oct 7, 2026
49dee26
test(cloudflare): Widen the wrangler readiness retry window in integr…
mydea Oct 7, 2026
fcb6cdf
chore: Add external contributor to CHANGELOG.md (#25136)
javascript-sdk-gitflow[bot] Oct 7, 2026
0201779
fix(core): Correct sleep clock drift on telemetry timestamps (#23054)
Lms24 Oct 7, 2026
164794b
fix(core): Compute span end time from `performance.now()` duration (#…
Lms24 Oct 7, 2026
d5ae601
fix(effect): Convert Effect span times to the Sentry clock (#24972)
Lms24 Oct 7, 2026
ca05d2d
test(cloudflare): Port the remaining static suites to span streaming …
JPeer264 Oct 7, 2026
3d01e5a
fix(effect): Detect HTTP spans named after the request method (#25159)
JPeer264 Oct 8, 2026
d283c16
fix(core): Exclude attachments from internal exception events (#25160)
msonnb Oct 8, 2026
559d8bd
test(e2e): Wait for the soft navigation entry before hiding the page …
Lms24 Oct 8, 2026
f1cdd11
fix(node): Register Vercel keep-alive listeners once
chargome Oct 8, 2026
edd839a
fix(replay): Place CLS and INP web vitals at the right time (#24990)
Lms24 Oct 8, 2026
5b98d75
fix(browser): Check for clock drift on page lifecycle events (#25091)
Lms24 Oct 8, 2026
af84269
fix(sveltekit): Upload source maps with SvelteKit 3 (#25139)
chargome Oct 8, 2026
cd0f3dc
fix(deps): Bump @graphql-tools/utils to 12.0.3 (#25162)
chargome Oct 8, 2026
2882a29
feat(nextjs): Add `@sentry/nextjs/cloudflare` (#24998)
JPeer264 Oct 8, 2026
ba3da33
test(nextjs): Run nextjs-16 on Bun, Deno and Cloudflare (#24999)
JPeer264 Oct 8, 2026
4f9a027
feat(cloudflare): Wrap vinext Worker entries with `@sentry/nextjs/clo…
JPeer264 Oct 8, 2026
b1638a0
feat(deps): Bump next from 16.2.11 to 16.3.8 in /dev-packages/e2e-tes…
dependabot[bot] Oct 8, 2026
b6616ce
test(node): Port AMQP integration tests to span streaming (#25158)
nicohrubec Oct 8, 2026
8acc0c8
test(node): Port pool and DataLoader integration tests to span stream…
nicohrubec Oct 8, 2026
cf24f0c
test(node): Port Knex integration tests to span streaming (#25154)
nicohrubec Oct 8, 2026
b4bd17e
chore(nitro): Remove stale bundler-plugin-core rollup external (#25149)
Lms24 Oct 8, 2026
de43b56
chore(deps-dev): Bump next from 15.5.24 to 15.5.27 (#25171)
dependabot[bot] Oct 8, 2026
540c798
feat(server-utils): Record LangChain TypeSafeClassifier runs as gen_a…
andreiborza Oct 8, 2026
1fee6d1
test(node): Cover Jev calls inside createAgent and LangGraph (#25132)
andreiborza Oct 8, 2026
dffd6b1
test(node): Port Vercel AI v5-v7 tests to span streaming (#25090)
nicohrubec Oct 8, 2026
0db1949
test(node): Port Tedious integration tests to span streaming (#25155)
nicohrubec Oct 8, 2026
4971a72
test(node): Port MySQL integration tests to span streaming (#25148)
nicohrubec Oct 8, 2026
04f7cb9
feat(server-utils): Add instrumentation for pi-durable (#24993)
JPeer264 Oct 8, 2026
b70f6bb
test(e2e): Add a node-pi-durable end-to-end application (#24994)
JPeer264 Oct 8, 2026
966e1ff
feat(cloudflare): Skip spans for the pi_ tables of PiHarness (#25028)
JPeer264 Oct 8, 2026
221dd86
test(e2e): Add a cloudflare-pi-durable end-to-end application (#25022)
JPeer264 Oct 8, 2026
5bb9a68
feat(server-utils): Map Mastra classifier evaluations to gen_ai.evalu…
andreiborza Oct 8, 2026
2fdcb23
test(e2e): Add Mastra Jev classifier test to node-mastra (#25115)
andreiborza Oct 8, 2026
e99e6e1
feat(remix): Propagate the server trace to Remix 3 page loads (#25145)
chargome Oct 8, 2026
53ae996
meta(changelog): Update changelog for 11.6.0
JPeer264 Oct 8, 2026
3605c50
chore(size-limit): Bump @sentry/node size limits
JPeer264 Oct 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
25 changes: 23 additions & 2 deletions .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ module.exports = [
import: createImport('init'),
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
gzip: true,
limit: '150 KB',
limit: '151 KB',
disablePlugins: ['@size-limit/esbuild'],
},
{
Expand Down Expand Up @@ -465,7 +465,7 @@ module.exports = [
path: 'packages/node/build/esm/index.js',
import: createImport('init'),
gzip: true,
limit: '128 KB',
limit: '130 KB',
disablePlugins: ['@size-limit/esbuild'],
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
modifyWebpackConfig: function (config) {
Expand Down Expand Up @@ -533,6 +533,27 @@ module.exports = [
return config;
},
},
// Next.js on Cloudflare Workers (ESM) - minified to match `wrangler deploy --dry-run --minify` output. An import of
// `@sentry/node` in this entry more than doubles its size.
{
name: '@sentry/nextjs/cloudflare (withSentry) - minified',
path: 'packages/nextjs/build/esm/cloudflare/index.js',
import: createImport('withSentry'),
ignore: [...builtinModules, ...nodePrefixedBuiltinModules],
gzip: false,
brotli: false,
limit: '223 KiB',
disablePlugins: ['@size-limit/webpack'],
webpack: false,
modifyEsbuildConfig: function (config) {
config.keepNames = true;
// Match wrangler's build settings
config.conditions = ['workerd', 'worker', 'browser'];
config.platform = 'browser';
config.format = 'esm';
return config;
},
},
];

function createImport(...args) {
Expand Down
81 changes: 81 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,87 @@

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

## 11.6.0

### Important Changes

- **feat(nextjs): Add `@sentry/nextjs/cloudflare` ([#24998](https://github.com/getsentry/sentry-javascript/pull/24998))**

The new `@sentry/nextjs/cloudflare` entry point exports `withSentry` for the Worker entry of a Next.js app on Cloudflare Workers, for example `.open-next/worker.js` of OpenNext. It is `withSentry` of `@sentry/cloudflare` with the Next.js server handling added, so a Next.js app on Workers gets the same spans as on Node.js.

```ts
import * as Sentry from '@sentry/nextjs/cloudflare';
import handler from './.open-next/worker.js';

export default Sentry.withSentry(
env => ({
dsn: env.SENTRY_DSN,
tracesSampleRate: 1.0,
}),
handler,
);
```

- **feat(server-utils): Add instrumentation for pi-durable ([#24993](https://github.com/getsentry/sentry-javascript/pull/24993))**

The new `piDurableIntegration` traces agents built with [pi-durable](https://github.com/earendil-works/pi/tree/main/packages/durable): each run, with its model requests and tool calls.

- **fix(core): Correct sleep clock drift on telemetry timestamps ([#23054](https://github.com/getsentry/sentry-javascript/pull/23054))**

When a device sleeps, the `performance.now()` clock of the browser stops. Before this change, timestamps of spans and other telemetry recorded after the sleep could be too early. The SDK now detects this drift and corrects its time origin, also for spans created from performance entries. Span end times are now computed from the `performance.now()` duration since the span start, like in OpenTelemetry ([#24903](https://github.com/getsentry/sentry-javascript/pull/24903)).

### Other Changes

- feat(cloudflare): Skip spans for the pi_ tables of PiHarness ([#25028](https://github.com/getsentry/sentry-javascript/pull/25028))
- feat(remix): Propagate the server trace to Remix 3 page loads ([#25145](https://github.com/getsentry/sentry-javascript/pull/25145))
- feat(server-utils): Map Mastra classifier evaluations to gen_ai.evaluate spans ([#25044](https://github.com/getsentry/sentry-javascript/pull/25044))
- feat(server-utils): Record LangChain TypeSafeClassifier runs as gen_ai.evaluate spans ([#25120](https://github.com/getsentry/sentry-javascript/pull/25120))
- fix(browser): Check for clock drift on page lifecycle events ([#25091](https://github.com/getsentry/sentry-javascript/pull/25091))
- fix(core): Exclude attachments from internal exception events ([#25160](https://github.com/getsentry/sentry-javascript/pull/25160))
- fix(effect): Convert Effect span times to the Sentry clock ([#24972](https://github.com/getsentry/sentry-javascript/pull/24972))
- fix(effect): Detect HTTP spans named after the request method ([#25159](https://github.com/getsentry/sentry-javascript/pull/25159))
- fix(node): Register Vercel keep-alive listeners once ([#25146](https://github.com/getsentry/sentry-javascript/pull/25146))
- fix(replay): Place CLS and INP web vitals at the right time ([#24990](https://github.com/getsentry/sentry-javascript/pull/24990))
- fix(server-utils): Record LangGraph span I/O for non-MessagesAnnotation state ([#23315](https://github.com/getsentry/sentry-javascript/pull/23315))
- fix(sveltekit): Upload source maps with SvelteKit 3 ([#25139](https://github.com/getsentry/sentry-javascript/pull/25139))

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

- chore: Add external contributor to CHANGELOG.md ([#25136](https://github.com/getsentry/sentry-javascript/pull/25136))
- chore(deps-dev): Bump next from 15.5.24 to 15.5.27 ([#25171](https://github.com/getsentry/sentry-javascript/pull/25171))
- chore(nitro): Remove stale bundler-plugin-core rollup external ([#25149](https://github.com/getsentry/sentry-javascript/pull/25149))
- feat(cloudflare): Wrap vinext Worker entries with `@sentry/nextjs/cloudflare` ([#25000](https://github.com/getsentry/sentry-javascript/pull/25000))
- feat(deps): Bump next from 16.2.11 to 16.3.8 in /dev-packages/e2e-tests/test-applications/nextjs-sourcemaps ([#25170](https://github.com/getsentry/sentry-javascript/pull/25170))
- fix(deps): Bump @graphql-tools/utils to 12.0.3 ([#25162](https://github.com/getsentry/sentry-javascript/pull/25162))
- ref(eslint-plugin-sdk): Improve `no-unsafe-random-apis` rule ([#25123](https://github.com/getsentry/sentry-javascript/pull/25123))
- test(cloudflare): Port the remaining static suites to span streaming ([#25112](https://github.com/getsentry/sentry-javascript/pull/25112))
- test(cloudflare): Widen the wrangler readiness retry window in integration tests ([#24925](https://github.com/getsentry/sentry-javascript/pull/24925))
- test(e2e): Add a cloudflare-pi-durable end-to-end application ([#25022](https://github.com/getsentry/sentry-javascript/pull/25022))
- test(e2e): Add a node-pi-durable end-to-end application ([#24994](https://github.com/getsentry/sentry-javascript/pull/24994))
- test(e2e): Add Mastra Jev classifier test to node-mastra ([#25115](https://github.com/getsentry/sentry-javascript/pull/25115))
- test(e2e): Wait for the soft navigation entry before hiding the page ([#25127](https://github.com/getsentry/sentry-javascript/pull/25127))
- test(nextjs): Run nextjs-16 on Bun, Deno and Cloudflare ([#24999](https://github.com/getsentry/sentry-javascript/pull/24999))
- test(node): Add streamed span collection helpers ([#25131](https://github.com/getsentry/sentry-javascript/pull/25131))
- test(node): Cover Jev calls inside createAgent and LangGraph ([#25132](https://github.com/getsentry/sentry-javascript/pull/25132))
- test(node): Port AMQP integration tests to span streaming ([#25158](https://github.com/getsentry/sentry-javascript/pull/25158))
- test(node): Port Anthropic integration tests to span streaming ([#25082](https://github.com/getsentry/sentry-javascript/pull/25082))
- test(node): Port Bedrock tests to span streaming ([#25086](https://github.com/getsentry/sentry-javascript/pull/25086))
- test(node): Port Google GenAI tests to span streaming ([#25083](https://github.com/getsentry/sentry-javascript/pull/25083))
- test(node): Port Knex integration tests to span streaming ([#25154](https://github.com/getsentry/sentry-javascript/pull/25154))
- test(node): Port LangChain tests to span streaming ([#25084](https://github.com/getsentry/sentry-javascript/pull/25084))
- test(node): Port LangGraph tests to span streaming ([#25085](https://github.com/getsentry/sentry-javascript/pull/25085))
- test(node): Port Mastra tests to span streaming ([#25087](https://github.com/getsentry/sentry-javascript/pull/25087))
- test(node): Port MySQL integration tests to span streaming ([#25148](https://github.com/getsentry/sentry-javascript/pull/25148))
- test(node): Port OpenAI integration tests to span streaming ([#25081](https://github.com/getsentry/sentry-javascript/pull/25081))
- test(node): Port pool and DataLoader integration tests to span streaming ([#25156](https://github.com/getsentry/sentry-javascript/pull/25156))
- test(node): Port Tedious integration tests to span streaming ([#25155](https://github.com/getsentry/sentry-javascript/pull/25155))
- test(node): Port Vercel AI v5-v7 tests to span streaming ([#25090](https://github.com/getsentry/sentry-javascript/pull/25090))

</details>

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

## 11.5.0

### Important Changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export const NO_AUTO_INSTRUMENTATION = [
'suites/tracing/knex/**',
'suites/tracing/koa/test.ts',
'suites/tracing/langchain/**',
'suites/tracing/langgraph/test.ts',
'suites/tracing/langgraph/**',
'suites/tracing/lru-memoizer/test.ts',
'suites/tracing/mastra/test.ts',
'suites/tracing/mcp-handler-exact-once/test.ts',
Expand All @@ -124,6 +124,7 @@ export const NO_AUTO_INSTRUMENTATION = [
'suites/tracing/openai/v6/test.ts',
'suites/tracing/openai/v7/test.ts',
'suites/tracing/orchestrion-lazy-registration/test.ts',
'suites/tracing/pi-durable/test.ts',
'suites/tracing/postgres-streamed/test.ts',
'suites/tracing/postgres/test.ts',
'suites/tracing/postgresjs-streamed/test.ts',
Expand Down Expand Up @@ -244,6 +245,7 @@ const BUN_BUILD_NOT_TRIAGED = [
'suites/tracing/google-genai-v2/test.ts',
'suites/tracing/google-genai/test.ts',
'suites/tracing/langchain/v1/test.ts',
'suites/tracing/langgraph/v1/test.ts',
'suites/tracing/mastra/test.ts',
'suites/tracing/mcp-handler-exact-once/test.ts',
'suites/tracing/mcp-server-streamed/test.ts',
Expand Down
9 changes: 7 additions & 2 deletions dev-packages/cloudflare-integration-tests/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ type RetryOptions = { maxRetries?: number; retryDelayMs?: number };
async function fetchWithRetry(
url: string,
init: RequestInit,
{ maxRetries = 25, retryDelayMs = 200 }: RetryOptions = {},
{ maxRetries = 75, retryDelayMs = 200 }: RetryOptions = {},
): Promise<Response> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
Expand Down Expand Up @@ -569,7 +569,12 @@ export function createRunner(...paths: string[]) {

if (!res.ok) {
if (!expectError) {
reject(new Error(`Expected request to "${path}" to succeed, but got a ${res.status} response`));
const responseBody = await res.text().catch(() => '');
reject(
new Error(
`Expected request to "${path}" to succeed, but got a ${res.status} response: ${responseBody.slice(0, 500)}`,
),
);
}

return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ import { defineCloudflareOptions } from '@sentry/cloudflare';

export default defineCloudflareOptions((env: { SENTRY_DSN: string }) => ({
dsn: env.SENTRY_DSN,
traceLifecycle: 'static',
tracesSampleRate: 1.0,
}));
Original file line number Diff line number Diff line change
@@ -1,49 +1,35 @@
import type { TransactionEvent } from '@sentry/core';
import { expect, it } from 'vitest';
import { createRunner } from '../../../../runner';
import { getSpanOp } from '../../../../spanUtils';

it('propagates the worker trace into each of two overlapping Durable Object RPC calls', async ({ signal }) => {
const doTraces: Record<string, TransactionEvent['contexts']> = {};
let workerTraceId: string | undefined;
let workerSpanId: string | undefined;

const runner = createRunner(__dirname)
.unordered()
.expect(envelope => {
const transactionEvent = envelope[1]?.[0]?.[1] as TransactionEvent;
expect(transactionEvent.transaction).toBe('work');
expect(transactionEvent.contexts?.trace?.op).toBe('rpc');
expect(transactionEvent.contexts?.trace?.data?.['test.label']).toBe('a');
doTraces.a = transactionEvent.contexts;
})
.expect(envelope => {
const transactionEvent = envelope[1]?.[0]?.[1] as TransactionEvent;
expect(transactionEvent.transaction).toBe('work');
expect(transactionEvent.contexts?.trace?.op).toBe('rpc');
expect(transactionEvent.contexts?.trace?.data?.['test.label']).toBe('b');
doTraces.b = transactionEvent.contexts;
})
.expect(envelope => {
const transactionEvent = envelope[1]?.[0]?.[1] as TransactionEvent;
expect(transactionEvent.transaction).toBe('GET /overlapping');
expect(transactionEvent.contexts?.trace?.op).toBe('http.server');
workerTraceId = transactionEvent.contexts?.trace?.trace_id;
workerSpanId = transactionEvent.contexts?.trace?.span_id;
})
.start(signal);
const runner = createRunner(__dirname).start(signal);

// The worker and the Durable Object stream from separate isolates, and both RPC segments come from
// the same Durable Object, so they can share an envelope.
const spansPromise = runner.collectStreamedSpans(
spansOfTrace => spansOfTrace.filter(span => span.is_segment).length === 3,
);

const response = await runner.makeRequest<string>('get', '/overlapping');
expect(response).toBe('a,b');

await runner.completed();
const segmentSpans = (await spansPromise).filter(span => span.is_segment);
const workerSpan = segmentSpans.find(span => getSpanOp(span) === 'http.server');
const rpcSpanA = segmentSpans.find(span => span.attributes['test.label']?.value === 'a');
const rpcSpanB = segmentSpans.find(span => span.attributes['test.label']?.value === 'b');

// `/overlapping` is a raw URL, so the streamed segment name keeps the method only.
expect(workerSpan?.name).toBe('GET');
expect(workerSpan?.attributes['url.path']).toEqual({ type: 'string', value: '/overlapping' });

expect(workerTraceId).toMatch(/^[\da-f]{32}$/);
expect(workerSpanId).toMatch(/^[\da-f]{16}$/);
expect(rpcSpanA?.name).toBe('work');
expect(getSpanOp(rpcSpanA!)).toBe('rpc');
expect(rpcSpanA?.parent_span_id).toBe(workerSpan?.span_id);

expect(doTraces.a?.trace?.trace_id).toBe(workerTraceId);
expect(doTraces.a?.trace?.parent_span_id).toBe(workerSpanId);
expect(doTraces.b?.trace?.trace_id).toBe(workerTraceId);
expect(doTraces.b?.trace?.parent_span_id).toBe(workerSpanId);
expect(rpcSpanB?.name).toBe('work');
expect(getSpanOp(rpcSpanB!)).toBe('rpc');
expect(rpcSpanB?.parent_span_id).toBe(workerSpan?.span_id);

expect(doTraces.a?.trace?.span_id).not.toBe(doTraces.b?.trace?.span_id);
expect(rpcSpanA?.span_id).not.toBe(rpcSpanB?.span_id);
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ class GreeterImpl extends WorkerEntrypoint<Env> {
// Manually instrumented here, in a module separate from the worker entry, which
// only imports and re-exports the wrapped class.
export const GreeterEntrypoint = Sentry.withSentry(
(env: Env) => ({ dsn: env.SENTRY_DSN, traceLifecycle: 'static', tracesSampleRate: 1.0 }),
(env: Env) => ({ dsn: env.SENTRY_DSN, tracesSampleRate: 1.0 }),
GreeterImpl,
);
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ import { defineCloudflareOptions } from '@sentry/cloudflare';

export default defineCloudflareOptions((env: { SENTRY_DSN: string }) => ({
dsn: env.SENTRY_DSN,
traceLifecycle: 'static',
tracesSampleRate: 1.0,
}));
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
import type { TransactionEvent } from '@sentry/core';
import { expect, it } from 'vitest';
import { createRunner } from '../../../runner';
import { getSpanOp } from '../../../spanUtils';

// `GreeterEntrypoint` is hand-wrapped in `./greeter` and only re-exported by
// the entry, so the transform's emitted `_INTERNAL_wrapUnlessInstrumented`
// guard must hand the manual wrap back instead of nesting a second wrapper.
// Nested entrypoint wrappers each instrument `fetch`, which shows up as extra
// spans on the entrypoint transaction, the strict shape below catches that.
// A nested wrapper throws inside the entrypoint and fails the request. The
// child-less assertion below catches a nested wrapper that runs without an
// error but instruments `fetch` a second time.
it('does not double-instrument an imported, already-wrapped WorkerEntrypoint', async ({ signal }) => {
const runner = createRunner(__dirname)
.unordered()
.expect(envelope => {
const transactionEvent = envelope[1]?.[0]?.[1] as TransactionEvent;
// The entrypoint's own transaction, child-less when wrapped exactly once.
expect(transactionEvent.transaction).toBe('GET /greet');
expect(transactionEvent.contexts?.trace?.op).toBe('http.server');
expect(transactionEvent.spans ?? []).toHaveLength(0);
})
.expect(envelope => {
const transactionEvent = envelope[1]?.[0]?.[1] as TransactionEvent;
// The auto-wrapped default export's transaction.
expect(transactionEvent.transaction).toBe('GET /call-entrypoint');
expect(transactionEvent.contexts?.trace?.op).toBe('http.server');
})
.start(signal);
const runner = createRunner(__dirname).start(signal);

// The default handler and the entrypoint stream from separate isolates, so the two segment spans
// of the trace arrive in separate envelopes.
const spansPromise = runner.collectStreamedSpans(
spansOfTrace => spansOfTrace.filter(span => span.is_segment).length === 2,
);

await runner.makeRequest('get', '/call-entrypoint');
await runner.completed();

const spans = await spansPromise;
// Both routes are raw URLs, so the streamed segment names keep the method only and the route is
// read from `url.path`.
const workerSpan = spans.find(span => span.is_segment && span.attributes['url.path']?.value === '/call-entrypoint');
const entrypointSpan = spans.find(span => span.is_segment && span.attributes['url.path']?.value === '/greet');

// The auto-wrapped default export's segment span.
expect(workerSpan?.name).toBe('GET');
expect(getSpanOp(workerSpan!)).toBe('http.server');

expect(entrypointSpan?.name).toBe('GET');
expect(getSpanOp(entrypointSpan!)).toBe('http.server');
expect(entrypointSpan?.parent_span_id).toBe(workerSpan?.span_id);
// The entrypoint's spans stay buffered until its invocation flushes, so a child span would arrive
// in the same envelope as the entrypoint's segment span.
expect(spans.filter(span => span.parent_span_id === entrypointSpan?.span_id)).toEqual([]);
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);

// Issued by the test after `/trigger` returned, its transaction is the
// Issued by the test after `/trigger` returned, its segment span is the
// sentinel proving every earlier envelope (including a duplicate step
// transaction from an accidental double wrap) has been delivered.
// span from an accidental double wrap) has been delivered.
if (url.pathname === '/sentinel') {
return new Response('ok');
}
Expand All @@ -26,7 +26,7 @@ export default {
const instance = await env.MY_WORKFLOW.create();
// Respond only once the workflow finished, so every step envelope (including
// a duplicate from an accidental double wrap) is sent before this request's
// own transaction completes the test's expectations.
// own segment span completes the test's expectations.
for (let i = 0; i < 20; i++) {
try {
const s = await instance.status();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ import { defineCloudflareOptions } from '@sentry/cloudflare';

export default defineCloudflareOptions((env: { SENTRY_DSN: string }) => ({
dsn: env.SENTRY_DSN,
traceLifecycle: 'static',
tracesSampleRate: 1.0,
}));
Loading
Loading