-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(core): Ensure
http.client
span descriptions don't contain query…
… params or fragments (#15404) This patch fixes an oversight with our `fetch` instrumentation in the core package and the browser XHR instrumentation. We didn't strip query params and URL hash fragments from the span name (description) of `http.client` spans. With this fix, the span description now only contains the URL protocol, host and path as defined in our [develop specification](https://develop.sentry.dev/sdk/expected-features/data-handling/#spans).
- Loading branch information
Showing
21 changed files
with
821 additions
and
23 deletions.
There are no files selected for viewing
11 changes: 11 additions & 0 deletions
11
...s/browser-integration-tests/suites/tracing/request/fetch-strip-query-and-fragment/init.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import * as Sentry from '@sentry/browser'; | ||
|
||
window.Sentry = Sentry; | ||
|
||
Sentry.init({ | ||
dsn: 'https://[email protected]/1337', | ||
integrations: [Sentry.browserTracingIntegration({ instrumentPageLoad: false, instrumentNavigation: false })], | ||
tracePropagationTargets: ['http://sentry-test-site.example'], | ||
tracesSampleRate: 1, | ||
autoSessionTracking: false, | ||
}); |
19 changes: 19 additions & 0 deletions
19
...rowser-integration-tests/suites/tracing/request/fetch-strip-query-and-fragment/subject.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
function withRootSpan(cb) { | ||
return Sentry.startSpan({ name: 'rootSpan' }, cb); | ||
} | ||
|
||
document.getElementById('btnQuery').addEventListener('click', async () => { | ||
await withRootSpan(() => fetch('http://sentry-test-site.example/0?id=123;page=5')); | ||
}); | ||
|
||
document.getElementById('btnFragment').addEventListener('click', async () => { | ||
await withRootSpan(() => fetch('http://sentry-test-site.example/1#fragment')); | ||
}); | ||
|
||
document.getElementById('btnQueryFragment').addEventListener('click', async () => { | ||
await withRootSpan(() => fetch('http://sentry-test-site.example/2?id=1#fragment')); | ||
}); | ||
|
||
document.getElementById('btnQueryFragmentSameOrigin').addEventListener('click', async () => { | ||
await withRootSpan(() => fetch('/api/users?id=1#fragment')); | ||
}); |
12 changes: 12 additions & 0 deletions
12
...ser-integration-tests/suites/tracing/request/fetch-strip-query-and-fragment/template.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8" /> | ||
</head> | ||
<body> | ||
<button id="btnQuery">Request with query</button> | ||
<button id="btnFragment">Request with fragment</button> | ||
<button id="btnQueryFragment">Request with query and fragment</button> | ||
<button id="btnQueryFragmentSameOrigin">Request with query and fragment</button> | ||
</body> | ||
</html> |
176 changes: 176 additions & 0 deletions
176
...s/browser-integration-tests/suites/tracing/request/fetch-strip-query-and-fragment/test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
import { expect } from '@playwright/test'; | ||
import { sentryTest } from '../../../../utils/fixtures'; | ||
import { envelopeRequestParser, shouldSkipTracingTest, waitForTransactionRequest } from '../../../../utils/helpers'; | ||
|
||
sentryTest('strips query params in fetch request spans', async ({ getLocalTestUrl, page }) => { | ||
if (shouldSkipTracingTest()) { | ||
sentryTest.skip(); | ||
} | ||
|
||
await page.route('http://sentry-test-site.example/*', route => route.fulfill({ body: 'ok' })); | ||
|
||
const url = await getLocalTestUrl({ testDir: __dirname }); | ||
|
||
await page.goto(url); | ||
|
||
const txnPromise = waitForTransactionRequest(page); | ||
await page.locator('#btnQuery').click(); | ||
const transactionEvent = envelopeRequestParser(await txnPromise); | ||
|
||
expect(transactionEvent.transaction).toEqual('rootSpan'); | ||
|
||
const requestSpan = transactionEvent.spans?.find(({ op }) => op === 'http.client'); | ||
|
||
expect(requestSpan).toMatchObject({ | ||
description: 'GET http://sentry-test-site.example/0', | ||
parent_span_id: transactionEvent.contexts?.trace?.span_id, | ||
span_id: expect.stringMatching(/[a-f0-9]{16}/), | ||
start_timestamp: expect.any(Number), | ||
timestamp: expect.any(Number), | ||
trace_id: transactionEvent.contexts?.trace?.trace_id, | ||
data: expect.objectContaining({ | ||
'http.method': 'GET', | ||
'http.url': 'http://sentry-test-site.example/0?id=123;page=5', | ||
'http.query': '?id=123;page=5', | ||
'http.response.status_code': 200, | ||
'http.response_content_length': 2, | ||
'sentry.op': 'http.client', | ||
'sentry.origin': 'auto.http.browser', | ||
type: 'fetch', | ||
'server.address': 'sentry-test-site.example', | ||
url: 'http://sentry-test-site.example/0?id=123;page=5', | ||
}), | ||
}); | ||
|
||
expect(requestSpan?.data).not.toHaveProperty('http.fragment'); | ||
}); | ||
|
||
sentryTest('strips hash fragment in fetch request spans', async ({ getLocalTestUrl, page }) => { | ||
if (shouldSkipTracingTest()) { | ||
sentryTest.skip(); | ||
} | ||
|
||
await page.route('http://sentry-test-site.example/*', route => route.fulfill({ body: 'ok' })); | ||
|
||
const url = await getLocalTestUrl({ testDir: __dirname }); | ||
|
||
await page.goto(url); | ||
|
||
const txnPromise = waitForTransactionRequest(page); | ||
await page.locator('#btnFragment').click(); | ||
const transactionEvent = envelopeRequestParser(await txnPromise); | ||
|
||
expect(transactionEvent.transaction).toEqual('rootSpan'); | ||
|
||
const requestSpan = transactionEvent.spans?.find(({ op }) => op === 'http.client'); | ||
|
||
expect(requestSpan).toMatchObject({ | ||
description: 'GET http://sentry-test-site.example/1', | ||
parent_span_id: transactionEvent.contexts?.trace?.span_id, | ||
span_id: expect.stringMatching(/[a-f0-9]{16}/), | ||
start_timestamp: expect.any(Number), | ||
timestamp: expect.any(Number), | ||
trace_id: transactionEvent.contexts?.trace?.trace_id, | ||
data: expect.objectContaining({ | ||
'http.method': 'GET', | ||
'http.url': 'http://sentry-test-site.example/1#fragment', | ||
'http.fragment': '#fragment', | ||
'http.response.status_code': 200, | ||
'http.response_content_length': 2, | ||
'sentry.op': 'http.client', | ||
'sentry.origin': 'auto.http.browser', | ||
type: 'fetch', | ||
'server.address': 'sentry-test-site.example', | ||
url: 'http://sentry-test-site.example/1#fragment', | ||
}), | ||
}); | ||
|
||
expect(requestSpan?.data).not.toHaveProperty('http.query'); | ||
}); | ||
|
||
sentryTest('strips hash fragment and query params in fetch request spans', async ({ getLocalTestUrl, page }) => { | ||
if (shouldSkipTracingTest()) { | ||
sentryTest.skip(); | ||
} | ||
|
||
await page.route('http://sentry-test-site.example/*', route => route.fulfill({ body: 'ok' })); | ||
|
||
const url = await getLocalTestUrl({ testDir: __dirname }); | ||
|
||
await page.goto(url); | ||
|
||
const txnPromise = waitForTransactionRequest(page); | ||
await page.locator('#btnQueryFragment').click(); | ||
const transactionEvent = envelopeRequestParser(await txnPromise); | ||
|
||
expect(transactionEvent.transaction).toEqual('rootSpan'); | ||
|
||
const requestSpan = transactionEvent.spans?.find(({ op }) => op === 'http.client'); | ||
|
||
expect(requestSpan).toMatchObject({ | ||
description: 'GET http://sentry-test-site.example/2', | ||
parent_span_id: transactionEvent.contexts?.trace?.span_id, | ||
span_id: expect.stringMatching(/[a-f0-9]{16}/), | ||
start_timestamp: expect.any(Number), | ||
timestamp: expect.any(Number), | ||
trace_id: transactionEvent.contexts?.trace?.trace_id, | ||
data: expect.objectContaining({ | ||
'http.method': 'GET', | ||
'http.url': 'http://sentry-test-site.example/2?id=1#fragment', | ||
'http.query': '?id=1', | ||
'http.fragment': '#fragment', | ||
'http.response.status_code': 200, | ||
'http.response_content_length': 2, | ||
'sentry.op': 'http.client', | ||
'sentry.origin': 'auto.http.browser', | ||
type: 'fetch', | ||
'server.address': 'sentry-test-site.example', | ||
url: 'http://sentry-test-site.example/2?id=1#fragment', | ||
}), | ||
}); | ||
}); | ||
|
||
sentryTest( | ||
'strips hash fragment and query params in same-origin fetch request spans', | ||
async ({ getLocalTestUrl, page }) => { | ||
if (shouldSkipTracingTest()) { | ||
sentryTest.skip(); | ||
} | ||
|
||
await page.route('**/*', route => route.fulfill({ body: 'ok' })); | ||
|
||
const url = await getLocalTestUrl({ testDir: __dirname }); | ||
|
||
await page.goto(url); | ||
|
||
const txnPromise = waitForTransactionRequest(page); | ||
await page.locator('#btnQueryFragmentSameOrigin').click(); | ||
const transactionEvent = envelopeRequestParser(await txnPromise); | ||
|
||
expect(transactionEvent.transaction).toEqual('rootSpan'); | ||
|
||
const requestSpan = transactionEvent.spans?.find(({ op }) => op === 'http.client'); | ||
|
||
expect(requestSpan).toMatchObject({ | ||
description: 'GET /api/users', | ||
parent_span_id: transactionEvent.contexts?.trace?.span_id, | ||
span_id: expect.stringMatching(/[a-f0-9]{16}/), | ||
start_timestamp: expect.any(Number), | ||
timestamp: expect.any(Number), | ||
trace_id: transactionEvent.contexts?.trace?.trace_id, | ||
data: expect.objectContaining({ | ||
'http.method': 'GET', | ||
'http.url': 'http://sentry-test.io/api/users?id=1#fragment', | ||
'http.query': '?id=1', | ||
'http.fragment': '#fragment', | ||
'http.response.status_code': 200, | ||
'http.response_content_length': 2, | ||
'sentry.op': 'http.client', | ||
'sentry.origin': 'auto.http.browser', | ||
type: 'fetch', | ||
'server.address': 'sentry-test.io', | ||
url: '/api/users?id=1#fragment', | ||
}), | ||
}); | ||
}, | ||
); |
11 changes: 11 additions & 0 deletions
11
...ges/browser-integration-tests/suites/tracing/request/xhr-strip-query-and-fragment/init.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import * as Sentry from '@sentry/browser'; | ||
|
||
window.Sentry = Sentry; | ||
|
||
Sentry.init({ | ||
dsn: 'https://[email protected]/1337', | ||
integrations: [Sentry.browserTracingIntegration({ instrumentPageLoad: false, instrumentNavigation: false })], | ||
tracePropagationTargets: ['http://sentry-test-site.example'], | ||
tracesSampleRate: 1, | ||
autoSessionTracking: false, | ||
}); |
29 changes: 29 additions & 0 deletions
29
.../browser-integration-tests/suites/tracing/request/xhr-strip-query-and-fragment/subject.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
function withRootSpan(cb) { | ||
return Sentry.startSpan({ name: 'rootSpan' }, cb); | ||
} | ||
|
||
function makeXHRRequest(url) { | ||
return new Promise((resolve, reject) => { | ||
const xhr = new XMLHttpRequest(); | ||
xhr.open('GET', url); | ||
xhr.onload = () => resolve(xhr.responseText); | ||
xhr.onerror = () => reject(xhr.statusText); | ||
xhr.send(); | ||
}); | ||
} | ||
|
||
document.getElementById('btnQuery').addEventListener('click', async () => { | ||
await withRootSpan(() => makeXHRRequest('http://sentry-test-site.example/0?id=123;page=5')); | ||
}); | ||
|
||
document.getElementById('btnFragment').addEventListener('click', async () => { | ||
await withRootSpan(() => makeXHRRequest('http://sentry-test-site.example/1#fragment')); | ||
}); | ||
|
||
document.getElementById('btnQueryFragment').addEventListener('click', async () => { | ||
await withRootSpan(() => makeXHRRequest('http://sentry-test-site.example/2?id=1#fragment')); | ||
}); | ||
|
||
document.getElementById('btnQueryFragmentSameOrigin').addEventListener('click', async () => { | ||
await withRootSpan(() => makeXHRRequest('/api/users?id=1#fragment')); | ||
}); |
12 changes: 12 additions & 0 deletions
12
...owser-integration-tests/suites/tracing/request/xhr-strip-query-and-fragment/template.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8" /> | ||
</head> | ||
<body> | ||
<button id="btnQuery">Request with query</button> | ||
<button id="btnFragment">Request with fragment</button> | ||
<button id="btnQueryFragment">Request with query and fragment</button> | ||
<button id="btnQueryFragmentSameOrigin">Same origin request with query and fragment</button> | ||
</body> | ||
</html> |
Oops, something went wrong.