From a0a6f6ceb5e0211aa1d9f6bdb2633c04106290cb Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Thu, 18 Dec 2025 17:28:15 +0100 Subject: [PATCH] feat(cloudflare): Support `propagateTraceparen --- .../cloudflare-integration-tests/runner.ts | 7 +++ .../suites/tracing/headers/index.ts | 19 ++++++ .../suites/tracing/headers/test.ts | 59 +++++++++++++++++++ .../suites/tracing/headers/wrangler.jsonc | 6 ++ .../tracing/dsc-txn-name-update/test.ts | 2 +- .../requests/fetch-breadcrumbs/test.ts | 2 +- .../fetch-no-tracing-no-spans/test.ts | 2 +- .../tracing/requests/fetch-no-tracing/test.ts | 2 +- .../fetch-sampled-no-active-span/test.ts | 2 +- .../tracing/requests/fetch-unsampled/test.ts | 2 +- .../tracing/requests/http-breadcrumbs/test.ts | 2 +- .../requests/http-no-tracing-no-spans/test.ts | 2 +- .../tracing/requests/http-no-tracing/test.ts | 2 +- .../http-sampled-no-active-span/test.ts | 2 +- .../tracing/requests/http-sampled/test.ts | 2 +- .../tracing/requests/http-unsampled/test.ts | 2 +- .../tracing/requests/traceparent/test.ts | 2 +- .../tracing/tracePropagationTargets/test.ts | 2 +- .../utils/server.ts | 46 --------------- .../tracing/dsc-txn-name-update/test.ts | 2 +- .../http-client-spans/fetch-basic/test.ts | 2 +- .../fetch-forward-request-hook/test.ts | 2 +- .../fetch-strip-query/test.ts | 2 +- .../http-client-spans/http-basic/test.ts | 2 +- .../http-strip-query/test.ts | 2 +- .../suites/tracing/httpIntegration/test.ts | 2 +- .../requests/fetch-breadcrumbs/test.ts | 2 +- .../fetch-no-tracing-no-spans/test.ts | 2 +- .../tracing/requests/fetch-no-tracing/test.ts | 2 +- .../fetch-sampled-no-active-span/test.ts | 2 +- .../tracing/requests/fetch-unsampled/test.ts | 2 +- .../tracing/requests/http-breadcrumbs/test.ts | 2 +- .../requests/http-no-tracing-no-spans/test.ts | 2 +- .../tracing/requests/http-no-tracing/test.ts | 2 +- .../http-sampled-no-active-span/test.ts | 2 +- .../tracing/requests/http-sampled/test.ts | 2 +- .../tracing/requests/http-unsampled/test.ts | 2 +- .../tracing/requests/traceparent/test.ts | 2 +- .../tracing/tracePropagationTargets/test.ts | 2 +- .../node-integration-tests/utils/server.ts | 48 --------------- dev-packages/test-utils/src/index.ts | 2 +- dev-packages/test-utils/src/server.ts | 46 +++++++++++++++ packages/cloudflare/src/integrations/fetch.ts | 2 + 43 files changed, 174 insertions(+), 129 deletions(-) create mode 100644 dev-packages/cloudflare-integration-tests/suites/tracing/headers/index.ts create mode 100644 dev-packages/cloudflare-integration-tests/suites/tracing/headers/test.ts create mode 100644 dev-packages/cloudflare-integration-tests/suites/tracing/headers/wrangler.jsonc delete mode 100644 dev-packages/node-integration-tests/utils/server.ts diff --git a/dev-packages/cloudflare-integration-tests/runner.ts b/dev-packages/cloudflare-integration-tests/runner.ts index b945bee2eeea..513309c0db97 100644 --- a/dev-packages/cloudflare-integration-tests/runner.ts +++ b/dev-packages/cloudflare-integration-tests/runner.ts @@ -64,8 +64,13 @@ export function createRunner(...paths: string[]) { const expectedEnvelopes: Expected[] = []; // By default, we ignore session & sessions const ignored: Set = new Set(['session', 'sessions', 'client_report']); + let serverUrl: string | undefined; return { + withServerUrl: function (url: string) { + serverUrl = url; + return this; + }, expect: function (expected: Expected) { expectedEnvelopes.push(expected); return this; @@ -154,6 +159,8 @@ export function createRunner(...paths: string[]) { 'false', '--var', `SENTRY_DSN:http://public@localhost:${mockServerPort}/1337`, + '--var', + `SERVER_URL:${serverUrl}`, ], { stdio, signal }, ); diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/headers/index.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/headers/index.ts new file mode 100644 index 000000000000..973f54053571 --- /dev/null +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/headers/index.ts @@ -0,0 +1,19 @@ +import * as Sentry from '@sentry/cloudflare'; + +interface Env { + SENTRY_DSN: string; + SERVER_URL: string; +} + +export default Sentry.withSentry( + (env: Env) => ({ + dsn: env.SENTRY_DSN, + propagateTraceparent: true, + }), + { + async fetch(_request, env, _ctx) { + await fetch(env.SERVER_URL); + throw new Error('Test error to capture trace headers'); + }, + }, +); diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/headers/test.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/headers/test.ts new file mode 100644 index 000000000000..d92fde438eb8 --- /dev/null +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/headers/test.ts @@ -0,0 +1,59 @@ +import { createTestServer } from '@sentry-internal/test-utils'; +import { expect, it } from 'vitest'; +import { eventEnvelope } from '../../../expect'; +import { createRunner } from '../../../runner'; + +it('Tracing headers', async ({ signal }) => { + expect.assertions(5); + + const [SERVER_URL, closeTestServer] = await createTestServer() + .get('/', headers => { + expect(headers['baggage']).toEqual(expect.any(String)); + expect(headers['sentry-trace']).toEqual(expect.stringMatching(/^([a-f\d]{32})-([a-f\d]{16})-0$/)); + expect(headers['sentry-trace']).not.toEqual('00000000000000000000000000000000-0000000000000000-0'); + expect(headers['traceparent']).toEqual(expect.stringMatching(/^00-([a-f\d]{32})-([a-f\d]{16})-00$/)); + }) + .start(); + + const runner = createRunner(__dirname) + .withServerUrl(SERVER_URL) + .expect( + eventEnvelope({ + level: 'error', + exception: { + values: [ + { + type: 'Error', + value: 'Test error to capture trace headers', + stacktrace: { + frames: expect.any(Array), + }, + mechanism: { type: 'auto.http.cloudflare', handled: false }, + }, + ], + }, + breadcrumbs: [ + { + category: 'fetch', + data: { + method: 'GET', + status_code: 200, + url: expect.stringContaining('http://localhost:'), + }, + timestamp: expect.any(Number), + type: 'http', + }, + ], + request: { + headers: expect.any(Object), + method: 'GET', + url: expect.any(String), + }, + }), + ) + .start(signal); + + await runner.makeRequest('get', '/'); + await runner.completed(); + closeTestServer(); +}); diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/headers/wrangler.jsonc b/dev-packages/cloudflare-integration-tests/suites/tracing/headers/wrangler.jsonc new file mode 100644 index 000000000000..24fb2861023d --- /dev/null +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/headers/wrangler.jsonc @@ -0,0 +1,6 @@ +{ + "name": "worker-name", + "compatibility_date": "2025-06-17", + "main": "index.ts", + "compatibility_flags": ["nodejs_compat"] +} diff --git a/dev-packages/node-core-integration-tests/suites/tracing/dsc-txn-name-update/test.ts b/dev-packages/node-core-integration-tests/suites/tracing/dsc-txn-name-update/test.ts index b9b2327497f5..4592221c286b 100644 --- a/dev-packages/node-core-integration-tests/suites/tracing/dsc-txn-name-update/test.ts +++ b/dev-packages/node-core-integration-tests/suites/tracing/dsc-txn-name-update/test.ts @@ -1,7 +1,7 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { expect, test } from 'vitest'; import { conditionalTest } from '../../../utils'; import { createRunner } from '../../../utils/runner'; -import { createTestServer } from '../../../utils/server'; // This test requires Node.js 22+ because it depends on the 'http.client.request.created' // diagnostic channel for baggage header propagation, which only exists since Node 22.12.0+ and 23.2.0+ diff --git a/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-breadcrumbs/test.ts b/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-breadcrumbs/test.ts index 0d1d33bb5fc9..531d66b3f2e6 100644 --- a/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-breadcrumbs/test.ts +++ b/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-breadcrumbs/test.ts @@ -1,7 +1,7 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { conditionalTest } from '../../../../utils'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing fetch', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-no-tracing-no-spans/test.ts b/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-no-tracing-no-spans/test.ts index 61dfe4c4ba88..7781f01f4605 100644 --- a/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-no-tracing-no-spans/test.ts +++ b/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-no-tracing-no-spans/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing fetch', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-no-tracing/test.ts b/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-no-tracing/test.ts index 046763a0b55a..2f0bfd410663 100644 --- a/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-no-tracing/test.ts +++ b/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-no-tracing/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing fetch', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/test.ts b/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/test.ts index acc1d6c89a25..702a2febd61d 100644 --- a/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/test.ts +++ b/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing fetch', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-unsampled/test.ts b/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-unsampled/test.ts index 4507a360006c..8458d25728d0 100644 --- a/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-unsampled/test.ts +++ b/dev-packages/node-core-integration-tests/suites/tracing/requests/fetch-unsampled/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing fetch', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-core-integration-tests/suites/tracing/requests/http-breadcrumbs/test.ts b/dev-packages/node-core-integration-tests/suites/tracing/requests/http-breadcrumbs/test.ts index 318d4628453b..96892353d2dd 100644 --- a/dev-packages/node-core-integration-tests/suites/tracing/requests/http-breadcrumbs/test.ts +++ b/dev-packages/node-core-integration-tests/suites/tracing/requests/http-breadcrumbs/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing http', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-core-integration-tests/suites/tracing/requests/http-no-tracing-no-spans/test.ts b/dev-packages/node-core-integration-tests/suites/tracing/requests/http-no-tracing-no-spans/test.ts index 1cad4abf9a99..17393f21a8a4 100644 --- a/dev-packages/node-core-integration-tests/suites/tracing/requests/http-no-tracing-no-spans/test.ts +++ b/dev-packages/node-core-integration-tests/suites/tracing/requests/http-no-tracing-no-spans/test.ts @@ -1,7 +1,7 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { conditionalTest } from '../../../../utils'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing http requests with tracing & spans disabled', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-core-integration-tests/suites/tracing/requests/http-no-tracing/test.ts b/dev-packages/node-core-integration-tests/suites/tracing/requests/http-no-tracing/test.ts index 55882d18830a..7d863d27ce6e 100644 --- a/dev-packages/node-core-integration-tests/suites/tracing/requests/http-no-tracing/test.ts +++ b/dev-packages/node-core-integration-tests/suites/tracing/requests/http-no-tracing/test.ts @@ -1,7 +1,7 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { conditionalTest } from '../../../../utils'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing http', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-core-integration-tests/suites/tracing/requests/http-sampled-no-active-span/test.ts b/dev-packages/node-core-integration-tests/suites/tracing/requests/http-sampled-no-active-span/test.ts index 8cf07571fe24..e2af51920b0b 100644 --- a/dev-packages/node-core-integration-tests/suites/tracing/requests/http-sampled-no-active-span/test.ts +++ b/dev-packages/node-core-integration-tests/suites/tracing/requests/http-sampled-no-active-span/test.ts @@ -1,7 +1,7 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { conditionalTest } from '../../../../utils'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing http', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-core-integration-tests/suites/tracing/requests/http-sampled/test.ts b/dev-packages/node-core-integration-tests/suites/tracing/requests/http-sampled/test.ts index a1ac7ca292e4..4aecd4c8dfa1 100644 --- a/dev-packages/node-core-integration-tests/suites/tracing/requests/http-sampled/test.ts +++ b/dev-packages/node-core-integration-tests/suites/tracing/requests/http-sampled/test.ts @@ -1,7 +1,7 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { conditionalTest } from '../../../../utils'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing http', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-core-integration-tests/suites/tracing/requests/http-unsampled/test.ts b/dev-packages/node-core-integration-tests/suites/tracing/requests/http-unsampled/test.ts index 63ae25f32a0c..bf6f3fb6e316 100644 --- a/dev-packages/node-core-integration-tests/suites/tracing/requests/http-unsampled/test.ts +++ b/dev-packages/node-core-integration-tests/suites/tracing/requests/http-unsampled/test.ts @@ -1,7 +1,7 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { conditionalTest } from '../../../../utils'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing http', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-core-integration-tests/suites/tracing/requests/traceparent/test.ts b/dev-packages/node-core-integration-tests/suites/tracing/requests/traceparent/test.ts index 2cdb4cfd1aa7..517ea314dfc5 100644 --- a/dev-packages/node-core-integration-tests/suites/tracing/requests/traceparent/test.ts +++ b/dev-packages/node-core-integration-tests/suites/tracing/requests/traceparent/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing traceparent', () => { createEsmAndCjsTests(__dirname, 'scenario-fetch.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-core-integration-tests/suites/tracing/tracePropagationTargets/test.ts b/dev-packages/node-core-integration-tests/suites/tracing/tracePropagationTargets/test.ts index a136eb770a8d..b97f64adace5 100644 --- a/dev-packages/node-core-integration-tests/suites/tracing/tracePropagationTargets/test.ts +++ b/dev-packages/node-core-integration-tests/suites/tracing/tracePropagationTargets/test.ts @@ -1,7 +1,7 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { expect, test } from 'vitest'; import { conditionalTest } from '../../../utils'; import { createRunner } from '../../../utils/runner'; -import { createTestServer } from '../../../utils/server'; // This test requires Node.js 22+ because it depends on the 'http.client.request.created' // diagnostic channel for baggage header propagation, which only exists since Node 22.12.0+ and 23.2.0+ diff --git a/dev-packages/node-core-integration-tests/utils/server.ts b/dev-packages/node-core-integration-tests/utils/server.ts index 92e0477c845c..b8941b4b0c32 100644 --- a/dev-packages/node-core-integration-tests/utils/server.ts +++ b/dev-packages/node-core-integration-tests/utils/server.ts @@ -37,49 +37,3 @@ export function createBasicSentryServer(onEnvelope: (env: Envelope) => void): Pr }); }); } - -type HeaderAssertCallback = (headers: Record) => void; - -/** Creates a test server that can be used to check headers */ -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type -export function createTestServer() { - const gets: Array<[string, HeaderAssertCallback, number]> = []; - let error: unknown | undefined; - - return { - get: function (path: string, callback: HeaderAssertCallback, result = 200) { - gets.push([path, callback, result]); - return this; - }, - start: async (): Promise<[string, () => void]> => { - const app = express(); - - for (const [path, callback, result] of gets) { - app.get(path, (req, res) => { - try { - callback(req.headers); - } catch (e) { - error = e; - } - - res.status(result).send(); - }); - } - - return new Promise(resolve => { - const server = app.listen(0, () => { - const address = server.address() as AddressInfo; - resolve([ - `http://localhost:${address.port}`, - () => { - server.close(); - if (error) { - throw error; - } - }, - ]); - }); - }); - }, - }; -} diff --git a/dev-packages/node-integration-tests/suites/tracing/dsc-txn-name-update/test.ts b/dev-packages/node-integration-tests/suites/tracing/dsc-txn-name-update/test.ts index aa74bea7d79e..ddac08fe1b21 100644 --- a/dev-packages/node-integration-tests/suites/tracing/dsc-txn-name-update/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/dsc-txn-name-update/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { expect, test } from 'vitest'; import { createRunner } from '../../../utils/runner'; -import { createTestServer } from '../../../utils/server'; test('adds current transaction name to baggage when the txn name is high-quality', async () => { expect.assertions(5); diff --git a/dev-packages/node-integration-tests/suites/tracing/http-client-spans/fetch-basic/test.ts b/dev-packages/node-integration-tests/suites/tracing/http-client-spans/fetch-basic/test.ts index 1b599def6be6..1cc06ba6f21e 100644 --- a/dev-packages/node-integration-tests/suites/tracing/http-client-spans/fetch-basic/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/http-client-spans/fetch-basic/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { expect, test } from 'vitest'; import { createRunner } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; test('captures spans for outgoing fetch requests', async () => { expect.assertions(3); diff --git a/dev-packages/node-integration-tests/suites/tracing/http-client-spans/fetch-forward-request-hook/test.ts b/dev-packages/node-integration-tests/suites/tracing/http-client-spans/fetch-forward-request-hook/test.ts index 8d0a35a43d05..6092e212df08 100644 --- a/dev-packages/node-integration-tests/suites/tracing/http-client-spans/fetch-forward-request-hook/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/http-client-spans/fetch-forward-request-hook/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { expect, test } from 'vitest'; import { createRunner } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; test('adds requestHook and responseHook attributes to spans of outgoing fetch requests', async () => { expect.assertions(3); diff --git a/dev-packages/node-integration-tests/suites/tracing/http-client-spans/fetch-strip-query/test.ts b/dev-packages/node-integration-tests/suites/tracing/http-client-spans/fetch-strip-query/test.ts index 580a63a52e90..8eea877dc72e 100644 --- a/dev-packages/node-integration-tests/suites/tracing/http-client-spans/fetch-strip-query/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/http-client-spans/fetch-strip-query/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { expect, test } from 'vitest'; import { createRunner } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; test('strips and handles query params in spans of outgoing fetch requests', async () => { expect.assertions(4); diff --git a/dev-packages/node-integration-tests/suites/tracing/http-client-spans/http-basic/test.ts b/dev-packages/node-integration-tests/suites/tracing/http-client-spans/http-basic/test.ts index bb21f7def8f0..0549d7e914c0 100644 --- a/dev-packages/node-integration-tests/suites/tracing/http-client-spans/http-basic/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/http-client-spans/http-basic/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { expect, test } from 'vitest'; import { createRunner } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; test('captures spans for outgoing http requests', async () => { expect.assertions(3); diff --git a/dev-packages/node-integration-tests/suites/tracing/http-client-spans/http-strip-query/test.ts b/dev-packages/node-integration-tests/suites/tracing/http-client-spans/http-strip-query/test.ts index edfac9fe2081..94ccd6c9702a 100644 --- a/dev-packages/node-integration-tests/suites/tracing/http-client-spans/http-strip-query/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/http-client-spans/http-strip-query/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { expect, test } from 'vitest'; import { createRunner } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; test('strips and handles query params in spans of outgoing http requests', async () => { expect.assertions(4); diff --git a/dev-packages/node-integration-tests/suites/tracing/httpIntegration/test.ts b/dev-packages/node-integration-tests/suites/tracing/httpIntegration/test.ts index 15c354e45533..ac0ac3780a38 100644 --- a/dev-packages/node-integration-tests/suites/tracing/httpIntegration/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/httpIntegration/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { afterAll, describe, expect, test } from 'vitest'; import { cleanupChildProcesses, createEsmAndCjsTests, createRunner } from '../../../utils/runner'; -import { createTestServer } from '../../../utils/server'; function getCommonHttpRequestHeaders(): Record { return { diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-breadcrumbs/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-breadcrumbs/test.ts index d3315ae86ece..2691d10294a5 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-breadcrumbs/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-breadcrumbs/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing fetch', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-no-tracing-no-spans/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-no-tracing-no-spans/test.ts index 61dfe4c4ba88..7781f01f4605 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-no-tracing-no-spans/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-no-tracing-no-spans/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing fetch', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-no-tracing/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-no-tracing/test.ts index 046763a0b55a..2f0bfd410663 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-no-tracing/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-no-tracing/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing fetch', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/test.ts index acc1d6c89a25..702a2febd61d 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-sampled-no-active-span/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing fetch', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-unsampled/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-unsampled/test.ts index 4507a360006c..8458d25728d0 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/fetch-unsampled/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/fetch-unsampled/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing fetch', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/http-breadcrumbs/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/http-breadcrumbs/test.ts index 318d4628453b..96892353d2dd 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/http-breadcrumbs/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/http-breadcrumbs/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing http', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/http-no-tracing-no-spans/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/http-no-tracing-no-spans/test.ts index 1cad4abf9a99..17393f21a8a4 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/http-no-tracing-no-spans/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/http-no-tracing-no-spans/test.ts @@ -1,7 +1,7 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { conditionalTest } from '../../../../utils'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing http requests with tracing & spans disabled', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/http-no-tracing/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/http-no-tracing/test.ts index d0b13513d1de..4f6593f82e34 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/http-no-tracing/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/http-no-tracing/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing http', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/http-sampled-no-active-span/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/http-sampled-no-active-span/test.ts index 932f379ec23e..b00148c26142 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/http-sampled-no-active-span/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/http-sampled-no-active-span/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing http', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/http-sampled/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/http-sampled/test.ts index 9a7b13a34332..ebd6198bfd4e 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/http-sampled/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/http-sampled/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing http', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/http-unsampled/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/http-unsampled/test.ts index 28fb877d0425..1b40af0b6ec3 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/http-unsampled/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/http-unsampled/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing http', () => { createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-integration-tests/suites/tracing/requests/traceparent/test.ts b/dev-packages/node-integration-tests/suites/tracing/requests/traceparent/test.ts index 2cdb4cfd1aa7..517ea314dfc5 100644 --- a/dev-packages/node-integration-tests/suites/tracing/requests/traceparent/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/requests/traceparent/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { describe, expect } from 'vitest'; import { createEsmAndCjsTests } from '../../../../utils/runner'; -import { createTestServer } from '../../../../utils/server'; describe('outgoing traceparent', () => { createEsmAndCjsTests(__dirname, 'scenario-fetch.mjs', 'instrument.mjs', (createRunner, test) => { diff --git a/dev-packages/node-integration-tests/suites/tracing/tracePropagationTargets/test.ts b/dev-packages/node-integration-tests/suites/tracing/tracePropagationTargets/test.ts index 9fb39a1ec8f2..dc5105c9d1bb 100644 --- a/dev-packages/node-integration-tests/suites/tracing/tracePropagationTargets/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/tracePropagationTargets/test.ts @@ -1,6 +1,6 @@ +import { createTestServer } from '@sentry-internal/test-utils'; import { expect, test } from 'vitest'; import { createRunner } from '../../../utils/runner'; -import { createTestServer } from '../../../utils/server'; test('HttpIntegration should instrument correct requests when tracePropagationTargets option is provided', async () => { expect.assertions(11); diff --git a/dev-packages/node-integration-tests/utils/server.ts b/dev-packages/node-integration-tests/utils/server.ts deleted file mode 100644 index a1ba3f522fb1..000000000000 --- a/dev-packages/node-integration-tests/utils/server.ts +++ /dev/null @@ -1,48 +0,0 @@ -import express from 'express'; -import type { AddressInfo } from 'net'; - -type HeaderAssertCallback = (headers: Record) => void; - -/** Creates a test server that can be used to check headers */ -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type -export function createTestServer() { - const gets: Array<[string, HeaderAssertCallback, number]> = []; - let error: unknown | undefined; - - return { - get: function (path: string, callback: HeaderAssertCallback, result = 200) { - gets.push([path, callback, result]); - return this; - }, - start: async (): Promise<[string, () => void]> => { - const app = express(); - - for (const [path, callback, result] of gets) { - app.get(path, (req, res) => { - try { - callback(req.headers); - } catch (e) { - error = e; - } - - res.status(result).send(); - }); - } - - return new Promise(resolve => { - const server = app.listen(0, () => { - const address = server.address() as AddressInfo; - resolve([ - `http://localhost:${address.port}`, - () => { - server.close(); - if (error) { - throw error; - } - }, - ]); - }); - }); - }, - }; -} diff --git a/dev-packages/test-utils/src/index.ts b/dev-packages/test-utils/src/index.ts index e9ae76f592ed..b03c13ecfa74 100644 --- a/dev-packages/test-utils/src/index.ts +++ b/dev-packages/test-utils/src/index.ts @@ -10,4 +10,4 @@ export { } from './event-proxy-server'; export { getPlaywrightConfig } from './playwright-config'; -export { createBasicSentryServer } from './server'; +export { createBasicSentryServer, createTestServer } from './server'; diff --git a/dev-packages/test-utils/src/server.ts b/dev-packages/test-utils/src/server.ts index b8941b4b0c32..92e0477c845c 100644 --- a/dev-packages/test-utils/src/server.ts +++ b/dev-packages/test-utils/src/server.ts @@ -37,3 +37,49 @@ export function createBasicSentryServer(onEnvelope: (env: Envelope) => void): Pr }); }); } + +type HeaderAssertCallback = (headers: Record) => void; + +/** Creates a test server that can be used to check headers */ +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +export function createTestServer() { + const gets: Array<[string, HeaderAssertCallback, number]> = []; + let error: unknown | undefined; + + return { + get: function (path: string, callback: HeaderAssertCallback, result = 200) { + gets.push([path, callback, result]); + return this; + }, + start: async (): Promise<[string, () => void]> => { + const app = express(); + + for (const [path, callback, result] of gets) { + app.get(path, (req, res) => { + try { + callback(req.headers); + } catch (e) { + error = e; + } + + res.status(result).send(); + }); + } + + return new Promise(resolve => { + const server = app.listen(0, () => { + const address = server.address() as AddressInfo; + resolve([ + `http://localhost:${address.port}`, + () => { + server.close(); + if (error) { + throw error; + } + }, + ]); + }); + }); + }, + }; +} diff --git a/packages/cloudflare/src/integrations/fetch.ts b/packages/cloudflare/src/integrations/fetch.ts index 66c9f559f29c..8dfff417ff27 100644 --- a/packages/cloudflare/src/integrations/fetch.ts +++ b/packages/cloudflare/src/integrations/fetch.ts @@ -90,6 +90,7 @@ const _fetchIntegration = ((options: Partial = {}) => { setupOnce() { addFetchInstrumentationHandler(handlerData => { const client = getClient(); + const { propagateTraceparent } = client?.getOptions() || {}; if (!client || !HAS_CLIENT_MAP.get(client)) { return; } @@ -100,6 +101,7 @@ const _fetchIntegration = ((options: Partial = {}) => { instrumentFetchRequest(handlerData, _shouldCreateSpan, _shouldAttachTraceData, spans, { spanOrigin: 'auto.http.fetch', + propagateTraceparent, }); if (breadcrumbs) {