Skip to content

Commit 209df9c

Browse files
committed
ref(core): Use helpers with event envelopes (#4656)
This patch converts the events logic in `packages/core/src/request.ts` to use the recently introduced envelope helpers. ref: #4587
1 parent aa845d1 commit 209df9c

File tree

3 files changed

+27
-43
lines changed

3 files changed

+27
-43
lines changed

packages/core/src/request.ts

Lines changed: 13 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,4 @@
1-
import {
2-
Event,
3-
SdkInfo,
4-
SentryRequest,
5-
SentryRequestType,
6-
Session,
7-
SessionAggregates,
8-
SessionEnvelope,
9-
SessionItem,
10-
} from '@sentry/types';
1+
import { Event, SdkInfo, SentryRequest, Session, SessionAggregates, SessionEnvelope, SessionItem } from '@sentry/types';
112
import { createEnvelope, dsnToString, normalize, serializeEnvelope } from '@sentry/utils';
123

134
import { APIDetails, getEnvelopeEndpointWithUrlEncodedAuth, getStoreEndpointWithUrlEncodedAuth } from './api';
@@ -138,39 +129,21 @@ export function eventToSentryRequest(event: Event, api: APIDetails): SentryReque
138129
// deserialization. Instead, we only implement a minimal subset of the spec to
139130
// serialize events inline here.
140131
if (useEnvelope) {
141-
const envelopeHeaders = JSON.stringify({
142-
event_id: event.event_id,
132+
const envelopeHeaders = {
133+
event_id: event.event_id as string,
143134
sent_at: new Date().toISOString(),
144135
...(sdkInfo && { sdk: sdkInfo }),
145136
...(!!api.tunnel && { dsn: dsnToString(api.dsn) }),
146-
});
147-
const itemHeaders = JSON.stringify({
148-
type: eventType,
149-
150-
// TODO: Right now, sampleRate may or may not be defined (it won't be in the cases of inheritance and
151-
// explicitly-set sampling decisions). Are we good with that?
152-
sample_rates: [{ id: samplingMethod, rate: sampleRate }],
153-
154-
// The content-type is assumed to be 'application/json' and not part of
155-
// the current spec for transaction items, so we don't bloat the request
156-
// body with it.
157-
//
158-
// content_type: 'application/json',
159-
//
160-
// The length is optional. It must be the number of bytes in req.Body
161-
// encoded as UTF-8. Since the server can figure this out and would
162-
// otherwise refuse events that report the length incorrectly, we decided
163-
// not to send the length to avoid problems related to reporting the wrong
164-
// size and to reduce request body size.
165-
//
166-
// length: new TextEncoder().encode(req.body).length,
167-
});
168-
// The trailing newline is optional. We intentionally don't send it to avoid
169-
// sending unnecessary bytes.
170-
//
171-
// const envelope = `${envelopeHeaders}\n${itemHeaders}\n${req.body}\n`;
172-
const envelope = `${envelopeHeaders}\n${itemHeaders}\n${req.body}`;
173-
req.body = envelope;
137+
};
138+
const eventItem: EventItem = [
139+
{
140+
type: eventType,
141+
sample_rates: [{ id: samplingMethod, rate: sampleRate }],
142+
},
143+
req.body,
144+
];
145+
const envelope = createEnvelope<EventEnvelope>(envelopeHeaders, [eventItem]);
146+
req.body = serializeEnvelope(envelope);
174147
}
175148

176149
return req;

packages/types/src/envelope.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ClientReport } from './clientreport';
22
import { Event } from './event';
33
import { SdkInfo } from './sdkinfo';
44
import { Session, SessionAggregates } from './session';
5+
import { TransactionSamplingMethod } from './transaction';
56
import { UserFeedback } from './user';
67

78
// Based on: https://develop.sentry.dev/sdk/envelopes/
@@ -25,14 +26,20 @@ type BaseEnvelope<EH extends BaseEnvelopeHeaders, I extends BaseEnvelopeItem<Bas
2526
I[],
2627
];
2728

28-
type EventItemHeaders = { type: 'event' | 'transaction' };
29+
type EventItemHeaders = {
30+
type: 'event' | 'transaction';
31+
sample_rates: [{ id?: TransactionSamplingMethod; rate?: number }];
32+
};
2933
type AttachmentItemHeaders = { type: 'attachment'; filename: string };
3034
type UserFeedbackItemHeaders = { type: 'user_report' };
3135
type SessionItemHeaders = { type: 'session' };
3236
type SessionAggregatesItemHeaders = { type: 'sessions' };
3337
type ClientReportItemHeaders = { type: 'client_report' };
3438

35-
export type EventItem = BaseEnvelopeItem<EventItemHeaders, Event>;
39+
// TODO(v7): Remove the string union from `Event | string`
40+
// We have to allow this hack for now as we pre-serialize events because we support
41+
// both store and envelope endpoints.
42+
export type EventItem = BaseEnvelopeItem<EventItemHeaders, Event | string>;
3643
export type AttachmentItem = BaseEnvelopeItem<AttachmentItemHeaders, unknown>;
3744
export type UserFeedbackItem = BaseEnvelopeItem<UserFeedbackItemHeaders, UserFeedback>;
3845
export type SessionItem =

packages/utils/src/envelope.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { Envelope } from '@sentry/types';
22

3+
import { isPrimitive } from './is';
4+
35
/**
46
* Creates an envelope.
57
* Make sure to always explicitly provide the generic to this function
@@ -33,6 +35,8 @@ export function serializeEnvelope(envelope: Envelope): string {
3335
// eslint-disable-next-line @typescript-eslint/no-explicit-any
3436
return (items as any[]).reduce((acc, item: typeof items[number]) => {
3537
const [itemHeaders, payload] = item;
36-
return `${acc}\n${JSON.stringify(itemHeaders)}\n${JSON.stringify(payload)}`;
38+
// We do not serialize payloads that are primitives
39+
const serializedPayload = isPrimitive(payload) ? String(payload) : JSON.stringify(payload);
40+
return `${acc}\n${JSON.stringify(itemHeaders)}\n${serializedPayload}`;
3741
}, serializedHeaders);
3842
}

0 commit comments

Comments
 (0)