From 24240e96da514dd8cfac5582dd9b4590f38c3aea Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 15 Feb 2022 18:38:48 -0500 Subject: [PATCH 01/13] feat(utils): Introduce envelope helper functions 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 https://github.com/getsentry/sentry-javascript/pull/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. --- packages/utils/src/envelope.ts | 48 ++++++++++++++++++++++++++++ packages/utils/src/index.ts | 1 + packages/utils/test/envelope.test.ts | 42 ++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 packages/utils/src/envelope.ts create mode 100644 packages/utils/test/envelope.test.ts diff --git a/packages/utils/src/envelope.ts b/packages/utils/src/envelope.ts new file mode 100644 index 000000000000..8ba572fa5779 --- /dev/null +++ b/packages/utils/src/envelope.ts @@ -0,0 +1,48 @@ +import { Envelope } from '@sentry/types'; + +/** + * Creates an envelope. + * Make sure to always explicitly provide the generic to this function + * so that the envelope types resolve correctly. + */ +export function createEnvelope(headers: E[0], items: E[1]): E { + return [headers, items] as E; +} + +/** + * Add a set of key value pairs to the envelope header. + * Make sure to always explicitly provide the generic to this function + * so that the envelope types resolve correctly. + */ +export function addHeaderToEnvelope(envelope: E, newHeaders: E[0]): E { + const [headers, items] = envelope; + return [{ ...headers, ...newHeaders }, items] as E; +} + +/** + * Add an item to an envelope. + * Make sure to always explicitly provide the generic to this function + * so that the envelope types resolve correctly. + */ +export function addItemToEnvelope(envelope: E, newItem: E[1][number]): E { + const [headers, items] = envelope; + return [headers, [...items, newItem]] as E; +} + +/** + * Serializes an envelope into a string. + */ +export function serializeEnvelope(envelope: Envelope): string { + const [headers, items] = envelope; + const serializedHeaders = JSON.stringify(headers); + + // 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 + return (items as any[]).reduce((acc, item: typeof items[number]) => { + const [itemHeaders, payload] = item; + return `${acc}\n${JSON.stringify(itemHeaders)}\n${JSON.stringify(payload)}`; + }, serializedHeaders); +} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 900e50653037..511d8a1315ca 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -21,3 +21,4 @@ export * from './supports'; export * from './syncpromise'; export * from './time'; export * from './env'; +export * from './envelope'; diff --git a/packages/utils/test/envelope.test.ts b/packages/utils/test/envelope.test.ts new file mode 100644 index 000000000000..451ca00ff1c8 --- /dev/null +++ b/packages/utils/test/envelope.test.ts @@ -0,0 +1,42 @@ +import { createEnvelope, addHeaderToEnvelope, addItemToEnvelope, serializeEnvelope } from '../src/envelope'; +import { EventEnvelope } from '@sentry/types'; + +describe('envelope', () => { + describe('createEnvelope()', () => { + const testTable: Array<[string, Parameters[0], Parameters[1]]> = [ + ['creates an empty envelope', {}, []], + ['creates an envelope with a header but no items', { dsn: 'https://public@example.com/1', sdk: {} }, []], + ]; + it.each(testTable)('%s', (_: string, headers, items) => { + const env = createEnvelope(headers, items); + expect(env).toHaveLength(2); + expect(env[0]).toStrictEqual(headers); + expect(env[1]).toStrictEqual(items); + }); + }); + + describe('addHeaderToEnvelope()', () => { + it('adds a header to the envelope', () => { + const env = createEnvelope({}, []); + expect(serializeEnvelope(env)).toMatchInlineSnapshot(`"{}"`); + const newEnv = addHeaderToEnvelope(env, { dsn: 'https://public@example.com/' }); + expect(serializeEnvelope(newEnv)).toMatchInlineSnapshot(`"{\\"dsn\\":\\"https://public@example.com/\\"}"`); + }); + }); + + describe('addItemToEnvelope()', () => { + const env = createEnvelope({ event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', sent_at: '123' }, []); + expect(serializeEnvelope(env)).toMatchInlineSnapshot( + `"{\\"event_id\\":\\"aa3ff046696b4bc6b609ce6d28fde9e2\\",\\"sent_at\\":\\"123\\"}"`, + ); + const newEnv = addItemToEnvelope(env, [ + { type: 'event' }, + { event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2' }, + ]); + expect(serializeEnvelope(newEnv)).toMatchInlineSnapshot(` + "{\\"event_id\\":\\"aa3ff046696b4bc6b609ce6d28fde9e2\\",\\"sent_at\\":\\"123\\"} + {\\"type\\":\\"event\\"} + {\\"event_id\\":\\"aa3ff046696b4bc6b609ce6d28fde9e2\\"}" + `); + }); +}); From b3423284c9608dbcd84e724773e06e25be5490cd Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 15 Feb 2022 19:36:39 -0500 Subject: [PATCH 02/13] yarn fix lint --- packages/utils/src/envelope.ts | 10 ---------- packages/utils/test/envelope.test.ts | 3 ++- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/utils/src/envelope.ts b/packages/utils/src/envelope.ts index 8ba572fa5779..0b06d3b266fe 100644 --- a/packages/utils/src/envelope.ts +++ b/packages/utils/src/envelope.ts @@ -9,16 +9,6 @@ export function createEnvelope(headers: E[0], items: E[1]): return [headers, items] as E; } -/** - * Add a set of key value pairs to the envelope header. - * Make sure to always explicitly provide the generic to this function - * so that the envelope types resolve correctly. - */ -export function addHeaderToEnvelope(envelope: E, newHeaders: E[0]): E { - const [headers, items] = envelope; - return [{ ...headers, ...newHeaders }, items] as E; -} - /** * Add an item to an envelope. * Make sure to always explicitly provide the generic to this function diff --git a/packages/utils/test/envelope.test.ts b/packages/utils/test/envelope.test.ts index 451ca00ff1c8..e6f66e492c0d 100644 --- a/packages/utils/test/envelope.test.ts +++ b/packages/utils/test/envelope.test.ts @@ -1,6 +1,7 @@ -import { createEnvelope, addHeaderToEnvelope, addItemToEnvelope, serializeEnvelope } from '../src/envelope'; import { EventEnvelope } from '@sentry/types'; +import { addHeaderToEnvelope, addItemToEnvelope, createEnvelope, serializeEnvelope } from '../src/envelope'; + describe('envelope', () => { describe('createEnvelope()', () => { const testTable: Array<[string, Parameters[0], Parameters[1]]> = [ From d7d551ee2d181a2e27c1bec408ef71140f3507da Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 23 Feb 2022 09:27:22 -0500 Subject: [PATCH 03/13] update tests --- packages/utils/test/envelope.test.ts | 44 +++++++++++++++------------- packages/utils/test/testutils.ts | 4 +++ 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/packages/utils/test/envelope.test.ts b/packages/utils/test/envelope.test.ts index e6f66e492c0d..64cdbe5e39ca 100644 --- a/packages/utils/test/envelope.test.ts +++ b/packages/utils/test/envelope.test.ts @@ -1,6 +1,7 @@ import { EventEnvelope } from '@sentry/types'; -import { addHeaderToEnvelope, addItemToEnvelope, createEnvelope, serializeEnvelope } from '../src/envelope'; +import { addItemToEnvelope, createEnvelope, serializeEnvelope } from '../src/envelope'; +import { parseEnvelope } from './testutils'; describe('envelope', () => { describe('createEnvelope()', () => { @@ -16,28 +17,31 @@ describe('envelope', () => { }); }); - describe('addHeaderToEnvelope()', () => { - it('adds a header to the envelope', () => { - const env = createEnvelope({}, []); - expect(serializeEnvelope(env)).toMatchInlineSnapshot(`"{}"`); - const newEnv = addHeaderToEnvelope(env, { dsn: 'https://public@example.com/' }); - expect(serializeEnvelope(newEnv)).toMatchInlineSnapshot(`"{\\"dsn\\":\\"https://public@example.com/\\"}"`); + describe('serializeEnvelope()', () => { + it('serializes an envelope', () => { + const env = createEnvelope({ event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', sent_at: '123' }, []); + expect(serializeEnvelope(env)).toMatchInlineSnapshot( + `"{\\"event_id\\":\\"aa3ff046696b4bc6b609ce6d28fde9e2\\",\\"sent_at\\":\\"123\\"}"`, + ); }); }); describe('addItemToEnvelope()', () => { - const env = createEnvelope({ event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', sent_at: '123' }, []); - expect(serializeEnvelope(env)).toMatchInlineSnapshot( - `"{\\"event_id\\":\\"aa3ff046696b4bc6b609ce6d28fde9e2\\",\\"sent_at\\":\\"123\\"}"`, - ); - const newEnv = addItemToEnvelope(env, [ - { type: 'event' }, - { event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2' }, - ]); - expect(serializeEnvelope(newEnv)).toMatchInlineSnapshot(` - "{\\"event_id\\":\\"aa3ff046696b4bc6b609ce6d28fde9e2\\",\\"sent_at\\":\\"123\\"} - {\\"type\\":\\"event\\"} - {\\"event_id\\":\\"aa3ff046696b4bc6b609ce6d28fde9e2\\"}" - `); + it('adds an item to an envelope', () => { + const env = createEnvelope({ event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', sent_at: '123' }, []); + const parsedEnvelope = parseEnvelope(serializeEnvelope(env)); + expect(parsedEnvelope).toHaveLength(1); + expect(parsedEnvelope[0]).toEqual({ event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', sent_at: '123' }); + + const newEnv = addItemToEnvelope(env, [ + { type: 'event' }, + { event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2' }, + ]); + const parsedNewEnvelope = parseEnvelope(serializeEnvelope(newEnv)); + expect(parsedNewEnvelope).toHaveLength(3); + expect(parsedNewEnvelope[0]).toEqual({ event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2', sent_at: '123' }); + expect(parsedNewEnvelope[1]).toEqual({ type: 'event' }); + expect(parsedNewEnvelope[2]).toEqual({ event_id: 'aa3ff046696b4bc6b609ce6d28fde9e2' }); + }); }); }); diff --git a/packages/utils/test/testutils.ts b/packages/utils/test/testutils.ts index 6130ee7ca365..aa3c5485eec1 100644 --- a/packages/utils/test/testutils.ts +++ b/packages/utils/test/testutils.ts @@ -11,3 +11,7 @@ export const testOnlyIfNodeVersionAtLeast = (minVersion: number): jest.It => { return it; }; + +export function parseEnvelope(env: string): Array> { + return env.split('\n').map(e => JSON.parse(e)); +} From 7fe5ed1964747310e66f65c4858bdb3352e725f5 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Thu, 24 Feb 2022 14:27:15 -0500 Subject: [PATCH 04/13] dont export base types --- packages/types/src/envelope.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/types/src/envelope.ts b/packages/types/src/envelope.ts index 2a70cea96667..aa7655db9cea 100644 --- a/packages/types/src/envelope.ts +++ b/packages/types/src/envelope.ts @@ -18,12 +18,12 @@ export type BaseEnvelopeItemHeaders = { length?: number; }; -export type BaseEnvelopeItem = [IH, P]; // P is for payload +type BaseEnvelopeItem = [IH, P]; // P is for payload -export type BaseEnvelope< - EH extends BaseEnvelopeHeaders, - I extends BaseEnvelopeItem, -> = [EH, I[]]; +type BaseEnvelope> = [ + EH, + I[], +]; type EventItemHeaders = { type: 'event' | 'transaction' }; type AttachmentItemHeaders = { type: 'attachment'; filename: string }; From a4b5541998d7beca8a91216ffa5a2375127d1c62 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Thu, 24 Feb 2022 14:34:35 -0500 Subject: [PATCH 05/13] fix import --- packages/types/src/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 996f53c4c685..13651b7cd78e 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -6,9 +6,7 @@ export { DsnComponents, DsnLike, DsnProtocol } from './dsn'; export { DebugImage, DebugImageType, DebugMeta } from './debugMeta'; export { AttachmentItem, - BaseEnvelope, BaseEnvelopeHeaders, - BaseEnvelopeItem, BaseEnvelopeItemHeaders, ClientReportEnvelope, ClientReportItem, From 6b5f172c466dd411ac206b00b07eaad27c2629a3 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 15 Feb 2022 18:49:05 -0500 Subject: [PATCH 06/13] ref(browser): Introduce client reports envelope helper Leverage the new envelope utility functions to construct client report envelopes sent in the browser transport. This also opens us up to more easily add client reports to node or other environments. --- packages/browser/src/transports/base.ts | 34 +++++++-------- packages/utils/src/clientreports.ts | 25 ++++++++++++ packages/utils/src/index.ts | 1 + packages/utils/test/clientreports.test.ts | 50 +++++++++++++++++++++++ 4 files changed, 91 insertions(+), 19 deletions(-) create mode 100644 packages/utils/src/clientreports.ts create mode 100644 packages/utils/test/clientreports.test.ts diff --git a/packages/browser/src/transports/base.ts b/packages/browser/src/transports/base.ts index 6d7651a02423..4a6daf5556bb 100644 --- a/packages/browser/src/transports/base.ts +++ b/packages/browser/src/transports/base.ts @@ -7,6 +7,7 @@ import { sessionToSentryRequest, } from '@sentry/core'; import { + ClientReportEnvelopeItemPayload, Event, Outcome, Response as SentryResponse, @@ -17,7 +18,7 @@ import { TransportOptions, } from '@sentry/types'; import { - dateTimestampInSeconds, + createClientReportEnvelope, dsnToString, eventStatusFromHttpCode, getGlobalObject, @@ -26,6 +27,7 @@ import { makePromiseBuffer, parseRetryAfterHeader, PromiseBuffer, + serializeEnvelope, } from '@sentry/utils'; import { sendReport } from './utils'; @@ -127,26 +129,20 @@ export abstract class BaseTransport implements Transport { logger.log(`Flushing outcomes:\n${JSON.stringify(outcomes, null, 2)}`); const url = getEnvelopeEndpointWithUrlEncodedAuth(this._api.dsn, this._api.tunnel); - // Envelope header is required to be at least an empty object - const envelopeHeader = JSON.stringify({ ...(this._api.tunnel && { dsn: dsnToString(this._api.dsn) }) }); - const itemHeaders = JSON.stringify({ - type: 'client_report', - }); - const item = JSON.stringify({ - timestamp: dateTimestampInSeconds(), - discarded_events: Object.keys(outcomes).map(key => { - const [category, reason] = key.split(':'); - return { - reason, - category, - quantity: outcomes[key], - }; - }), - }); - const envelope = `${envelopeHeader}\n${itemHeaders}\n${item}`; + + const discardedEvents = Object.keys(outcomes).map(key => { + const [category, reason] = key.split(':'); + return { + reason, + category, + quantity: outcomes[key], + }; + // TODO: Improve types on discarded_events to get rid of cast + }) as ClientReportEnvelopeItemPayload['discarded_events']; + const envelope = createClientReportEnvelope(discardedEvents, this._api.tunnel && dsnToString(this._api.dsn)); try { - sendReport(url, envelope); + sendReport(url, serializeEnvelope(envelope)); } catch (e) { logger.error(e); } diff --git a/packages/utils/src/clientreports.ts b/packages/utils/src/clientreports.ts new file mode 100644 index 000000000000..bc5fc7f400d6 --- /dev/null +++ b/packages/utils/src/clientreports.ts @@ -0,0 +1,25 @@ +import { ClientReportEnvelope, ClientReportEnvelopeItemHeader, ClientReportEnvelopeItemPayload } from '@sentry/types'; + +import { createEnvelope } from './envelope'; +import { dateTimestampInSeconds } from './time'; + +/** + * Creates client report envelope + * @param discarded_events An array of discard events + * @param dsn A DSN that can be set on the header. Optional. + */ +export function createClientReportEnvelope( + discarded_events: ClientReportEnvelopeItemPayload['discarded_events'], + dsn?: string, + timestamp?: number, +): ClientReportEnvelope { + const header = dsn ? { dsn } : {}; + + const itemHeader: ClientReportEnvelopeItemHeader = { type: 'client_report' }; + const itemPayload: ClientReportEnvelopeItemPayload = { + timestamp: timestamp || dateTimestampInSeconds(), + discarded_events, + }; + + return createEnvelope(header, [[itemHeader, itemPayload]]); +} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 511d8a1315ca..4e9d6cdbfc52 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -22,3 +22,4 @@ export * from './syncpromise'; export * from './time'; export * from './env'; export * from './envelope'; +export * from './clientreports'; diff --git a/packages/utils/test/clientreports.test.ts b/packages/utils/test/clientreports.test.ts new file mode 100644 index 000000000000..e0421f4b51d5 --- /dev/null +++ b/packages/utils/test/clientreports.test.ts @@ -0,0 +1,50 @@ +import { createClientReportEnvelope } from '../src/clientreports'; +import { serializeEnvelope } from '../src/envelope'; +import { ClientReportEnvelopeItemPayload } from '@sentry/types'; + +const DEFAULT_DISCARDED_EVENTS: ClientReportEnvelopeItemPayload['discarded_events'] = [ + { + reason: 'before_send', + category: 'event', + quantity: 30, + }, + { + reason: 'network_error', + category: 'transaction', + quantity: 23, + }, +]; + +const MOCK_DSN = 'https://public@example.com/1'; + +describe('createClientReportEnvelope', () => { + const testTable: Array< + [string, Parameters[0], Parameters[1]] + > = [ + ['with no discard reasons', [], undefined], + ['with a dsn', [], MOCK_DSN], + ['with discard reasons', DEFAULT_DISCARDED_EVENTS, MOCK_DSN], + ]; + it.each(testTable)('%s', (_: string, discardedEvents, dsn) => { + const env = createClientReportEnvelope(discardedEvents, dsn); + + expect(env[0]).toEqual(dsn ? { dsn } : {}); + + const items = env[1]; + expect(items).toHaveLength(1); + const clientReportItem = items[0]; + + expect(clientReportItem[0]).toEqual({ type: 'client_report' }); + expect(clientReportItem[1]).toEqual({ timestamp: expect.any(Number), discarded_events: discardedEvents }); + }); + + it('serializes an envelope', () => { + const env = createClientReportEnvelope(DEFAULT_DISCARDED_EVENTS, MOCK_DSN, 123456); + const serializedEnv = serializeEnvelope(env); + expect(serializedEnv).toMatchInlineSnapshot(` + "{\\"dsn\\":\\"https://public@example.com/1\\"} + {\\"type\\":\\"client_report\\"} + {\\"timestamp\\":123456,\\"discarded_events\\":[{\\"reason\\":\\"before_send\\",\\"category\\":\\"event\\",\\"quantity\\":30},{\\"reason\\":\\"network_error\\",\\"category\\":\\"transaction\\",\\"quantity\\":23}]}" + `); + }); +}); From 79c77a24c822fad18b4ae0b142aec34532c27877 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 23 Feb 2022 10:06:56 -0500 Subject: [PATCH 07/13] do some renames --- packages/utils/src/{clientreports.ts => clientreport.ts} | 8 ++++---- .../test/{clientreports.test.ts => clientreport.test.ts} | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) rename packages/utils/src/{clientreports.ts => clientreport.ts} (63%) rename packages/utils/test/{clientreports.test.ts => clientreport.test.ts} (88%) diff --git a/packages/utils/src/clientreports.ts b/packages/utils/src/clientreport.ts similarity index 63% rename from packages/utils/src/clientreports.ts rename to packages/utils/src/clientreport.ts index bc5fc7f400d6..602164cd5073 100644 --- a/packages/utils/src/clientreports.ts +++ b/packages/utils/src/clientreport.ts @@ -1,4 +1,4 @@ -import { ClientReportEnvelope, ClientReportEnvelopeItemHeader, ClientReportEnvelopeItemPayload } from '@sentry/types'; +import { ClientReport, ClientReportEnvelope } from '@sentry/types'; import { createEnvelope } from './envelope'; import { dateTimestampInSeconds } from './time'; @@ -9,14 +9,14 @@ import { dateTimestampInSeconds } from './time'; * @param dsn A DSN that can be set on the header. Optional. */ export function createClientReportEnvelope( - discarded_events: ClientReportEnvelopeItemPayload['discarded_events'], + discarded_events: ClientReport['discarded_events'], dsn?: string, timestamp?: number, ): ClientReportEnvelope { const header = dsn ? { dsn } : {}; - const itemHeader: ClientReportEnvelopeItemHeader = { type: 'client_report' }; - const itemPayload: ClientReportEnvelopeItemPayload = { + const itemHeader = { type: 'client_report' }; + const itemPayload = { timestamp: timestamp || dateTimestampInSeconds(), discarded_events, }; diff --git a/packages/utils/test/clientreports.test.ts b/packages/utils/test/clientreport.test.ts similarity index 88% rename from packages/utils/test/clientreports.test.ts rename to packages/utils/test/clientreport.test.ts index e0421f4b51d5..8ee8f9abfae7 100644 --- a/packages/utils/test/clientreports.test.ts +++ b/packages/utils/test/clientreport.test.ts @@ -1,8 +1,8 @@ -import { createClientReportEnvelope } from '../src/clientreports'; +import { createClientReportEnvelope } from '../src/clientreport'; import { serializeEnvelope } from '../src/envelope'; -import { ClientReportEnvelopeItemPayload } from '@sentry/types'; +import { ClientReport } from '@sentry/types'; -const DEFAULT_DISCARDED_EVENTS: ClientReportEnvelopeItemPayload['discarded_events'] = [ +const DEFAULT_DISCARDED_EVENTS: ClientReport['discarded_events'] = [ { reason: 'before_send', category: 'event', From 2b39da3861688ef38ee468b167c638de43ba8858 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 23 Feb 2022 10:13:58 -0500 Subject: [PATCH 08/13] update export + inline --- packages/utils/src/clientreport.ts | 20 ++++++++++---------- packages/utils/src/index.ts | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/utils/src/clientreport.ts b/packages/utils/src/clientreport.ts index 602164cd5073..4994afe2a0d2 100644 --- a/packages/utils/src/clientreport.ts +++ b/packages/utils/src/clientreport.ts @@ -1,4 +1,4 @@ -import { ClientReport, ClientReportEnvelope } from '@sentry/types'; +import { ClientReport, ClientReportEnvelope, ClientReportEnvelopeItem } from '@sentry/types'; import { createEnvelope } from './envelope'; import { dateTimestampInSeconds } from './time'; @@ -13,13 +13,13 @@ export function createClientReportEnvelope( dsn?: string, timestamp?: number, ): ClientReportEnvelope { - const header = dsn ? { dsn } : {}; - - const itemHeader = { type: 'client_report' }; - const itemPayload = { - timestamp: timestamp || dateTimestampInSeconds(), - discarded_events, - }; - - return createEnvelope(header, [[itemHeader, itemPayload]]); + return createEnvelope(dsn ? { dsn } : {}, [ + [ + { type: 'client_report' }, + { + timestamp: timestamp || dateTimestampInSeconds(), + discarded_events, + }, + ], + ]); } diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 4e9d6cdbfc52..6a8e84e2fd93 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -22,4 +22,4 @@ export * from './syncpromise'; export * from './time'; export * from './env'; export * from './envelope'; -export * from './clientreports'; +export * from './clientreport'; From 585f82538a8a6e3908b6fbd8967c69e6c060ac1c Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 23 Feb 2022 10:14:45 -0500 Subject: [PATCH 09/13] fix type --- packages/browser/src/transports/base.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/browser/src/transports/base.ts b/packages/browser/src/transports/base.ts index 4a6daf5556bb..e519dd56dc88 100644 --- a/packages/browser/src/transports/base.ts +++ b/packages/browser/src/transports/base.ts @@ -7,7 +7,7 @@ import { sessionToSentryRequest, } from '@sentry/core'; import { - ClientReportEnvelopeItemPayload, + ClientReport, Event, Outcome, Response as SentryResponse, @@ -138,7 +138,7 @@ export abstract class BaseTransport implements Transport { quantity: outcomes[key], }; // TODO: Improve types on discarded_events to get rid of cast - }) as ClientReportEnvelopeItemPayload['discarded_events']; + }) as ClientReport['discarded_events']; const envelope = createClientReportEnvelope(discardedEvents, this._api.tunnel && dsnToString(this._api.dsn)); try { From fd7baf3690c2f3bbaaff6165c1a28c9d95015e8e Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 23 Feb 2022 11:39:25 -0500 Subject: [PATCH 10/13] remove type --- packages/utils/src/clientreport.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/src/clientreport.ts b/packages/utils/src/clientreport.ts index 4994afe2a0d2..582197f207a3 100644 --- a/packages/utils/src/clientreport.ts +++ b/packages/utils/src/clientreport.ts @@ -1,4 +1,4 @@ -import { ClientReport, ClientReportEnvelope, ClientReportEnvelopeItem } from '@sentry/types'; +import { ClientReport, ClientReportEnvelope } from '@sentry/types'; import { createEnvelope } from './envelope'; import { dateTimestampInSeconds } from './time'; From fb6b86f45064d734d2ee268eafa7ea0249899e60 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 23 Feb 2022 12:00:39 -0500 Subject: [PATCH 11/13] use array type --- packages/browser/src/transports/base.ts | 2 +- packages/types/src/envelope.ts | 2 +- packages/utils/src/clientreport.ts | 2 +- packages/utils/test/clientreport.test.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/browser/src/transports/base.ts b/packages/browser/src/transports/base.ts index e519dd56dc88..30d60fff923d 100644 --- a/packages/browser/src/transports/base.ts +++ b/packages/browser/src/transports/base.ts @@ -138,7 +138,7 @@ export abstract class BaseTransport implements Transport { quantity: outcomes[key], }; // TODO: Improve types on discarded_events to get rid of cast - }) as ClientReport['discarded_events']; + }) as Array; const envelope = createClientReportEnvelope(discardedEvents, this._api.tunnel && dsnToString(this._api.dsn)); try { diff --git a/packages/types/src/envelope.ts b/packages/types/src/envelope.ts index aa7655db9cea..85e81f4990c8 100644 --- a/packages/types/src/envelope.ts +++ b/packages/types/src/envelope.ts @@ -38,7 +38,7 @@ export type UserFeedbackItem = BaseEnvelopeItem | BaseEnvelopeItem; -export type ClientReportItem = BaseEnvelopeItem; +export type ClientReportItem = BaseEnvelopeItem>; type EventEnvelopeHeaders = { event_id: string; sent_at: string }; type SessionEnvelopeHeaders = { sent_at: string }; diff --git a/packages/utils/src/clientreport.ts b/packages/utils/src/clientreport.ts index 582197f207a3..3ca115307f13 100644 --- a/packages/utils/src/clientreport.ts +++ b/packages/utils/src/clientreport.ts @@ -9,7 +9,7 @@ import { dateTimestampInSeconds } from './time'; * @param dsn A DSN that can be set on the header. Optional. */ export function createClientReportEnvelope( - discarded_events: ClientReport['discarded_events'], + discarded_events: Array, dsn?: string, timestamp?: number, ): ClientReportEnvelope { diff --git a/packages/utils/test/clientreport.test.ts b/packages/utils/test/clientreport.test.ts index 8ee8f9abfae7..730a96f71bda 100644 --- a/packages/utils/test/clientreport.test.ts +++ b/packages/utils/test/clientreport.test.ts @@ -2,7 +2,7 @@ import { createClientReportEnvelope } from '../src/clientreport'; import { serializeEnvelope } from '../src/envelope'; import { ClientReport } from '@sentry/types'; -const DEFAULT_DISCARDED_EVENTS: ClientReport['discarded_events'] = [ +const DEFAULT_DISCARDED_EVENTS: Array = [ { reason: 'before_send', category: 'event', From f46e8f1d0ea6de192dc2fcd4ba01284d4b55dd9f Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 23 Feb 2022 12:13:22 -0500 Subject: [PATCH 12/13] fix array stuff --- packages/browser/src/transports/base.ts | 2 +- packages/types/src/clientreport.ts | 2 +- packages/types/src/envelope.ts | 2 +- packages/utils/src/clientreport.ts | 21 ++++++++++----------- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/packages/browser/src/transports/base.ts b/packages/browser/src/transports/base.ts index 30d60fff923d..e519dd56dc88 100644 --- a/packages/browser/src/transports/base.ts +++ b/packages/browser/src/transports/base.ts @@ -138,7 +138,7 @@ export abstract class BaseTransport implements Transport { quantity: outcomes[key], }; // TODO: Improve types on discarded_events to get rid of cast - }) as Array; + }) as ClientReport['discarded_events']; const envelope = createClientReportEnvelope(discardedEvents, this._api.tunnel && dsnToString(this._api.dsn)); try { diff --git a/packages/types/src/clientreport.ts b/packages/types/src/clientreport.ts index add2194c13ff..22c590d0cc64 100644 --- a/packages/types/src/clientreport.ts +++ b/packages/types/src/clientreport.ts @@ -3,5 +3,5 @@ import { Outcome } from './transport'; export type ClientReport = { timestamp: number; - discarded_events: { reason: Outcome; category: SentryRequestType; quantity: number }; + discarded_events: Array<{ reason: Outcome; category: SentryRequestType; quantity: number }>; }; diff --git a/packages/types/src/envelope.ts b/packages/types/src/envelope.ts index 85e81f4990c8..aa7655db9cea 100644 --- a/packages/types/src/envelope.ts +++ b/packages/types/src/envelope.ts @@ -38,7 +38,7 @@ export type UserFeedbackItem = BaseEnvelopeItem | BaseEnvelopeItem; -export type ClientReportItem = BaseEnvelopeItem>; +export type ClientReportItem = BaseEnvelopeItem; type EventEnvelopeHeaders = { event_id: string; sent_at: string }; type SessionEnvelopeHeaders = { sent_at: string }; diff --git a/packages/utils/src/clientreport.ts b/packages/utils/src/clientreport.ts index 3ca115307f13..f91c79ab5c5c 100644 --- a/packages/utils/src/clientreport.ts +++ b/packages/utils/src/clientreport.ts @@ -1,4 +1,4 @@ -import { ClientReport, ClientReportEnvelope } from '@sentry/types'; +import { ClientReport, ClientReportEnvelope, ClientReportItem } from '@sentry/types'; import { createEnvelope } from './envelope'; import { dateTimestampInSeconds } from './time'; @@ -9,17 +9,16 @@ import { dateTimestampInSeconds } from './time'; * @param dsn A DSN that can be set on the header. Optional. */ export function createClientReportEnvelope( - discarded_events: Array, + discarded_events: ClientReport['discarded_events'], dsn?: string, timestamp?: number, ): ClientReportEnvelope { - return createEnvelope(dsn ? { dsn } : {}, [ - [ - { type: 'client_report' }, - { - timestamp: timestamp || dateTimestampInSeconds(), - discarded_events, - }, - ], - ]); + const clientReportItem: ClientReportItem = [ + { type: 'client_report' }, + { + timestamp: timestamp || dateTimestampInSeconds(), + discarded_events, + }, + ]; + return createEnvelope(dsn ? { dsn } : {}, [clientReportItem]); } From df8a5440a7ca1650a56449c373be4b871b0d61a6 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 23 Feb 2022 12:30:11 -0500 Subject: [PATCH 13/13] lint fix --- packages/utils/test/clientreport.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/utils/test/clientreport.test.ts b/packages/utils/test/clientreport.test.ts index 730a96f71bda..8d98291c3a14 100644 --- a/packages/utils/test/clientreport.test.ts +++ b/packages/utils/test/clientreport.test.ts @@ -1,6 +1,7 @@ +import { ClientReport } from '@sentry/types'; + import { createClientReportEnvelope } from '../src/clientreport'; import { serializeEnvelope } from '../src/envelope'; -import { ClientReport } from '@sentry/types'; const DEFAULT_DISCARDED_EVENTS: Array = [ {