From f8a01c9f29f66c1f783086078ea09eafbb9a94e4 Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Tue, 25 Oct 2022 17:28:56 +0200 Subject: [PATCH 1/2] Add `tracePropagationTargets` and combine with `tracingOrigins` for adding `sentry-trace` headers --- packages/tracing/src/browser/request.ts | 39 +++++++++++++++++-------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/packages/tracing/src/browser/request.ts b/packages/tracing/src/browser/request.ts index 4f25c787e158..f0129b184ba2 100644 --- a/packages/tracing/src/browser/request.ts +++ b/packages/tracing/src/browser/request.ts @@ -22,6 +22,13 @@ export interface RequestInstrumentationOptions { */ tracingOrigins: Array; + /** + * List of strings / regex used to define which outgoing requests the `sentry-trace` header will be attached to. + * + * Default: ['localhost', /^\//] {@see DEFAULT_TRACING_ORIGINS} + */ + tracePropagationTargets: Array; + /** * Flag to disable patching all together for fetch requests. * @@ -99,12 +106,12 @@ export const defaultRequestInstrumentationOptions: RequestInstrumentationOptions traceFetch: true, traceXHR: true, tracingOrigins: DEFAULT_TRACING_ORIGINS, + tracePropagationTargets: DEFAULT_TRACING_ORIGINS, }; /** Registers span creators for xhr and fetch requests */ export function instrumentOutgoingRequests(_options?: Partial): void { - // eslint-disable-next-line @typescript-eslint/unbound-method - const { traceFetch, traceXHR, tracingOrigins, shouldCreateSpanForRequest } = { + const { traceFetch, traceXHR, tracingOrigins, tracePropagationTargets, shouldCreateSpanForRequest } = { ...defaultRequestInstrumentationOptions, ..._options, }; @@ -133,17 +140,21 @@ export function instrumentOutgoingRequests(_options?: Partial + tracingOrigins.some(origin => isMatchingPattern(url, origin)) || + tracePropagationTargets.some(origin => isMatchingPattern(url, origin)); + const spans: Record = {}; if (traceFetch) { addInstrumentationHandler('fetch', (handlerData: FetchData) => { - fetchCallback(handlerData, shouldCreateSpan, spans); + fetchCallback(handlerData, shouldCreateSpan, shouldAttachHeaders, spans); }); } if (traceXHR) { addInstrumentationHandler('xhr', (handlerData: XHRData) => { - xhrCallback(handlerData, shouldCreateSpan, spans); + xhrCallback(handlerData, shouldCreateSpan, shouldAttachHeaders, spans); }); } } @@ -154,6 +165,7 @@ export function instrumentOutgoingRequests(_options?: Partial boolean, + shouldAttachHeaders: (url: string) => boolean, spans: Record, ): void { if (!hasTracingEnabled() || !(handlerData.fetchData && shouldCreateSpan(handlerData.fetchData.url))) { @@ -203,14 +215,16 @@ export function fetchCallback( // eslint-disable-next-line @typescript-eslint/no-explicit-any const options: { [key: string]: any } = handlerData.args[1]; - options.headers = addTracingHeadersToFetchRequest( - request, - activeTransaction.getDynamicSamplingContext(), - span, - options, - ); + if (shouldAttachHeaders(handlerData.fetchData.url)) { + options.headers = addTracingHeadersToFetchRequest( + request, + activeTransaction.getDynamicSamplingContext(), + span, + options, + ); - activeTransaction.metadata.propagations += 1; + activeTransaction.metadata.propagations += 1; + } } } @@ -284,6 +298,7 @@ function addTracingHeadersToFetchRequest( export function xhrCallback( handlerData: XHRData, shouldCreateSpan: (url: string) => boolean, + shouldAttachHeaders: (url: string) => boolean, spans: Record, ): void { if ( @@ -329,7 +344,7 @@ export function xhrCallback( handlerData.xhr.__sentry_xhr_span_id__ = span.spanId; spans[handlerData.xhr.__sentry_xhr_span_id__] = span; - if (handlerData.xhr.setRequestHeader) { + if (handlerData.xhr.setRequestHeader && shouldAttachHeaders(handlerData.xhr.__sentry_xhr__.url)) { try { handlerData.xhr.setRequestHeader('sentry-trace', span.toTraceparent()); From fbdb1a4f4c8c3415a77cf1661fec77c8db8004c3 Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Tue, 25 Oct 2022 18:14:26 +0200 Subject: [PATCH 2/2] Fix tests --- packages/tracing/test/browser/request.test.ts | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/packages/tracing/test/browser/request.test.ts b/packages/tracing/test/browser/request.test.ts index 0c11a2bee515..13bd0cf01a5a 100644 --- a/packages/tracing/test/browser/request.test.ts +++ b/packages/tracing/test/browser/request.test.ts @@ -47,8 +47,8 @@ describe('instrumentOutgoingRequests', () => { describe('callbacks', () => { let hub: Hub; let transaction: Transaction; - const alwaysCreateSpan = () => true; - const neverCreateSpan = () => false; + const always = () => true; + const never = () => false; const startTimestamp = 1356996072000; const endTimestamp = 1356996072000; const fetchHandlerData: FetchData = { @@ -87,7 +87,7 @@ describe('callbacks', () => { it('does not create span if shouldCreateSpan returns false', () => { const spans = {}; - fetchCallback(fetchHandlerData, neverCreateSpan, spans); + fetchCallback(fetchHandlerData, never, never, spans); expect(spans).toEqual({}); }); @@ -96,7 +96,7 @@ describe('callbacks', () => { const noFetchData = { args: fetchHandlerData.args, startTimestamp: fetchHandlerData.startTimestamp }; const spans = {}; - fetchCallback(noFetchData, alwaysCreateSpan, spans); + fetchCallback(noFetchData, always, never, spans); expect(spans).toEqual({}); }); @@ -104,7 +104,7 @@ describe('callbacks', () => { hasTracingEnabled.mockReturnValueOnce(false); const spans = {}; - fetchCallback(fetchHandlerData, alwaysCreateSpan, spans); + fetchCallback(fetchHandlerData, always, never, spans); expect(spans).toEqual({}); }); @@ -118,7 +118,7 @@ describe('callbacks', () => { startTimestamp: 1353501072000, }; - fetchCallback(handlerData, alwaysCreateSpan, {}); + fetchCallback(handlerData, always, never, {}); const headers = (handlerData.args[1].headers as Record) || {}; expect(headers['sentry-trace']).not.toBeDefined(); @@ -128,7 +128,7 @@ describe('callbacks', () => { const spans = {}; // triggered by request being sent - fetchCallback(fetchHandlerData, alwaysCreateSpan, spans); + fetchCallback(fetchHandlerData, always, never, spans); const newSpan = transaction.spanRecorder?.spans[1] as Span; @@ -149,7 +149,7 @@ describe('callbacks', () => { }; // triggered by response coming back - fetchCallback(postRequestFetchHandlerData, alwaysCreateSpan, spans); + fetchCallback(postRequestFetchHandlerData, always, never, spans); expect(newSpan.endTimestamp).toBeDefined(); }); @@ -158,7 +158,7 @@ describe('callbacks', () => { const spans: Record = {}; // triggered by request being sent - fetchCallback(fetchHandlerData, alwaysCreateSpan, spans); + fetchCallback(fetchHandlerData, always, never, spans); const newSpan = transaction.spanRecorder?.spans[1] as Span; @@ -171,7 +171,7 @@ describe('callbacks', () => { }; // triggered by response coming back - fetchCallback(postRequestFetchHandlerData, alwaysCreateSpan, spans); + fetchCallback(postRequestFetchHandlerData, always, never, spans); expect(newSpan.status).toBe(spanStatusfromHttpCode(404)); }); @@ -186,7 +186,7 @@ describe('callbacks', () => { }; // in that case, the response coming back will be ignored - fetchCallback(postRequestFetchHandlerData, alwaysCreateSpan, {}); + fetchCallback(postRequestFetchHandlerData, always, never, {}); const newSpan = transaction.spanRecorder?.spans[1]; @@ -199,15 +199,17 @@ describe('callbacks', () => { expect(transaction.metadata.propagations).toBe(0); - fetchCallback(firstReqData, alwaysCreateSpan, {}); + fetchCallback(firstReqData, always, always, {}); expect(transaction.metadata.propagations).toBe(1); - fetchCallback(secondReqData, alwaysCreateSpan, {}); + fetchCallback(secondReqData, always, always, {}); expect(transaction.metadata.propagations).toBe(2); }); it('adds sentry-trace header to fetch requests', () => { - // TODO + fetchCallback(fetchHandlerData, always, always, {}); + + expect(fetchHandlerData.args[1].headers['sentry-trace']).toBeDefined(); }); }); @@ -215,7 +217,7 @@ describe('callbacks', () => { it('does not create span if shouldCreateSpan returns false', () => { const spans = {}; - xhrCallback(xhrHandlerData, neverCreateSpan, spans); + xhrCallback(xhrHandlerData, never, never, spans); expect(spans).toEqual({}); }); @@ -224,20 +226,20 @@ describe('callbacks', () => { hasTracingEnabled.mockReturnValueOnce(false); const spans = {}; - xhrCallback(xhrHandlerData, alwaysCreateSpan, spans); + xhrCallback(xhrHandlerData, always, never, spans); expect(spans).toEqual({}); }); it('does not add xhr request headers if tracing is disabled', () => { hasTracingEnabled.mockReturnValueOnce(false); - xhrCallback(xhrHandlerData, alwaysCreateSpan, {}); + xhrCallback(xhrHandlerData, always, always, {}); expect(setRequestHeader).not.toHaveBeenCalled(); }); it('adds sentry-trace header to XHR requests', () => { - xhrCallback(xhrHandlerData, alwaysCreateSpan, {}); + xhrCallback(xhrHandlerData, always, always, {}); expect(setRequestHeader).toHaveBeenCalledWith( 'sentry-trace', @@ -249,7 +251,7 @@ describe('callbacks', () => { const spans = {}; // triggered by request being sent - xhrCallback(xhrHandlerData, alwaysCreateSpan, spans); + xhrCallback(xhrHandlerData, always, never, spans); const newSpan = transaction.spanRecorder?.spans[1] as Span; @@ -270,7 +272,7 @@ describe('callbacks', () => { }; // triggered by response coming back - xhrCallback(postRequestXHRHandlerData, alwaysCreateSpan, spans); + xhrCallback(postRequestXHRHandlerData, always, never, spans); expect(newSpan.endTimestamp).toBeDefined(); }); @@ -279,7 +281,7 @@ describe('callbacks', () => { const spans = {}; // triggered by request being sent - xhrCallback(xhrHandlerData, alwaysCreateSpan, spans); + xhrCallback(xhrHandlerData, always, never, spans); const newSpan = transaction.spanRecorder?.spans[1] as Span; @@ -292,7 +294,7 @@ describe('callbacks', () => { postRequestXHRHandlerData.xhr.__sentry_xhr__.status_code = 404; // triggered by response coming back - xhrCallback(postRequestXHRHandlerData, alwaysCreateSpan, spans); + xhrCallback(postRequestXHRHandlerData, always, never, spans); expect(newSpan.status).toBe(spanStatusfromHttpCode(404)); }); @@ -311,7 +313,7 @@ describe('callbacks', () => { }; // in that case, the response coming back will be ignored - xhrCallback(postRequestXHRHandlerData, alwaysCreateSpan, {}); + xhrCallback(postRequestXHRHandlerData, always, never, {}); const newSpan = transaction.spanRecorder?.spans[1]; @@ -324,10 +326,10 @@ describe('callbacks', () => { expect(transaction.metadata.propagations).toBe(0); - xhrCallback(firstReqData, alwaysCreateSpan, {}); + xhrCallback(firstReqData, always, always, {}); expect(transaction.metadata.propagations).toBe(1); - xhrCallback(secondReqData, alwaysCreateSpan, {}); + xhrCallback(secondReqData, always, always, {}); expect(transaction.metadata.propagations).toBe(2); }); });