-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(browser): Add new v7 Fetch Transport (#4765)
This PR creates the new v7 Fetch Transport, and updates the browser backend to use the new transport. To configure the transport, users can supply `requestOptions`, which is supplied to the fetch request. This consolidates the earlier pattern of passing in both headers and fetchParameters that the old fetch transport used to use.
- Loading branch information
1 parent
4ab3abb
commit 249302a
Showing
9 changed files
with
203 additions
and
4 deletions.
There are no files selected for viewing
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
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 |
---|---|---|
@@ -1,3 +1,5 @@ | ||
export { BaseTransport } from './base'; | ||
export { FetchTransport } from './fetch'; | ||
export { XHRTransport } from './xhr'; | ||
|
||
export { makeNewFetchTransport } from './new-fetch'; |
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,44 @@ | ||
import { | ||
BaseTransportOptions, | ||
createTransport, | ||
NewTransport, | ||
TransportMakeRequestResponse, | ||
TransportRequest, | ||
} from '@sentry/core'; | ||
|
||
import { FetchImpl, getNativeFetchImplementation } from './utils'; | ||
|
||
export interface FetchTransportOptions extends BaseTransportOptions { | ||
requestOptions?: RequestInit; | ||
} | ||
|
||
/** | ||
* Creates a Transport that uses the Fetch API to send events to Sentry. | ||
*/ | ||
export function makeNewFetchTransport( | ||
options: FetchTransportOptions, | ||
nativeFetch: FetchImpl = getNativeFetchImplementation(), | ||
): NewTransport { | ||
function makeRequest(request: TransportRequest): PromiseLike<TransportMakeRequestResponse> { | ||
const requestOptions: RequestInit = { | ||
body: request.body, | ||
method: 'POST', | ||
referrerPolicy: 'origin', | ||
...options.requestOptions, | ||
}; | ||
|
||
return nativeFetch(options.url, requestOptions).then(response => { | ||
return response.text().then(body => ({ | ||
body, | ||
headers: { | ||
'x-sentry-rate-limits': response.headers.get('X-Sentry-Rate-Limits'), | ||
'retry-after': response.headers.get('Retry-After'), | ||
}, | ||
reason: response.statusText, | ||
statusCode: response.status, | ||
})); | ||
}); | ||
} | ||
|
||
return createTransport({ bufferSize: options.bufferSize }, makeRequest); | ||
} |
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,98 @@ | ||
import { EventEnvelope, EventItem } from '@sentry/types'; | ||
import { createEnvelope, serializeEnvelope } from '@sentry/utils'; | ||
|
||
import { FetchTransportOptions, makeNewFetchTransport } from '../../../src/transports/new-fetch'; | ||
import { FetchImpl } from '../../../src/transports/utils'; | ||
|
||
const DEFAULT_FETCH_TRANSPORT_OPTIONS: FetchTransportOptions = { | ||
url: 'https://sentry.io/api/42/store/?sentry_key=123&sentry_version=7', | ||
}; | ||
|
||
const ERROR_ENVELOPE = createEnvelope<EventEnvelope>({ event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', sent_at: '123' }, [ | ||
[{ type: 'event' }, { event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2' }] as EventItem, | ||
]); | ||
|
||
class Headers { | ||
headers: { [key: string]: string } = {}; | ||
get(key: string) { | ||
return this.headers[key] || null; | ||
} | ||
set(key: string, value: string) { | ||
this.headers[key] = value; | ||
} | ||
} | ||
|
||
describe('NewFetchTransport', () => { | ||
it('calls fetch with the given URL', async () => { | ||
const mockFetch = jest.fn(() => | ||
Promise.resolve({ | ||
headers: new Headers(), | ||
status: 200, | ||
text: () => Promise.resolve({}), | ||
}), | ||
) as unknown as FetchImpl; | ||
const transport = makeNewFetchTransport(DEFAULT_FETCH_TRANSPORT_OPTIONS, mockFetch); | ||
|
||
expect(mockFetch).toHaveBeenCalledTimes(0); | ||
const res = await transport.send(ERROR_ENVELOPE); | ||
expect(mockFetch).toHaveBeenCalledTimes(1); | ||
|
||
expect(res.status).toBe('success'); | ||
|
||
expect(mockFetch).toHaveBeenLastCalledWith(DEFAULT_FETCH_TRANSPORT_OPTIONS.url, { | ||
body: serializeEnvelope(ERROR_ENVELOPE), | ||
method: 'POST', | ||
referrerPolicy: 'origin', | ||
}); | ||
}); | ||
|
||
it('sets rate limit headers', async () => { | ||
const headers = { | ||
get: jest.fn(), | ||
}; | ||
|
||
const mockFetch = jest.fn(() => | ||
Promise.resolve({ | ||
headers, | ||
status: 200, | ||
text: () => Promise.resolve({}), | ||
}), | ||
) as unknown as FetchImpl; | ||
const transport = makeNewFetchTransport(DEFAULT_FETCH_TRANSPORT_OPTIONS, mockFetch); | ||
|
||
expect(headers.get).toHaveBeenCalledTimes(0); | ||
await transport.send(ERROR_ENVELOPE); | ||
|
||
expect(headers.get).toHaveBeenCalledTimes(2); | ||
expect(headers.get).toHaveBeenCalledWith('X-Sentry-Rate-Limits'); | ||
expect(headers.get).toHaveBeenCalledWith('Retry-After'); | ||
}); | ||
|
||
it('allows for custom options to be passed in', async () => { | ||
const mockFetch = jest.fn(() => | ||
Promise.resolve({ | ||
headers: new Headers(), | ||
status: 200, | ||
text: () => Promise.resolve({}), | ||
}), | ||
) as unknown as FetchImpl; | ||
|
||
const REQUEST_OPTIONS: RequestInit = { | ||
referrerPolicy: 'strict-origin', | ||
keepalive: true, | ||
referrer: 'http://example.org', | ||
}; | ||
|
||
const transport = makeNewFetchTransport( | ||
{ ...DEFAULT_FETCH_TRANSPORT_OPTIONS, requestOptions: REQUEST_OPTIONS }, | ||
mockFetch, | ||
); | ||
|
||
await transport.send(ERROR_ENVELOPE); | ||
expect(mockFetch).toHaveBeenLastCalledWith(DEFAULT_FETCH_TRANSPORT_OPTIONS.url, { | ||
body: serializeEnvelope(ERROR_ENVELOPE), | ||
method: 'POST', | ||
...REQUEST_OPTIONS, | ||
}); | ||
}); | ||
}); |
1 change: 1 addition & 0 deletions
1
packages/integration-tests/suites/new-transports/fetch-captureException/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 @@ | ||
Sentry.captureException(new Error('this is an error')); |
21 changes: 21 additions & 0 deletions
21
packages/integration-tests/suites/new-transports/fetch-captureException/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,21 @@ | ||
import { expect } from '@playwright/test'; | ||
import { Event } from '@sentry/types'; | ||
|
||
import { sentryTest } from '../../../utils/fixtures'; | ||
import { getFirstSentryEnvelopeRequest } from '../../../utils/helpers'; | ||
|
||
sentryTest('should capture an error with the new fetch transport', async ({ getLocalTestPath, page }) => { | ||
const url = await getLocalTestPath({ testDir: __dirname }); | ||
|
||
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url); | ||
|
||
expect(eventData.exception?.values).toHaveLength(1); | ||
expect(eventData.exception?.values?.[0]).toMatchObject({ | ||
type: 'Error', | ||
value: 'this is an error', | ||
mechanism: { | ||
type: 'generic', | ||
handled: true, | ||
}, | ||
}); | ||
}); |
2 changes: 2 additions & 0 deletions
2
packages/integration-tests/suites/new-transports/fetch-startTransaction/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,2 @@ | ||
const transaction = Sentry.startTransaction({ name: 'test_transaction_1' }); | ||
transaction.finish(); |
13 changes: 13 additions & 0 deletions
13
packages/integration-tests/suites/new-transports/fetch-startTransaction/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,13 @@ | ||
import { expect } from '@playwright/test'; | ||
import { Event } from '@sentry/types'; | ||
|
||
import { sentryTest } from '../../../utils/fixtures'; | ||
import { getFirstSentryEnvelopeRequest } from '../../../utils/helpers'; | ||
|
||
sentryTest('should report a transaction with the new fetch transport', async ({ getLocalTestPath, page }) => { | ||
const url = await getLocalTestPath({ testDir: __dirname }); | ||
const transaction = await getFirstSentryEnvelopeRequest<Event>(page, url); | ||
|
||
expect(transaction.transaction).toBe('test_transaction_1'); | ||
expect(transaction.spans).toBeDefined(); | ||
}); |
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,13 @@ | ||
import * as Sentry from '@sentry/browser'; | ||
// eslint-disable-next-line no-unused-vars | ||
import * as _ from '@sentry/tracing'; | ||
|
||
window.Sentry = Sentry; | ||
|
||
Sentry.init({ | ||
dsn: 'https://public@dsn.ingest.sentry.io/1337', | ||
_experiments: { | ||
newTransport: true, | ||
}, | ||
tracesSampleRate: 1.0, | ||
}); |