Skip to content

Commit

Permalink
ref(core): Use helpers with event envelopes (#4656)
Browse files Browse the repository at this point in the history
This patch converts the events logic in `packages/core/src/request.ts`
to use the recently introduced envelope helpers.

ref: #4587
  • Loading branch information
AbhiPrasad authored Mar 1, 2022
1 parent e0ca11e commit b1009b5
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 35 deletions.
55 changes: 23 additions & 32 deletions packages/core/src/request.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { Event, SdkInfo, SentryRequest, SentryRequestType, Session, SessionAggregates } from '@sentry/types';
import { dsnToString, normalize } from '@sentry/utils';
import {
Event,
EventEnvelope,
EventItem,
SdkInfo,
SentryRequest,
SentryRequestType,
Session,
SessionAggregates,
} from '@sentry/types';
import { createEnvelope, dsnToString, normalize, serializeEnvelope } from '@sentry/utils';

import { APIDetails, getEnvelopeEndpointWithUrlEncodedAuth, getStoreEndpointWithUrlEncodedAuth } from './api';

Expand Down Expand Up @@ -128,39 +137,21 @@ export function eventToSentryRequest(event: Event, api: APIDetails): SentryReque
// deserialization. Instead, we only implement a minimal subset of the spec to
// serialize events inline here.
if (useEnvelope) {
const envelopeHeaders = JSON.stringify({
event_id: event.event_id,
const envelopeHeaders = {
event_id: event.event_id as string,
sent_at: new Date().toISOString(),
...(sdkInfo && { sdk: sdkInfo }),
...(!!api.tunnel && { dsn: dsnToString(api.dsn) }),
});
const itemHeaders = JSON.stringify({
type: eventType,

// TODO: Right now, sampleRate may or may not be defined (it won't be in the cases of inheritance and
// explicitly-set sampling decisions). Are we good with that?
sample_rates: [{ id: samplingMethod, rate: sampleRate }],

// The content-type is assumed to be 'application/json' and not part of
// the current spec for transaction items, so we don't bloat the request
// body with it.
//
// content_type: 'application/json',
//
// The length is optional. It must be the number of bytes in req.Body
// encoded as UTF-8. Since the server can figure this out and would
// otherwise refuse events that report the length incorrectly, we decided
// not to send the length to avoid problems related to reporting the wrong
// size and to reduce request body size.
//
// length: new TextEncoder().encode(req.body).length,
});
// The trailing newline is optional. We intentionally don't send it to avoid
// sending unnecessary bytes.
//
// const envelope = `${envelopeHeaders}\n${itemHeaders}\n${req.body}\n`;
const envelope = `${envelopeHeaders}\n${itemHeaders}\n${req.body}`;
req.body = envelope;
};
const eventItem: EventItem = [
{
type: eventType,
sample_rates: [{ id: samplingMethod, rate: sampleRate }],
},
req.body,
];
const envelope = createEnvelope<EventEnvelope>(envelopeHeaders, [eventItem]);
req.body = serializeEnvelope(envelope);
}

return req;
Expand Down
11 changes: 9 additions & 2 deletions packages/types/src/envelope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ClientReport } from './clientreport';
import { Event } from './event';
import { SdkInfo } from './sdkinfo';
import { Session, SessionAggregates } from './session';
import { TransactionSamplingMethod } from './transaction';
import { UserFeedback } from './user';

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

type EventItemHeaders = { type: 'event' | 'transaction' };
type EventItemHeaders = {
type: 'event' | 'transaction';
sample_rates: [{ id?: TransactionSamplingMethod; rate?: number }];
};
type AttachmentItemHeaders = { type: 'attachment'; filename: string };
type UserFeedbackItemHeaders = { type: 'user_report' };
type SessionItemHeaders = { type: 'session' };
type SessionAggregatesItemHeaders = { type: 'sessions' };
type ClientReportItemHeaders = { type: 'client_report' };

export type EventItem = BaseEnvelopeItem<EventItemHeaders, Event>;
// TODO(v7): Remove the string union from `Event | string`
// We have to allow this hack for now as we pre-serialize events because we support
// both store and envelope endpoints.
export type EventItem = BaseEnvelopeItem<EventItemHeaders, Event | string>;
export type AttachmentItem = BaseEnvelopeItem<AttachmentItemHeaders, unknown>;
export type UserFeedbackItem = BaseEnvelopeItem<UserFeedbackItemHeaders, UserFeedback>;
export type SessionItem =
Expand Down
6 changes: 5 additions & 1 deletion packages/utils/src/envelope.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Envelope } from '@sentry/types';

import { isPrimitive } from './is';

/**
* Creates an envelope.
* Make sure to always explicitly provide the generic to this function
Expand Down Expand Up @@ -33,6 +35,8 @@ export function serializeEnvelope(envelope: Envelope): string {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (items as any[]).reduce((acc, item: typeof items[number]) => {
const [itemHeaders, payload] = item;
return `${acc}\n${JSON.stringify(itemHeaders)}\n${JSON.stringify(payload)}`;
// We do not serialize payloads that are primitives
const serializedPayload = isPrimitive(payload) ? String(payload) : JSON.stringify(payload);
return `${acc}\n${JSON.stringify(itemHeaders)}\n${serializedPayload}`;
}, serializedHeaders);
}

0 comments on commit b1009b5

Please sign in to comment.