From 75af20f575b6f874ff1f45725ac05ed4d53cf3f0 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Fri, 11 Oct 2024 17:43:50 +0200 Subject: [PATCH] test(node): Add tests for current DSC transaction name updating behavior --- .../dsc-txn-name-update/scenario-events.ts | 29 +++++ .../dsc-txn-name-update/scenario-headers.ts | 45 +++++++ .../tracing/dsc-txn-name-update/test.ts | 123 ++++++++++++++++++ 3 files changed, 197 insertions(+) create mode 100644 dev-packages/node-integration-tests/suites/tracing/dsc-txn-name-update/scenario-events.ts create mode 100644 dev-packages/node-integration-tests/suites/tracing/dsc-txn-name-update/scenario-headers.ts create mode 100644 dev-packages/node-integration-tests/suites/tracing/dsc-txn-name-update/test.ts diff --git a/dev-packages/node-integration-tests/suites/tracing/dsc-txn-name-update/scenario-events.ts b/dev-packages/node-integration-tests/suites/tracing/dsc-txn-name-update/scenario-events.ts new file mode 100644 index 000000000000..892167fa55b4 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/dsc-txn-name-update/scenario-events.ts @@ -0,0 +1,29 @@ +import { loggingTransport } from '@sentry-internal/node-integration-tests'; +import * as Sentry from '@sentry/node'; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + tracesSampleRate: 1.0, + transport: loggingTransport, +}); + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +Sentry.startSpan( + { name: 'initial-name', attributes: { [Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url' } }, + async span => { + Sentry.captureMessage('message-1'); + + span.updateName('updated-name-1'); + span.setAttribute(Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'route'); + + Sentry.captureMessage('message-2'); + + span.updateName('updated-name-2'); + span.setAttribute(Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'custom'); + + Sentry.captureMessage('message-3'); + + span.end(); + }, +); diff --git a/dev-packages/node-integration-tests/suites/tracing/dsc-txn-name-update/scenario-headers.ts b/dev-packages/node-integration-tests/suites/tracing/dsc-txn-name-update/scenario-headers.ts new file mode 100644 index 000000000000..8c9c01e21444 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/dsc-txn-name-update/scenario-headers.ts @@ -0,0 +1,45 @@ +import { loggingTransport } from '@sentry-internal/node-integration-tests'; +import * as Sentry from '@sentry/node'; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + release: '1.0', + tracesSampleRate: 1.0, + transport: loggingTransport, +}); + +import * as http from 'http'; + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +Sentry.startSpan( + { name: 'initial-name', attributes: { [Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url' } }, + async span => { + await makeHttpRequest(`${process.env.SERVER_URL}/api/v0`); + + span.updateName('updated-name-1'); + span.setAttribute(Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'route'); + + await makeHttpRequest(`${process.env.SERVER_URL}/api/v1`); + + span.updateName('updated-name-2'); + span.setAttribute(Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'custom'); + await makeHttpRequest(`${process.env.SERVER_URL}/api/v2`); + + span.end(); + }, +); + +function makeHttpRequest(url: string): Promise { + return new Promise(resolve => { + http + .request(url, httpRes => { + httpRes.on('data', () => { + // we don't care about data + }); + httpRes.on('end', () => { + resolve(); + }); + }) + .end(); + }); +} 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 new file mode 100644 index 000000000000..cefaba1ad97f --- /dev/null +++ b/dev-packages/node-integration-tests/suites/tracing/dsc-txn-name-update/test.ts @@ -0,0 +1,123 @@ +import { createRunner } from '../../../utils/runner'; +import { createTestServer } from '../../../utils/server'; + +test('adds current transaction name to baggage when the txn name is high-quality', done => { + expect.assertions(5); + + let traceId: string | undefined; + + createTestServer(done) + .get('/api/v0', headers => { + const baggageItems = getBaggageHeaderItems(headers); + traceId = baggageItems.find(item => item.startsWith('sentry-trace_id='))?.split('=')[1] as string; + + expect(traceId).toMatch(/^[0-9a-f]{32}$/); + + expect(baggageItems).toEqual([ + 'sentry-environment=production', + 'sentry-public_key=public', + 'sentry-release=1.0', + 'sentry-sample_rate=1', + 'sentry-sampled=true', + `sentry-trace_id=${traceId}`, + ]); + }) + .get('/api/v1', headers => { + expect(getBaggageHeaderItems(headers)).toEqual([ + 'sentry-environment=production', + 'sentry-public_key=public', + 'sentry-release=1.0', + 'sentry-sample_rate=1', + 'sentry-sampled=true', + `sentry-trace_id=${traceId}`, + 'sentry-transaction=updated-name-1', + ]); + }) + .get('/api/v2', headers => { + expect(getBaggageHeaderItems(headers)).toEqual([ + 'sentry-environment=production', + 'sentry-public_key=public', + 'sentry-release=1.0', + 'sentry-sample_rate=1', + 'sentry-sampled=true', + `sentry-trace_id=${traceId}`, + 'sentry-transaction=updated-name-2', + ]); + }) + .start() + .then(([SERVER_URL, closeTestServer]) => { + createRunner(__dirname, 'scenario-headers.ts') + .withEnv({ SERVER_URL }) + .expect({ + transaction: {}, + }) + .start(closeTestServer); + }); +}); + +test('adds current transaction name to trace envelope header when the txn name is high-quality', done => { + expect.assertions(4); + + createRunner(__dirname, 'scenario-events.ts') + .expectHeader({ + event: { + trace: { + environment: 'production', + public_key: 'public', + release: '1.0', + sample_rate: '1', + sampled: 'true', + trace_id: expect.any(String), + }, + }, + }) + .expectHeader({ + event: { + trace: { + environment: 'production', + public_key: 'public', + release: '1.0', + sample_rate: '1', + sampled: 'true', + trace_id: expect.any(String), + transaction: 'updated-name-1', + }, + }, + }) + .expectHeader({ + event: { + trace: { + environment: 'production', + public_key: 'public', + release: '1.0', + sample_rate: '1', + sampled: 'true', + trace_id: expect.any(String), + transaction: 'updated-name-2', + }, + }, + }) + .expectHeader({ + transaction: { + trace: { + environment: 'production', + public_key: 'public', + release: '1.0', + sample_rate: '1', + sampled: 'true', + trace_id: expect.any(String), + transaction: 'updated-name-2', + }, + }, + }) + .start(done); +}); + +function getBaggageHeaderItems(headers: Record) { + const baggage = headers['baggage'] as string; + const baggageItems = baggage + .split(',') + .map(b => b.trim()) + .sort(); + return baggageItems; +}