From 97fbd3abf7c41dbd343466e2cba3a30ab4522f80 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Thu, 2 Jun 2022 10:34:39 +0200 Subject: [PATCH 1/5] feat(tracing): add propagation of environment and release values in baggage headers --- packages/tracing/src/browser/request.ts | 2 +- packages/tracing/src/span.ts | 40 ++++++++++++++++-- packages/tracing/src/transaction.ts | 6 +-- packages/tracing/test/span.test.ts | 55 +++++++++++++++++++++++++ packages/types/src/span.ts | 2 + packages/utils/src/baggage.ts | 10 ++++- packages/utils/test/baggage.test.ts | 6 +-- 7 files changed, 109 insertions(+), 12 deletions(-) diff --git a/packages/tracing/src/browser/request.ts b/packages/tracing/src/browser/request.ts index b45775edd05f..0d72c96a2a30 100644 --- a/packages/tracing/src/browser/request.ts +++ b/packages/tracing/src/browser/request.ts @@ -1,4 +1,5 @@ /* eslint-disable max-lines */ +import type { Span } from '@sentry/types'; import { addInstrumentationHandler, BAGGAGE_HEADER_NAME, @@ -7,7 +8,6 @@ import { mergeAndSerializeBaggage, } from '@sentry/utils'; -import { Span } from '../span'; import { getActiveTransaction, hasTracingEnabled } from '../utils'; export const DEFAULT_TRACING_ORIGINS = ['localhost', /^\//]; diff --git a/packages/tracing/src/span.ts b/packages/tracing/src/span.ts index 68cba79eb7cc..f6755972b576 100644 --- a/packages/tracing/src/span.ts +++ b/packages/tracing/src/span.ts @@ -1,6 +1,15 @@ /* eslint-disable max-lines */ -import { Baggage, Primitive, Span as SpanInterface, SpanContext, Transaction } from '@sentry/types'; -import { dropUndefinedKeys, timestampWithMs, uuid4 } from '@sentry/utils'; +import { getCurrentHub } from '@sentry/hub'; +import { Baggage, Hub, Primitive, Span as SpanInterface, SpanContext, Transaction } from '@sentry/types'; +import { + createBaggage, + dropUndefinedKeys, + isBaggageEmpty, + isSentryBaggageEmpty, + setBaggageValue, + timestampWithMs, + uuid4, +} from '@sentry/utils'; /** * Keeps track of finished spans for a given transaction @@ -302,7 +311,14 @@ export class Span implements SpanInterface { * @inheritdoc */ public getBaggage(): Baggage | undefined { - return this.transaction && this.transaction.metadata.baggage; + const existingBaggage = this.transaction && this.transaction.metadata.baggage; + + const finalBaggage = + !existingBaggage || isSentryBaggageEmpty(existingBaggage) + ? this._getBaggageWithSentryValues(existingBaggage) + : existingBaggage; + + return isBaggageEmpty(finalBaggage) ? undefined : finalBaggage; } /** @@ -334,6 +350,24 @@ export class Span implements SpanInterface { trace_id: this.traceId, }); } + + /** + * + * @param baggage + * @returns + */ + private _getBaggageWithSentryValues(baggage: Baggage = createBaggage({})): Baggage { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any + const hub: Hub = ((this.transaction as any) && (this.transaction as any)._hub) || getCurrentHub(); + const client = hub.getClient(); + + const { environment, release } = (client && client.getOptions()) || {}; + + environment && setBaggageValue(baggage, 'environment', environment); + release && setBaggageValue(baggage, 'release', release); + + return baggage; + } } export type SpanStatusType = diff --git a/packages/tracing/src/transaction.ts b/packages/tracing/src/transaction.ts index fb6cd9d02b6c..464f9c2588cc 100644 --- a/packages/tracing/src/transaction.ts +++ b/packages/tracing/src/transaction.ts @@ -17,12 +17,12 @@ export class Transaction extends SpanClass implements TransactionInterface { public metadata: TransactionMetadata; - private _measurements: Measurements = {}; - /** * The reference to the current hub. */ - private readonly _hub: Hub; + protected readonly _hub: Hub; + + private _measurements: Measurements = {}; private _trimEnd?: boolean; diff --git a/packages/tracing/test/span.test.ts b/packages/tracing/test/span.test.ts index 27df400ffc9e..d64f986cd9da 100644 --- a/packages/tracing/test/span.test.ts +++ b/packages/tracing/test/span.test.ts @@ -1,9 +1,11 @@ import { BrowserClient } from '@sentry/browser'; import { Hub, makeMain, Scope } from '@sentry/hub'; +import { createBaggage, getSentryBaggageItems, getThirdPartyBaggage, isSentryBaggageEmpty } from '@sentry/utils'; import { Span, Transaction } from '../src'; import { TRACEPARENT_REGEXP } from '../src/utils'; import { getDefaultBrowserClientOptions } from './testutils'; +import { BaseTransportOptions, ClientOptions } from '@sentry/types'; describe('Span', () => { let hub: Hub; @@ -390,4 +392,57 @@ describe('Span', () => { expect(span.data).toStrictEqual({ data0: 'foo', data1: 'bar' }); }); }); + + describe('getBaggage and _getBaggageWithSentryValues', () => { + beforeEach(() => { + hub.getClient()!!.getOptions = () => { + return { + release: '1.0.1', + environment: 'production', + } as ClientOptions; + }; + }); + + test('leave baggage content untouched and just return baggage if there already is Sentry content in it', () => { + const transaction = new Transaction( + { + name: 'tx', + metadata: { baggage: createBaggage({ environment: 'myEnv' }, '') }, + }, + hub, + ); + + const hubSpy = jest.spyOn(hub.getClient()!!, 'getOptions'); + + const span = transaction.startChild(); + + const baggage = span.getBaggage(); + + expect(hubSpy).toHaveBeenCalledTimes(0); + expect(baggage && isSentryBaggageEmpty(baggage)).toBeFalsy(); + expect(baggage && getSentryBaggageItems(baggage)).toStrictEqual({ environment: 'myEnv' }); + expect(baggage && getThirdPartyBaggage(baggage)).toStrictEqual(''); + }); + + test('add Sentry baggage data to baggage if Sentry content is empty', () => { + const transaction = new Transaction( + { + name: 'tx', + metadata: { baggage: createBaggage({}, '') }, + }, + hub, + ); + + const hubSpy = jest.spyOn(hub.getClient()!!, 'getOptions'); + + const span = transaction.startChild(); + + const baggage = span.getBaggage(); + + expect(hubSpy).toHaveBeenCalledTimes(1); + expect(baggage && isSentryBaggageEmpty(baggage)).toBeFalsy(); + expect(baggage && getSentryBaggageItems(baggage)).toStrictEqual({ release: '1.0.1', environment: 'production' }); + expect(baggage && getThirdPartyBaggage(baggage)).toStrictEqual(''); + }); + }); }); diff --git a/packages/types/src/span.ts b/packages/types/src/span.ts index 120d754cc329..a619bf3c3489 100644 --- a/packages/types/src/span.ts +++ b/packages/types/src/span.ts @@ -178,4 +178,6 @@ export interface Span extends SpanContext { /** return the baggage for dynamic sampling and trace propagation */ getBaggage(): Baggage | undefined; + + //_getBaggageWithSentryValues(baggage: Baggage): Baggage; } diff --git a/packages/utils/src/baggage.ts b/packages/utils/src/baggage.ts index bc2f6568ff1f..16b066f6a8c0 100644 --- a/packages/utils/src/baggage.ts +++ b/packages/utils/src/baggage.ts @@ -31,11 +31,17 @@ export function setBaggageValue(baggage: Baggage, key: keyof BaggageObj, value: baggage[0][key] = value; } -/** Check if the baggage object (i.e. the first element in the tuple) is empty */ -export function isBaggageEmpty(baggage: Baggage): boolean { +/** Check if the Sentry part of the passed baggage (i.e. the first element in the tuple) is empty */ +export function isSentryBaggageEmpty(baggage: Baggage): boolean { return Object.keys(baggage[0]).length === 0; } +/** Check if the Sentry part of the passed baggage (i.e. the first element in the tuple) is empty */ +export function isBaggageEmpty(baggage: Baggage): boolean { + const thirdPartyBaggage = getThirdPartyBaggage(baggage); + return isSentryBaggageEmpty(baggage) && (thirdPartyBaggage == undefined || thirdPartyBaggage.length === 0); +} + /** Returns Sentry specific baggage values */ export function getSentryBaggageItems(baggage: Baggage): BaggageObj { return baggage[0]; diff --git a/packages/utils/test/baggage.test.ts b/packages/utils/test/baggage.test.ts index 07ccdaaedd48..380b6cd076ce 100644 --- a/packages/utils/test/baggage.test.ts +++ b/packages/utils/test/baggage.test.ts @@ -1,7 +1,7 @@ import { createBaggage, getBaggageValue, - isBaggageEmpty, + isSentryBaggageEmpty, mergeAndSerializeBaggage, parseBaggageString, serializeBaggage, @@ -98,12 +98,12 @@ describe('Baggage', () => { }); }); - describe('isBaggageEmpty', () => { + describe('isSentryBaggageEmpty', () => { it.each([ ['returns true if the modifyable part of baggage is empty', createBaggage({}), true], ['returns false if the modifyable part of baggage is not empty', createBaggage({ release: '10.0.2' }), false], ])('%s', (_: string, baggage, outcome) => { - expect(isBaggageEmpty(baggage)).toEqual(outcome); + expect(isSentryBaggageEmpty(baggage)).toEqual(outcome); }); }); From 296f4c206ef4cb1004a6666bbacee4ae71aa24a4 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Thu, 2 Jun 2022 10:55:49 +0200 Subject: [PATCH 2/5] adjust node integration tests --- .../sentry-trace/baggage-header-assign/test.ts | 16 ++++++++-------- .../sentry-trace/baggage-header-out/test.ts | 3 +-- .../suites/express/sentry-trace/server.ts | 1 + packages/types/src/span.ts | 2 -- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/node-integration-tests/suites/express/sentry-trace/baggage-header-assign/test.ts b/packages/node-integration-tests/suites/express/sentry-trace/baggage-header-assign/test.ts index 81dddb7c1f97..4e0677f8c14f 100644 --- a/packages/node-integration-tests/suites/express/sentry-trace/baggage-header-assign/test.ts +++ b/packages/node-integration-tests/suites/express/sentry-trace/baggage-header-assign/test.ts @@ -3,7 +3,7 @@ import * as path from 'path'; import { getAPIResponse, runServer } from '../../../../utils/index'; import { TestAPIResponse } from '../server'; -test('Should assign `baggage` header which contains 3rd party trace baggage data of an outgoing request.', async () => { +test('Should assign `baggage` header which contains 3rd party trace baggage data to an outgoing request.', async () => { const url = await runServer(__dirname, `${path.resolve(__dirname, '..')}/server.ts`); const response = (await getAPIResponse(new URL(`${url}/express`), { @@ -14,39 +14,39 @@ test('Should assign `baggage` header which contains 3rd party trace baggage data expect(response).toMatchObject({ test_data: { host: 'somewhere.not.sentry', - baggage: expect.stringContaining('foo=bar,bar=baz'), + baggage: 'foo=bar,bar=baz,sentry-environment=prod,sentry-release=1.0', }, }); }); -test('Should assign `baggage` header which contains sentry trace baggage data of an outgoing request.', async () => { +test('Should assign `baggage` header which contains sentry trace baggage data to an outgoing request.', async () => { const url = await runServer(__dirname, `${path.resolve(__dirname, '..')}/server.ts`); const response = (await getAPIResponse(new URL(`${url}/express`), { - baggage: 'sentry-version=1.0.0,sentry-environment=production', + baggage: 'sentry-version=2.0.0,sentry-environment=myEnv', })) as TestAPIResponse; expect(response).toBeDefined(); expect(response).toMatchObject({ test_data: { host: 'somewhere.not.sentry', - baggage: expect.stringContaining('sentry-version=1.0.0,sentry-environment=production'), + baggage: 'sentry-version=2.0.0,sentry-environment=myEnv', }, }); }); -test('Should assign `baggage` header which contains sentry and 3rd party trace baggage data of an outgoing request.', async () => { +test('Should assign `baggage` header which contains sentry and 3rd party trace baggage data to an outgoing request.', async () => { const url = await runServer(__dirname, `${path.resolve(__dirname, '..')}/server.ts`); const response = (await getAPIResponse(new URL(`${url}/express`), { - baggage: 'sentry-version=1.0.0,sentry-environment=production,dogs=great', + baggage: 'sentry-version=2.0.0,sentry-environment=myEnv,dogs=great', })) as TestAPIResponse; expect(response).toBeDefined(); expect(response).toMatchObject({ test_data: { host: 'somewhere.not.sentry', - baggage: expect.stringContaining('dogs=great,sentry-version=1.0.0,sentry-environment=production'), + baggage: expect.stringContaining('dogs=great,sentry-version=2.0.0,sentry-environment=myEnv'), }, }); }); diff --git a/packages/node-integration-tests/suites/express/sentry-trace/baggage-header-out/test.ts b/packages/node-integration-tests/suites/express/sentry-trace/baggage-header-out/test.ts index 70b6cc19edee..822e85105d0e 100644 --- a/packages/node-integration-tests/suites/express/sentry-trace/baggage-header-out/test.ts +++ b/packages/node-integration-tests/suites/express/sentry-trace/baggage-header-out/test.ts @@ -12,8 +12,7 @@ test('should attach a `baggage` header to an outgoing request.', async () => { expect(response).toMatchObject({ test_data: { host: 'somewhere.not.sentry', - // TODO this is currently still empty but eventually it should contain sentry data - baggage: expect.stringMatching(''), + baggage: expect.stringMatching('sentry-environment=prod,sentry-release=1.0'), }, }); }); diff --git a/packages/node-integration-tests/suites/express/sentry-trace/server.ts b/packages/node-integration-tests/suites/express/sentry-trace/server.ts index 632d9b8338fb..25238008efcf 100644 --- a/packages/node-integration-tests/suites/express/sentry-trace/server.ts +++ b/packages/node-integration-tests/suites/express/sentry-trace/server.ts @@ -11,6 +11,7 @@ export type TestAPIResponse = { test_data: { host: string; 'sentry-trace': strin Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', release: '1.0', + environment: 'prod', integrations: [new Sentry.Integrations.Http({ tracing: true }), new Tracing.Integrations.Express({ app })], tracesSampleRate: 1.0, }); diff --git a/packages/types/src/span.ts b/packages/types/src/span.ts index a619bf3c3489..120d754cc329 100644 --- a/packages/types/src/span.ts +++ b/packages/types/src/span.ts @@ -178,6 +178,4 @@ export interface Span extends SpanContext { /** return the baggage for dynamic sampling and trace propagation */ getBaggage(): Baggage | undefined; - - //_getBaggageWithSentryValues(baggage: Baggage): Baggage; } From d243198d206c87e3e7d9845c659b9628a16c5117 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Thu, 2 Jun 2022 11:19:27 +0200 Subject: [PATCH 3/5] fix node unit test type errors --- packages/node/test/integrations/http.test.ts | 4 ++-- packages/tracing/test/span.test.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/node/test/integrations/http.test.ts b/packages/node/test/integrations/http.test.ts index 50d26e92452a..c51ff1aa0f59 100644 --- a/packages/node/test/integrations/http.test.ts +++ b/packages/node/test/integrations/http.test.ts @@ -40,7 +40,7 @@ describe('tracing', () => { nock('http://dogs.are.great').get('/').reply(200); const transaction = createTransactionOnScope(); - const spans = (transaction as Span).spanRecorder?.spans as Span[]; + const spans = (transaction as unknown as Span).spanRecorder?.spans as Span[]; http.get('http://dogs.are.great/'); @@ -55,7 +55,7 @@ describe('tracing', () => { nock('http://squirrelchasers.ingest.sentry.io').get('/api/12312012/store/').reply(200); const transaction = createTransactionOnScope(); - const spans = (transaction as Span).spanRecorder?.spans as Span[]; + const spans = (transaction as unknown as Span).spanRecorder?.spans as Span[]; http.get('http://squirrelchasers.ingest.sentry.io/api/12312012/store/'); diff --git a/packages/tracing/test/span.test.ts b/packages/tracing/test/span.test.ts index d64f986cd9da..0c35b6c04765 100644 --- a/packages/tracing/test/span.test.ts +++ b/packages/tracing/test/span.test.ts @@ -1,11 +1,11 @@ import { BrowserClient } from '@sentry/browser'; import { Hub, makeMain, Scope } from '@sentry/hub'; +import { BaseTransportOptions, ClientOptions } from '@sentry/types'; import { createBaggage, getSentryBaggageItems, getThirdPartyBaggage, isSentryBaggageEmpty } from '@sentry/utils'; import { Span, Transaction } from '../src'; import { TRACEPARENT_REGEXP } from '../src/utils'; import { getDefaultBrowserClientOptions } from './testutils'; -import { BaseTransportOptions, ClientOptions } from '@sentry/types'; describe('Span', () => { let hub: Hub; @@ -395,7 +395,7 @@ describe('Span', () => { describe('getBaggage and _getBaggageWithSentryValues', () => { beforeEach(() => { - hub.getClient()!!.getOptions = () => { + hub.getClient()!.getOptions = () => { return { release: '1.0.1', environment: 'production', @@ -412,7 +412,7 @@ describe('Span', () => { hub, ); - const hubSpy = jest.spyOn(hub.getClient()!!, 'getOptions'); + const hubSpy = jest.spyOn(hub.getClient()!, 'getOptions'); const span = transaction.startChild(); @@ -433,7 +433,7 @@ describe('Span', () => { hub, ); - const hubSpy = jest.spyOn(hub.getClient()!!, 'getOptions'); + const hubSpy = jest.spyOn(hub.getClient()!, 'getOptions'); const span = transaction.startChild(); From 8e78e7c1a404e0e1fe3c5a2baf0bff82f06c27e1 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Thu, 2 Jun 2022 12:47:35 +0200 Subject: [PATCH 4/5] Improve node and tracing tests --- packages/node/test/integrations/http.test.ts | 8 ++-- .../test/browser/browsertracing.test.ts | 44 +++++++++++++++++-- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/packages/node/test/integrations/http.test.ts b/packages/node/test/integrations/http.test.ts index c51ff1aa0f59..254e371aaa35 100644 --- a/packages/node/test/integrations/http.test.ts +++ b/packages/node/test/integrations/http.test.ts @@ -21,6 +21,8 @@ describe('tracing', () => { dsn: 'https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012', tracesSampleRate: 1.0, integrations: [new HttpIntegration({ tracing: true })], + release: '1.0.0', + environment: 'production', }); const hub = new Hub(new NodeClient(options)); addExtensionMethods(); @@ -96,8 +98,7 @@ describe('tracing', () => { const baggageHeader = request.getHeader('baggage') as string; expect(baggageHeader).toBeDefined(); - // this might change once we actually add our baggage data to the header - expect(baggageHeader).toEqual(''); + expect(baggageHeader).toEqual('sentry-environment=production,sentry-release=1.0.0'); }); it('propagates 3rd party baggage header data to outgoing non-sentry requests', async () => { @@ -109,8 +110,7 @@ describe('tracing', () => { const baggageHeader = request.getHeader('baggage') as string; expect(baggageHeader).toBeDefined(); - // this might change once we actually add our baggage data to the header - expect(baggageHeader).toEqual('dog=great'); + expect(baggageHeader).toEqual('dog=great,sentry-environment=production,sentry-release=1.0.0'); }); it("doesn't attach the sentry-trace header to outgoing sentry requests", () => { diff --git a/packages/tracing/test/browser/browsertracing.test.ts b/packages/tracing/test/browser/browsertracing.test.ts index 6fbcc5b6f6d8..90587b88e255 100644 --- a/packages/tracing/test/browser/browsertracing.test.ts +++ b/packages/tracing/test/browser/browsertracing.test.ts @@ -1,6 +1,6 @@ import { BrowserClient } from '@sentry/browser'; import { Hub, makeMain } from '@sentry/hub'; -import { BaggageObj } from '@sentry/types'; +import type { BaggageObj, BaseTransportOptions, ClientOptions } from '@sentry/types'; import { getGlobalObject, InstrumentHandlerCallback, InstrumentHandlerType } from '@sentry/utils'; import { JSDOM } from 'jsdom'; @@ -415,7 +415,16 @@ describe('BrowserTracing', () => { }); }); - describe('using the data', () => { + describe('using the tag data', () => { + beforeEach(() => { + hub.getClient()!.getOptions = () => { + return { + release: '1.0.0', + environment: 'production', + } as ClientOptions; + }; + }); + it('uses the tracing data for pageload transactions', () => { // make sampled false here, so we can see that it's being used rather than the tracesSampleRate-dictated one document.head.innerHTML = @@ -439,11 +448,34 @@ describe('BrowserTracing', () => { expect(baggage[1]).toEqual('foo=bar'); }); + it('adds Sentry baggage data to pageload transactions if not present in meta tags', () => { + // make sampled false here, so we can see that it's being used rather than the tracesSampleRate-dictated one + document.head.innerHTML = + '' + + ''; + + // pageload transactions are created as part of the BrowserTracing integration's initialization + createBrowserTracing(true); + const transaction = getActiveTransaction(hub) as IdleTransaction; + const baggage = transaction.getBaggage()!; + + expect(transaction).toBeDefined(); + expect(transaction.op).toBe('pageload'); + expect(transaction.traceId).toEqual('12312012123120121231201212312012'); + expect(transaction.parentSpanId).toEqual('1121201211212012'); + expect(transaction.sampled).toBe(false); + expect(baggage).toBeDefined(); + expect(baggage[0]).toBeDefined(); + expect(baggage[0]).toEqual({ environment: 'production', release: '1.0.0' }); + expect(baggage[1]).toBeDefined(); + expect(baggage[1]).toEqual('foo=bar'); + }); + it('ignores the data for navigation transactions', () => { mockChangeHistory = () => undefined; document.head.innerHTML = '' + - ''; + ''; createBrowserTracing(true); @@ -455,7 +487,11 @@ describe('BrowserTracing', () => { expect(transaction.op).toBe('navigation'); expect(transaction.traceId).not.toEqual('12312012123120121231201212312012'); expect(transaction.parentSpanId).toBeUndefined(); - expect(baggage).toBeUndefined(); + expect(baggage).toBeDefined(); + expect(baggage[0]).toBeDefined(); + expect(baggage[0]).toEqual({ release: '1.0.0', environment: 'production' }); + expect(baggage[1]).toBeDefined(); + expect(baggage[1]).toEqual(''); }); }); }); From dd44ae74e9a3d9ddf5ef0f3a4087a93c7bd179ef Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Fri, 3 Jun 2022 17:15:09 +0200 Subject: [PATCH 5/5] change test descriptions (node integration tests) --- .../suites/express/sentry-trace/baggage-header-assign/test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/node-integration-tests/suites/express/sentry-trace/baggage-header-assign/test.ts b/packages/node-integration-tests/suites/express/sentry-trace/baggage-header-assign/test.ts index 4e0677f8c14f..f2d318877a65 100644 --- a/packages/node-integration-tests/suites/express/sentry-trace/baggage-header-assign/test.ts +++ b/packages/node-integration-tests/suites/express/sentry-trace/baggage-header-assign/test.ts @@ -19,7 +19,7 @@ test('Should assign `baggage` header which contains 3rd party trace baggage data }); }); -test('Should assign `baggage` header which contains sentry trace baggage data to an outgoing request.', async () => { +test('Should not overwrite baggage if the incoming request already has Sentry baggage data.', async () => { const url = await runServer(__dirname, `${path.resolve(__dirname, '..')}/server.ts`); const response = (await getAPIResponse(new URL(`${url}/express`), { @@ -35,7 +35,7 @@ test('Should assign `baggage` header which contains sentry trace baggage data to }); }); -test('Should assign `baggage` header which contains sentry and 3rd party trace baggage data to an outgoing request.', async () => { +test('Should pass along sentry and 3rd party trace baggage data from an incoming to an outgoing request.', async () => { const url = await runServer(__dirname, `${path.resolve(__dirname, '..')}/server.ts`); const response = (await getAPIResponse(new URL(`${url}/express`), {