Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(node): Ensure tracing without performance (TWP) works #11564

Merged
merged 13 commits into from
Apr 15, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { loggingTransport } from '@sentry-internal/node-integration-tests';
import * as Sentry from '@sentry/node';

export type TestAPIResponse = { test_data: { host: string; 'sentry-trace': string; baggage: string } };

Sentry.init({
dsn: 'https://[email protected]/1337',
release: '1.0',
environment: 'prod',
integrations: [
// TODO: This used to use the Express integration
],
tracesSampleRate: 1.0,
transport: loggingTransport,
});

import http from 'http';
import { startExpressServerAndSendPortToRunner } from '@sentry-internal/node-integration-tests';
import cors from 'cors';
import express from 'express';

const app = express();

app.use(cors());

app.get('/test/express', (_req, res) => {
const headers = http.get('http://somewhere.not.sentry/').getHeaders();

// Responding with the headers outgoing request headers back to the assertions.
res.send({ test_data: headers });
});

Sentry.setupExpressErrorHandler(app);

startExpressServerAndSendPortToRunner(app);
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ afterAll(() => {
});

test('Should assign `sentry-trace` header which sets parent trace id of an outgoing request.', async () => {
const runner = createRunner(__dirname, '..', 'server.ts').start();
const runner = createRunner(__dirname, 'server.ts').start();

const response = await runner.makeRequest<TestAPIResponse>('get', '/test/express', {
'sentry-trace': '12312012123120121231201212312012-1121201211212012-0',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { loggingTransport } from '@sentry-internal/node-integration-tests';
import * as Sentry from '@sentry/node';

Sentry.init({
dsn: 'https://[email protected]/1337',
release: '1.0',
tracePropagationTargets: [/\/v0/, 'v1'],
integrations: [],
transport: loggingTransport,
});

async function run(): Promise<void> {
// Since fetch is lazy loaded, we need to wait a bit until it's fully instrumented
await new Promise(resolve => setTimeout(resolve, 100));
await fetch(`${process.env.SERVER_URL}/api/v0`).then(res => res.text());
await fetch(`${process.env.SERVER_URL}/api/v1`).then(res => res.text());
await fetch(`${process.env.SERVER_URL}/api/v2`).then(res => res.text());
await fetch(`${process.env.SERVER_URL}/api/v3`).then(res => res.text());

Sentry.captureException(new Error('foo'));
}

// eslint-disable-next-line @typescript-eslint/no-floating-promises
run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { conditionalTest } from '../../../../utils';
import { createRunner } from '../../../../utils/runner';
import { createTestServer } from '../../../../utils/server';

conditionalTest({ min: 18 })('outgoing fetch', () => {
test('outgoing fetch requests are correctly instrumented without tracesSampleRate', done => {
expect.assertions(15);

createTestServer(done)
.get('/api/v0', headers => {
expect(headers['sentry-trace']).toEqual(expect.stringMatching(/^([a-f0-9]{32})-([a-f0-9]{16})$/));
expect(headers['sentry-trace']).not.toEqual('00000000000000000000000000000000-0000000000000000');
expect(headers['baggage']).toEqual(expect.any(String));
expect(headers['__requestUrl']).toBeUndefined();
})
.get('/api/v1', headers => {
expect(headers['sentry-trace']).toEqual(expect.stringMatching(/^([a-f0-9]{32})-([a-f0-9]{16})$/));
expect(headers['sentry-trace']).not.toEqual('00000000000000000000000000000000-0000000000000000');
expect(headers['baggage']).toEqual(expect.any(String));
expect(headers['__requestUrl']).toBeUndefined();
})
.get('/api/v2', headers => {
expect(headers['baggage']).toBeUndefined();
expect(headers['sentry-trace']).toBeUndefined();
expect(headers['__requestUrl']).toBeUndefined();
})
.get('/api/v3', headers => {
expect(headers['baggage']).toBeUndefined();
expect(headers['sentry-trace']).toBeUndefined();
expect(headers['__requestUrl']).toBeUndefined();
})
.start()
.then(SERVER_URL => {
createRunner(__dirname, 'scenario.ts')
.withEnv({ SERVER_URL })
.ensureNoErrorOutput()
.ignore('session', 'sessions')
.expect({
event: {
exception: {
values: [
{
type: 'Error',
value: 'foo',
},
],
},
},
})
.start(done);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { loggingTransport } from '@sentry-internal/node-integration-tests';
import * as Sentry from '@sentry/node';

Sentry.init({
dsn: 'https://[email protected]/1337',
release: '1.0',
tracePropagationTargets: [/\/v0/, 'v1'],
tracesSampleRate: 1.0,
integrations: [],
transport: loggingTransport,
});

async function run(): Promise<void> {
// Since fetch is lazy loaded, we need to wait a bit until it's fully instrumented
await new Promise(resolve => setTimeout(resolve, 100));
await fetch(`${process.env.SERVER_URL}/api/v0`).then(res => res.text());
await fetch(`${process.env.SERVER_URL}/api/v1`).then(res => res.text());
await fetch(`${process.env.SERVER_URL}/api/v2`).then(res => res.text());
await fetch(`${process.env.SERVER_URL}/api/v3`).then(res => res.text());

Sentry.captureException(new Error('foo'));
}

// eslint-disable-next-line @typescript-eslint/no-floating-promises
run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { conditionalTest } from '../../../../utils';
import { createRunner } from '../../../../utils/runner';
import { createTestServer } from '../../../../utils/server';

conditionalTest({ min: 18 })('outgoing fetch', () => {
test('outgoing sampled fetch requests without active span are correctly instrumented', done => {
expect.assertions(11);

createTestServer(done)
.get('/api/v0', headers => {
expect(headers['baggage']).toEqual(expect.any(String));
expect(headers['sentry-trace']).toEqual(expect.stringMatching(/^([a-f0-9]{32})-([a-f0-9]{16})$/));
expect(headers['sentry-trace']).not.toEqual('00000000000000000000000000000000-0000000000000000');
})
.get('/api/v1', headers => {
expect(headers['baggage']).toEqual(expect.any(String));
expect(headers['sentry-trace']).toEqual(expect.stringMatching(/^([a-f0-9]{32})-([a-f0-9]{16})$/));
expect(headers['sentry-trace']).not.toEqual('00000000000000000000000000000000-0000000000000000');
})
.get('/api/v2', headers => {
expect(headers['baggage']).toBeUndefined();
expect(headers['sentry-trace']).toBeUndefined();
})
.get('/api/v3', headers => {
expect(headers['baggage']).toBeUndefined();
expect(headers['sentry-trace']).toBeUndefined();
})
.start()
.then(SERVER_URL => {
createRunner(__dirname, 'scenario.ts')
.withEnv({ SERVER_URL })
.ignore('session', 'sessions')
.expect({
event: {
exception: {
values: [
{
type: 'Error',
value: 'foo',
},
],
},
},
})
.start(done);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { loggingTransport } from '@sentry-internal/node-integration-tests';
import * as Sentry from '@sentry/node';

Sentry.init({
dsn: 'https://[email protected]/1337',
release: '1.0',
tracesSampleRate: 1.0,
tracePropagationTargets: [/\/v0/, 'v1'],
integrations: [],
transport: loggingTransport,
});

async function run(): Promise<void> {
await Sentry.startSpan({ name: 'test_span' }, async () => {
// Since fetch is lazy loaded, we need to wait a bit until it's fully instrumented
await new Promise(resolve => setTimeout(resolve, 100));
await fetch(`${process.env.SERVER_URL}/api/v0`).then(res => res.text());
await fetch(`${process.env.SERVER_URL}/api/v1`).then(res => res.text());
await fetch(`${process.env.SERVER_URL}/api/v2`).then(res => res.text());
await fetch(`${process.env.SERVER_URL}/api/v3`).then(res => res.text());
});
}

// eslint-disable-next-line @typescript-eslint/no-floating-promises
run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { conditionalTest } from '../../../../utils';
import { createRunner } from '../../../../utils/runner';
import { createTestServer } from '../../../../utils/server';

conditionalTest({ min: 18 })('outgoing fetch', () => {
test('outgoing sampled fetch requests are correctly instrumented', done => {
expect.assertions(11);

createTestServer(done)
.get('/api/v0', headers => {
expect(headers['sentry-trace']).toEqual(expect.stringMatching(/^([a-f0-9]{32})-([a-f0-9]{16})-1$/));
expect(headers['sentry-trace']).not.toEqual('00000000000000000000000000000000-0000000000000000-1');
expect(headers['baggage']).toEqual(expect.any(String));
})
.get('/api/v1', headers => {
expect(headers['sentry-trace']).toEqual(expect.stringMatching(/^([a-f0-9]{32})-([a-f0-9]{16})-1$/));
expect(headers['sentry-trace']).not.toEqual('00000000000000000000000000000000-0000000000000000-1');
expect(headers['baggage']).toEqual(expect.any(String));
})
.get('/api/v2', headers => {
expect(headers['baggage']).toBeUndefined();
expect(headers['sentry-trace']).toBeUndefined();
})
.get('/api/v3', headers => {
expect(headers['baggage']).toBeUndefined();
expect(headers['sentry-trace']).toBeUndefined();
})
.start()
.then(SERVER_URL => {
createRunner(__dirname, 'scenario.ts')
.withEnv({ SERVER_URL })
.expect({
transaction: {
// we're not too concerned with the actual transaction here since this is tested elsewhere
},
})
.start(done);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { loggingTransport } from '@sentry-internal/node-integration-tests';
import * as Sentry from '@sentry/node';

Sentry.init({
dsn: 'https://[email protected]/1337',
release: '1.0',
tracePropagationTargets: [/\/v0/, 'v1'],
tracesSampleRate: 0,
integrations: [],
transport: loggingTransport,
});

async function run(): Promise<void> {
// Wrap in span that is not sampled
await Sentry.startSpan({ name: 'outer' }, async () => {
// Since fetch is lazy loaded, we need to wait a bit until it's fully instrumented
await new Promise(resolve => setTimeout(resolve, 100));
await fetch(`${process.env.SERVER_URL}/api/v0`).then(res => res.text());
await fetch(`${process.env.SERVER_URL}/api/v1`).then(res => res.text());
await fetch(`${process.env.SERVER_URL}/api/v2`).then(res => res.text());
await fetch(`${process.env.SERVER_URL}/api/v3`).then(res => res.text());
});

Sentry.captureException(new Error('foo'));
}

// eslint-disable-next-line @typescript-eslint/no-floating-promises
run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { conditionalTest } from '../../../../utils';
import { createRunner } from '../../../../utils/runner';
import { createTestServer } from '../../../../utils/server';

conditionalTest({ min: 18 })('outgoing fetch', () => {
test('outgoing fetch requests are correctly instrumented when not sampled', done => {
expect.assertions(11);

createTestServer(done)
.get('/api/v0', headers => {
expect(headers['baggage']).toEqual(expect.any(String));
expect(headers['sentry-trace']).toEqual(expect.stringMatching(/^([a-f0-9]{32})-([a-f0-9]{16})-0$/));
expect(headers['sentry-trace']).not.toEqual('00000000000000000000000000000000-0000000000000000-0');
})
.get('/api/v1', headers => {
expect(headers['baggage']).toEqual(expect.any(String));
expect(headers['sentry-trace']).toEqual(expect.stringMatching(/^([a-f0-9]{32})-([a-f0-9]{16})-0$/));
expect(headers['sentry-trace']).not.toEqual('00000000000000000000000000000000-0000000000000000-0');
})
.get('/api/v2', headers => {
expect(headers['baggage']).toBeUndefined();
expect(headers['sentry-trace']).toBeUndefined();
})
.get('/api/v3', headers => {
expect(headers['baggage']).toBeUndefined();
expect(headers['sentry-trace']).toBeUndefined();
})
.start()
.then(SERVER_URL => {
createRunner(__dirname, 'scenario.ts')
.withEnv({ SERVER_URL })
.ignore('session', 'sessions')
.expect({
event: {
exception: {
values: [
{
type: 'Error',
value: 'foo',
},
],
},
},
})
.start(done);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { loggingTransport } from '@sentry-internal/node-integration-tests';
import * as Sentry from '@sentry/node';

Sentry.init({
dsn: 'https://[email protected]/1337',
release: '1.0',
tracePropagationTargets: [/\/v0/, 'v1'],
integrations: [],
transport: loggingTransport,
});

import * as http from 'http';

async function run(): Promise<void> {
await makeHttpRequest(`${process.env.SERVER_URL}/api/v0`);
await makeHttpRequest(`${process.env.SERVER_URL}/api/v1`);
await makeHttpRequest(`${process.env.SERVER_URL}/api/v2`);
await makeHttpRequest(`${process.env.SERVER_URL}/api/v3`);

Sentry.captureException(new Error('foo'));
}

// eslint-disable-next-line @typescript-eslint/no-floating-promises
run();

function makeHttpRequest(url: string): Promise<void> {
return new Promise<void>(resolve => {
http
.request(url, httpRes => {
httpRes.on('data', () => {
// we don't care about data
});
httpRes.on('end', () => {
resolve();
});
})
.end();
});
}
Loading
Loading