Skip to content

Commit 6c27931

Browse files
author
Luca Forstner
committed
Add tests for tracesSampleRate behavior
1 parent 4fb937f commit 6c27931

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

dev-packages/node-integration-tests/src/index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ export function startExpressServerAndSendPortToRunner(app: Express, port: number
2929
const server = app.listen(port || 0, () => {
3030
const address = server.address() as AddressInfo;
3131

32+
// @ts-expect-error If we write the port to the app we can read it within route handlers in tests
33+
app.port = port || address.port;
34+
3235
// eslint-disable-next-line no-console
3336
console.log(`{"port":${port || address.port}}`);
3437
});
@@ -41,3 +44,11 @@ export function sendPortToRunner(port: number): void {
4144
// eslint-disable-next-line no-console
4245
console.log(`{"port":${port}}`);
4346
}
47+
48+
/**
49+
* Can be used to get the port of a running app, so requests can be sent to a server from within the server.
50+
*/
51+
export function getPortAppIsRunningOn(app: Express): number | undefined {
52+
// @ts-expect-error It's not defined in the types but we'd like to read it.
53+
return app.port;
54+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const { loggingTransport } = require('@sentry-internal/node-integration-tests');
2+
const Sentry = require('@sentry/node');
3+
4+
Sentry.init({
5+
dsn: 'https://[email protected]/1337',
6+
transport: loggingTransport,
7+
tracesSampleRate: 1,
8+
});
9+
10+
// express must be required after Sentry is initialized
11+
const express = require('express');
12+
const cors = require('cors');
13+
const {
14+
startExpressServerAndSendPortToRunner,
15+
getPortAppIsRunningOn,
16+
} = require('@sentry-internal/node-integration-tests');
17+
18+
const app = express();
19+
20+
app.use(cors());
21+
22+
app.get('/check', (req, res) => {
23+
const appPort = getPortAppIsRunningOn(app);
24+
// eslint-disable-next-line no-undef
25+
fetch(`http://localhost:${appPort}/bounce`)
26+
.then(r => r.json())
27+
.then(bounceRes => {
28+
res.json({ propagatedData: bounceRes });
29+
});
30+
});
31+
32+
app.get('/bounce', (req, res) => {
33+
res.json({
34+
baggage: req.headers['baggage'],
35+
});
36+
});
37+
38+
Sentry.setupExpressErrorHandler(app);
39+
40+
startExpressServerAndSendPortToRunner(app);
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { cleanupChildProcesses, createRunner } from '../../../utils/runner';
2+
3+
describe('sample_rand propagation (default)', () => {
4+
afterAll(() => {
5+
cleanupChildProcesses();
6+
});
7+
8+
test('propagates a sample rand when there are no incoming trace headers', async () => {
9+
const runner = createRunner(__dirname, 'server.js').start();
10+
const response = await runner.makeRequest('get', '/check');
11+
expect(response).toEqual({
12+
propagatedData: {
13+
baggage: expect.stringMatching(/sentry-sample_rand=0\.[0-9]+/),
14+
},
15+
});
16+
});
17+
18+
test('propagates a sample rand when there is a sentry-trace header and incoming sentry baggage', async () => {
19+
const runner = createRunner(__dirname, 'server.js').start();
20+
const response = await runner.makeRequest('get', '/check', {
21+
headers: {
22+
'sentry-trace': '530699e319cc067ce440315d74acb312-414dc2a08d5d1dac-1',
23+
baggage: 'sentry-release=foo,sentry-sample_rand=0.424242',
24+
},
25+
});
26+
expect(response).toEqual({
27+
propagatedData: {
28+
baggage: expect.stringMatching(/sentry-sample_rand=0\.424242/),
29+
},
30+
});
31+
});
32+
33+
test('propagates a sample rand when there is an incoming sentry-trace header but no baggage header', async () => {
34+
const runner = createRunner(__dirname, 'server.js').start();
35+
const response = await runner.makeRequest('get', '/check', {
36+
headers: {
37+
'sentry-trace': '530699e319cc067ce440315d74acb312-414dc2a08d5d1dac-1',
38+
},
39+
});
40+
expect(response).toEqual({
41+
propagatedData: {
42+
baggage: expect.stringMatching(/sentry-sample_rand=0\.[0-9]+/),
43+
},
44+
});
45+
});
46+
47+
test('propagates a sample_rand that would lead to a positive sampling decision when there is an incoming positive sampling decision but no sample_rand in the baggage header', async () => {
48+
const runner = createRunner(__dirname, 'server.js').start();
49+
const response = await runner.makeRequest('get', '/check', {
50+
headers: {
51+
'sentry-trace': '530699e319cc067ce440315d74acb312-414dc2a08d5d1dac-1',
52+
baggage: 'sentry-sample_rate=0.25',
53+
},
54+
});
55+
56+
const sampleRand = Number((response as any).propagatedData.baggage.match(/sentry-sample_rand=(0\.[0-9]+)/)[1]);
57+
58+
expect(sampleRand).toStrictEqual(expect.any(Number));
59+
expect(sampleRand).not.toBeNaN();
60+
expect(sampleRand).toBeLessThan(0.25);
61+
});
62+
63+
test('propagates a sample_rand that would lead to a negative sampling decision when there is an incoming negative sampling decision but no sample_rand in the baggage header', async () => {
64+
const runner = createRunner(__dirname, 'server.js').start();
65+
const response = await runner.makeRequest('get', '/check', {
66+
headers: {
67+
'sentry-trace': '530699e319cc067ce440315d74acb312-414dc2a08d5d1dac-0',
68+
baggage: 'sentry-sample_rate=0.75',
69+
},
70+
});
71+
72+
const sampleRand = Number((response as any).propagatedData.baggage.match(/sentry-sample_rand=(0\.[0-9]+)/)[1]);
73+
74+
expect(sampleRand).toStrictEqual(expect.any(Number));
75+
expect(sampleRand).not.toBeNaN();
76+
expect(sampleRand).toBeGreaterThanOrEqual(0.75);
77+
});
78+
79+
test('a new sample_rand when there is no sentry-trace header but a baggage header with sample_rand', async () => {
80+
const runner = createRunner(__dirname, 'server.js').start();
81+
const response = await runner.makeRequest('get', '/check', {
82+
headers: {
83+
baggage: 'sentry-sample_rate=0.75,sentry-sample_rand=0.5',
84+
},
85+
});
86+
87+
expect((response as any).propagatedData.baggage).toMatch(/sentry-sample_rand=0\.[0-9]+/);
88+
const sampleRandStr = (response as any).propagatedData.baggage.match(/sentry-sample_rand=(0\.[0-9]+)/)[1];
89+
expect(sampleRandStr).not.toBe('0.5');
90+
});
91+
});

0 commit comments

Comments
 (0)