Skip to content

Commit 8acba7f

Browse files
authored
feat(node): Support propagateTraceparent
2 parents 6f0b8b4 + 87d04c4 commit 8acba7f

File tree

17 files changed

+263
-29
lines changed

17 files changed

+263
-29
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import * as Sentry from '@sentry/node-core';
2+
import { loggingTransport } from '@sentry-internal/node-integration-tests';
3+
import { setupOtel } from '../../../../utils/setupOtel.js';
4+
5+
const client = Sentry.init({
6+
dsn: 'https://[email protected]/1337',
7+
release: '1.0',
8+
tracesSampleRate: 1,
9+
propagateTraceparent: true,
10+
transport: loggingTransport,
11+
});
12+
13+
setupOtel(client);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import * as Sentry from '@sentry/node-core';
2+
3+
async function run() {
4+
// Wrap in span that is not sampled
5+
await Sentry.startSpan({ name: 'outer' }, async () => {
6+
await fetch(`${process.env.SERVER_URL}/api/v1`).then(res => res.text());
7+
});
8+
}
9+
10+
run();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import * as Sentry from '@sentry/node-core';
2+
import * as http from 'http';
3+
4+
function makeHttpRequest(url) {
5+
return new Promise(resolve => {
6+
http
7+
.request(url, httpRes => {
8+
httpRes.on('data', () => {
9+
// we don't care about data
10+
});
11+
httpRes.on('end', () => {
12+
resolve();
13+
});
14+
})
15+
.end();
16+
});
17+
}
18+
19+
await Sentry.startSpan({ name: 'outer' }, async () => {
20+
await makeHttpRequest(`${process.env.SERVER_URL}/api/v1`);
21+
});
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { describe, expect } from 'vitest';
2+
import { createEsmAndCjsTests } from '../../../../utils/runner';
3+
import { createTestServer } from '../../../../utils/server';
4+
5+
describe('outgoing traceparent', () => {
6+
createEsmAndCjsTests(__dirname, 'scenario-fetch.mjs', 'instrument.mjs', (createRunner, test) => {
7+
test('outgoing fetch requests should get traceparent headers', async () => {
8+
expect.assertions(5);
9+
10+
const [SERVER_URL, closeTestServer] = await createTestServer()
11+
.get('/api/v1', headers => {
12+
expect(headers['baggage']).toEqual(expect.any(String));
13+
expect(headers['sentry-trace']).toEqual(expect.stringMatching(/^([a-f\d]{32})-([a-f\d]{16})-1$/));
14+
expect(headers['sentry-trace']).not.toEqual('00000000000000000000000000000000-0000000000000000-0');
15+
expect(headers['traceparent']).toEqual(expect.stringMatching(/^00-([a-f\d]{32})-([a-f\d]{16})-01$/));
16+
})
17+
.start();
18+
19+
await createRunner()
20+
.withEnv({ SERVER_URL })
21+
.expect({
22+
transaction: {
23+
// we're not too concerned with the actual transaction here since this is tested elsewhere
24+
},
25+
})
26+
.start()
27+
.completed();
28+
closeTestServer();
29+
});
30+
});
31+
32+
createEsmAndCjsTests(__dirname, 'scenario-http.mjs', 'instrument.mjs', (createRunner, test) => {
33+
test('outgoing http requests should get traceparent headers', async () => {
34+
expect.assertions(5);
35+
36+
const [SERVER_URL, closeTestServer] = await createTestServer()
37+
.get('/api/v1', headers => {
38+
expect(headers['baggage']).toEqual(expect.any(String));
39+
expect(headers['sentry-trace']).toEqual(expect.stringMatching(/^([a-f\d]{32})-([a-f\d]{16})-1$/));
40+
expect(headers['sentry-trace']).not.toEqual('00000000000000000000000000000000-0000000000000000-0');
41+
expect(headers['traceparent']).toEqual(expect.stringMatching(/^00-([a-f\d]{32})-([a-f\d]{16})-01$/));
42+
})
43+
.start();
44+
45+
await createRunner()
46+
.withEnv({ SERVER_URL })
47+
.expect({
48+
transaction: {
49+
// we're not too concerned with the actual transaction here since this is tested elsewhere
50+
},
51+
})
52+
.start()
53+
.completed();
54+
closeTestServer();
55+
});
56+
});
57+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import * as Sentry from '@sentry/node';
2+
import { loggingTransport } from '@sentry-internal/node-integration-tests';
3+
4+
Sentry.init({
5+
dsn: 'https://[email protected]/1337',
6+
release: '1.0',
7+
tracesSampleRate: 1,
8+
propagateTraceparent: true,
9+
transport: loggingTransport,
10+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import * as Sentry from '@sentry/node';
2+
3+
async function run() {
4+
// Wrap in span that is not sampled
5+
await Sentry.startSpan({ name: 'outer' }, async () => {
6+
await fetch(`${process.env.SERVER_URL}/api/v1`).then(res => res.text());
7+
});
8+
}
9+
10+
run();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import * as Sentry from '@sentry/node';
2+
import * as http from 'http';
3+
4+
function makeHttpRequest(url) {
5+
return new Promise(resolve => {
6+
http
7+
.request(url, httpRes => {
8+
httpRes.on('data', () => {
9+
// we don't care about data
10+
});
11+
httpRes.on('end', () => {
12+
resolve();
13+
});
14+
})
15+
.end();
16+
});
17+
}
18+
19+
Sentry.startSpan({ name: 'outer' }, async () => {
20+
await makeHttpRequest(`${process.env.SERVER_URL}/api/v1`);
21+
});
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { describe, expect } from 'vitest';
2+
import { createEsmAndCjsTests } from '../../../../utils/runner';
3+
import { createTestServer } from '../../../../utils/server';
4+
5+
describe('outgoing traceparent', () => {
6+
createEsmAndCjsTests(__dirname, 'scenario-fetch.mjs', 'instrument.mjs', (createRunner, test) => {
7+
test('outgoing fetch requests should get traceparent headers', async () => {
8+
expect.assertions(5);
9+
10+
const [SERVER_URL, closeTestServer] = await createTestServer()
11+
.get('/api/v1', headers => {
12+
expect(headers['baggage']).toEqual(expect.any(String));
13+
expect(headers['sentry-trace']).toEqual(expect.stringMatching(/^([a-f\d]{32})-([a-f\d]{16})-1$/));
14+
expect(headers['sentry-trace']).not.toEqual('00000000000000000000000000000000-0000000000000000-0');
15+
expect(headers['traceparent']).toEqual(expect.stringMatching(/^00-([a-f\d]{32})-([a-f\d]{16})-01$/));
16+
})
17+
.start();
18+
19+
await createRunner()
20+
.withEnv({ SERVER_URL })
21+
.expect({
22+
transaction: {
23+
// we're not too concerned with the actual transaction here since this is tested elsewhere
24+
},
25+
})
26+
.start()
27+
.completed();
28+
closeTestServer();
29+
});
30+
});
31+
32+
createEsmAndCjsTests(__dirname, 'scenario-http.mjs', 'instrument.mjs', (createRunner, test) => {
33+
test('outgoing http requests should get traceparent headers', async () => {
34+
expect.assertions(5);
35+
36+
const [SERVER_URL, closeTestServer] = await createTestServer()
37+
.get('/api/v1', headers => {
38+
expect(headers['baggage']).toEqual(expect.any(String));
39+
expect(headers['sentry-trace']).toEqual(expect.stringMatching(/^([a-f\d]{32})-([a-f\d]{16})-1$/));
40+
expect(headers['sentry-trace']).not.toEqual('00000000000000000000000000000000-0000000000000000-0');
41+
expect(headers['traceparent']).toEqual(expect.stringMatching(/^00-([a-f\d]{32})-([a-f\d]{16})-01$/));
42+
})
43+
.start();
44+
45+
await createRunner()
46+
.withEnv({ SERVER_URL })
47+
.expect({
48+
transaction: {
49+
// we're not too concerned with the actual transaction here since this is tested elsewhere
50+
},
51+
})
52+
.start()
53+
.completed();
54+
closeTestServer();
55+
});
56+
});
57+
});

packages/browser/src/client.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,6 @@ type BrowserSpecificOptions = BrowserClientReplayOptions &
5050
*/
5151
skipBrowserExtensionCheck?: boolean;
5252

53-
/**
54-
* If set to `true`, the SDK propagates the W3C `traceparent` header to any outgoing requests,
55-
* in addition to the `sentry-trace` and `baggage` headers. Use the {@link CoreOptions.tracePropagationTargets}
56-
* option to control to which outgoing requests the header will be attached.
57-
*
58-
* **Important:** If you set this option to `true`, make sure that you configured your servers'
59-
* CORS settings to allow the `traceparent` header. Otherwise, requests might get blocked.
60-
*
61-
* @see https://www.w3.org/TR/trace-context/
62-
*
63-
* @default false
64-
*/
65-
propagateTraceparent?: boolean;
66-
6753
/**
6854
* If you use Spotlight by Sentry during development, use
6955
* this option to forward captured Sentry events to Spotlight.

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ export {
270270
generateSentryTraceHeader,
271271
propagationContextFromHeaders,
272272
shouldContinueTrace,
273+
generateTraceparentHeader,
273274
} from './utils/tracing';
274275
export { getSDKSource, isBrowserBundle } from './utils/env';
275276
export type { SdkSource } from './utils/env';

0 commit comments

Comments
 (0)