-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(utils): Introduce envelope helper functions #4587
Conversation
size-limit report
|
This patch introduces functions that create, mutate and serialize envelopes. It also adds some basic unit tests that sanity check their functionality. It builds on top of the work done in #4527. Users are expected to not directly interact with the Envelope instance, but instead use the helper functions to work with them. Essentially, we can treat the envelope instance as an opaque handle, similar to how void pointers are used in low-level languages. This was done to minimize the bundle impact of working with the envelopes, and as the set of possible envelope operations was fixed (and on the smaller end). To directly create an envelope, the `createEnvelope()` function was introduced. Users are encouraged to explicitly provide the generic type arg to this function so that add headers/items are typed accordingly. To add headers and items to envelopes, the `addHeaderToEnvelope()` and `addItemToEnvelope()` functions are exposed respectively. The reason that these functions are purely additive (or in the case of headers, can re-write existing ones), instead of allow for headers/items to be removed, is that removal functionality doesn't seem like it'll be used at all. In the interest of keeping the API surface small, we settled with these two functions, but we can come back and adjust this later on. Finally, there is `serializeEnvelope()`, which is used to serialize an envelope to a string. It does have some TypeScript complications, which is explained in detail in a code comment, but otherwise is a pretty simple implementation. You can notice the power of the tuple based envelope implementation, where it becomes easy to access headers/items. ```js const [headers, items] = envelope; ``` To illustrate how these functions will be used, another patch will be added that adds a `createClientReportEnvelope()` util, and the base transport in `@sentry/browser` will be updated to use that util.
518332c
to
b342328
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few comments, but overall looks good!
packages/utils/src/envelope.ts
Outdated
* Make sure to always explicitly provide the generic to this function | ||
* so that the envelope types resolve correctly. | ||
*/ | ||
export function createEnvelope<E extends Envelope>(headers: E[0], items: E[1]): E { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
export function createEnvelope<E extends Envelope>(headers: E[0], items: E[1]): E { | |
export function createEnvelope<E extends Envelope>(headers: E[0], items: E[1] = []): E { |
Obviously it doesn't make a ton of sense for someone to make an empty envelope, but just in case...
(This protects against return [headers, [...items, newItem]] as E;
in addItemToEnvelope
crashing if someone were to create an empty envelope since, stupidly, you can do {...undefined}
but not [...undefined]
.)
// Have to cast items to any here since Envelope is a union type | ||
// Fixed in Typescript 4.2 | ||
// TODO: Remove any[] cast when we upgrade to TS 4.2 | ||
// https://github.com/microsoft/TypeScript/issues/36390 | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After #4609, is this workaround still necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, as items is still a union type.
export function parseEnvelope(env: string): Array<Record<any, any>> { | ||
return env.split('\n').map(e => JSON.parse(e)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, we have such a function already if you want to use it:
sentry-javascript/packages/core/test/lib/request.test.ts
Lines 22 to 30 in bb6f865
function parseEnvelopeRequest(request: SentryRequest): any { | |
const [envelopeHeaderString, itemHeaderString, eventString] = request.body.split('\n'); | |
return { | |
envelopeHeader: JSON.parse(envelopeHeaderString), | |
itemHeader: JSON.parse(itemHeaderString), | |
event: JSON.parse(eventString), | |
}; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll leave it like this because this works with multiple envelope items - doesn't just assume a single one. Useful for when we expand the tests in the future.
This patch converts the sessions logic in `packages/core/src/request.ts` to use the recently introduced envelope helpers. ref: #4587
This patch converts the events logic in `packages/core/src/request.ts` to use the recently introduced envelope helpers. ref: #4587
This patch converts the events logic in `packages/core/src/request.ts` to use the recently introduced envelope helpers. ref: #4587
This patch converts the events logic in `packages/core/src/request.ts` to use the recently introduced envelope helpers. ref: #4587
This patch converts the sessions logic in `packages/core/src/request.ts` to use the recently introduced envelope helpers. ref: #4587
This patch converts the sessions logic in `packages/core/src/request.ts` to use the recently introduced envelope helpers. ref: #4587
This patch introduces functions that create, mutate and serialize
envelopes. It also adds some basic unit tests that sanity check their
functionality. It builds on top of the work done in
#4527.
Users are expected to not directly interact with the Envelope instance,
but instead use the helper functions to work with them. Essentially, we
can treat the envelope instance as an opaque handle, similar to how void
pointers are used in low-level languages. This was done to minimize the
bundle impact of working with the envelopes, and as the set of possible
envelope operations was fixed (and on the smaller end).
To directly create an envelope, the
createEnvelope()
function wasintroduced. Users are encouraged to explicitly provide the generic type
arg to this function so that headers/items are typed accordingly.
To add items to envelopes, the
addItemToEnvelope()
functions is exposed.In the interest of keeping the API surface small, we settled with just this one
function, but we can come back and change it later on.
Finally, there is
serializeEnvelope()
, which is used to serialize anenvelope to a string. It does have some TypeScript complications, which
are explained in detail in a code comment, but otherwise is a pretty
simple implementation. You can notice the power of the tuple based
envelope implementation, where it becomes easy to access headers/items.
To illustrate how these functions will be used, another patch will be
added that adds a
createClientReportEnvelope()
util, and the basetransport in
@sentry/browser
will be updated to use that util.Edit: See that PR right here: #4588
Resolves https://getsentry.atlassian.net/browse/WEB-558