From a8cc69413017bb5dca94b4cd3c457b8a0282aaa9 Mon Sep 17 00:00:00 2001 From: JonasBa Date: Wed, 21 Jun 2023 12:28:23 -0400 Subject: [PATCH] feat: send profiles in same envelope as txn --- package.json | 2 +- packages/browser/src/profiling/cache.ts | 72 ------ .../browser/src/profiling/hubextensions.ts | 220 ++++++------------ packages/browser/src/profiling/integration.ts | 102 ++------ .../browser/src/profiling/jsSelfProfiling.ts | 3 - packages/browser/src/profiling/utils.ts | 177 ++++---------- .../dedupePerformanceEntries.benchmark.ts | 47 ---- .../src/util/dedupePerformanceEntries.new.ts | 102 -------- 8 files changed, 144 insertions(+), 581 deletions(-) delete mode 100644 packages/browser/src/profiling/cache.ts delete mode 100644 packages/replay/src/util/dedupePerformanceEntries.benchmark.ts delete mode 100644 packages/replay/src/util/dedupePerformanceEntries.new.ts diff --git a/package.json b/package.json index 8ebd0541f657..4349b4196cc7 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "yalc:publish": "lerna run yalc:publish" }, "volta": { - "node": "16.19.0", + "node": "18.12.1", "yarn": "1.22.19" }, "workspaces": [ diff --git a/packages/browser/src/profiling/cache.ts b/packages/browser/src/profiling/cache.ts deleted file mode 100644 index ee62538e60cb..000000000000 --- a/packages/browser/src/profiling/cache.ts +++ /dev/null @@ -1,72 +0,0 @@ -import type { Event } from '@sentry/types'; - -/** - * Creates a cache that evicts keys in fifo order - * @param size {Number} - */ -export function makeProfilingCache( - size: number, -): { - get: (key: Key) => Value | undefined; - add: (key: Key, value: Value) => void; - delete: (key: Key) => boolean; - clear: () => void; - size: () => number; -} { - // Maintain a fifo queue of keys, we cannot rely on Object.keys as the browser may not support it. - let evictionOrder: Key[] = []; - let cache: Record = {}; - - return { - add(key: Key, value: Value) { - while (evictionOrder.length >= size) { - // shift is O(n) but this is small size and only happens if we are - // exceeding the cache size so it should be fine. - const evictCandidate = evictionOrder.shift(); - - if (evictCandidate !== undefined) { - // eslint-disable-next-line @typescript-eslint/no-dynamic-delete - delete cache[evictCandidate]; - } - } - - // in case we have a collision, delete the old key. - if (cache[key]) { - this.delete(key); - } - - evictionOrder.push(key); - cache[key] = value; - }, - clear() { - cache = {}; - evictionOrder = []; - }, - get(key: Key): Value | undefined { - return cache[key]; - }, - size() { - return evictionOrder.length; - }, - // Delete cache key and return true if it existed, false otherwise. - delete(key: Key): boolean { - if (!cache[key]) { - return false; - } - - // eslint-disable-next-line @typescript-eslint/no-dynamic-delete - delete cache[key]; - - for (let i = 0; i < evictionOrder.length; i++) { - if (evictionOrder[i] === key) { - evictionOrder.splice(i, 1); - break; - } - } - - return true; - }, - }; -} - -export const PROFILING_EVENT_CACHE = makeProfilingCache(20); diff --git a/packages/browser/src/profiling/hubextensions.ts b/packages/browser/src/profiling/hubextensions.ts index c1cd8d8a1165..292d4e672ae6 100644 --- a/packages/browser/src/profiling/hubextensions.ts +++ b/packages/browser/src/profiling/hubextensions.ts @@ -1,9 +1,10 @@ +/* eslint-disable complexity */ import { getCurrentHub } from '@sentry/core'; -import type { CustomSamplingContext, Transaction } from '@sentry/types'; +import type { Transaction } from '@sentry/types'; import { logger, uuid4 } from '@sentry/utils'; -import type { BrowserClient } from '../client'; import { WINDOW } from '../helpers'; +import { addToProfileQueue } from './integration'; import type { JSSelfProfile, JSSelfProfiler, @@ -17,120 +18,6 @@ export const MAX_PROFILE_DURATION_MS = 30_000; // once, it will always fail and this allows us to early return. let PROFILING_CONSTRUCTOR_FAILED = false; -// Takes a transaction and determines if it should be profiled or not. If it should be profiled, it returns the -// profile_id, otherwise returns undefined. Takes care of setting profile context on transaction as well -/** - * - */ -export function maybeProfileTransaction( - client: BrowserClient, - transaction: Transaction, - customSamplingContext?: CustomSamplingContext, -): string | undefined { - // profilesSampleRate is multiplied with tracesSampleRate to get the final sampling rate. We dont perform - // the actual multiplication to get the final rate, but we discard the profile if the transaction was sampled, - // so anything after this block from here is based on the transaction sampling. - if (!transaction.sampled) { - return; - } - - // Client and options are required for profiling - if (!client) { - __DEBUG_BUILD__ && logger.log('[Profiling] Profiling disabled, no client found.'); - return; - } - - const options = client.getOptions(); - if (!options) { - __DEBUG_BUILD__ && logger.log('[Profiling] Profiling disabled, no options found.'); - return; - } - - // @ts-ignore profilesSampler is not part of the browser options yet - const profilesSampler = options.profilesSampler; - // @ts-ignore profilesSampleRate is not part of the browser options yet - let profilesSampleRate: number | boolean | undefined = options.profilesSampleRate; - - // Prefer sampler to sample rate if both are provided. - if (typeof profilesSampler === 'function') { - profilesSampleRate = profilesSampler({ transactionContext: transaction.toContext(), ...customSamplingContext }); - } - - // Since this is coming from the user (or from a function provided by the user), who knows what we might get. (The - // only valid values are booleans or numbers between 0 and 1.) - if (!isValidSampleRate(profilesSampleRate)) { - __DEBUG_BUILD__ && logger.warn('[Profiling] Discarding profile because of invalid sample rate.'); - return; - } - - // if the function returned 0 (or false), or if `profileSampleRate` is 0, it's a sign the profile should be dropped - if (!profilesSampleRate) { - __DEBUG_BUILD__ && - logger.log( - `[Profiling] Discarding profile because ${ - typeof profilesSampler === 'function' - ? 'profileSampler returned 0 or false' - : 'a negative sampling decision was inherited or profileSampleRate is set to 0' - }`, - ); - return; - } - - // Now we roll the dice. Math.random is inclusive of 0, but not of 1, so strict < is safe here. In case sampleRate is - // a boolean, the < comparison will cause it to be automatically cast to 1 if it's true and 0 if it's false. - const sampled = profilesSampleRate === true ? true : Math.random() < profilesSampleRate; - // Check if we should sample this profile - if (!sampled) { - __DEBUG_BUILD__ && - logger.log( - `[Profiling] Discarding profile because it's not included in the random sample (sampling rate = ${Number( - profilesSampleRate, - )})`, - ); - return; - } - - const profile_id = uuid4(); - CpuProfilerBindings.startProfiling(profile_id); - - __DEBUG_BUILD__ && logger.log(`[Profiling] started profiling transaction: ${transaction.name}`); - - // set transaction context - do this regardless if profiling fails down the line - // so that we can still see the profile_id in the transaction context - return profile_id; -} - -/** - * - */ -export function stopTransactionProfile( - transaction: Transaction, - profile_id: string | undefined, -): ReturnType<(typeof CpuProfilerBindings)['stopProfiling']> | null { - // Should not happen, but satisfy the type checker and be safe regardless. - if (!profile_id) { - return null; - } - - const profile = CpuProfilerBindings.stopProfiling(profile_id); - - __DEBUG_BUILD__ && logger.log(`[Profiling] stopped profiling of transaction: ${transaction.name}`); - - // In case of an overlapping transaction, stopProfiling may return null and silently ignore the overlapping profile. - if (!profile) { - __DEBUG_BUILD__ && - logger.log( - `[Profiling] profiler returned null profile for: ${transaction.name}`, - 'this may indicate an overlapping transaction or a call to stopProfiling with a profile title that was never started', - ); - return null; - } - - // Assign profile_id to the profile - profile.profile_id = profile_id; - return profile; -} - /** * Check if profiler constructor is available. * @param maybeProfiler @@ -162,7 +49,7 @@ export function onProfilingStartRouteTransaction(transaction: Transaction | unde * startProfiling is called after the call to startTransaction in order to avoid our own code from * being profiled. Because of that same reason, stopProfiling is called before the call to stopTransaction. */ -function wrapTransactionWithProfiling(transaction: Transaction): Transaction { +export function wrapTransactionWithProfiling(transaction: Transaction): Transaction { // Feature support check first const JSProfilerConstructor = WINDOW.Profiler; @@ -175,14 +62,6 @@ function wrapTransactionWithProfiling(transaction: Transaction): Transaction { return transaction; } - // profilesSampleRate is multiplied with tracesSampleRate to get the final sampling rate. - if (!transaction.sampled) { - if (__DEBUG_BUILD__) { - logger.log('[Profiling] Transaction is not sampled, skipping profiling'); - } - return transaction; - } - // If constructor failed once, it will always fail, so we can early return. if (PROFILING_CONSTRUCTOR_FAILED) { if (__DEBUG_BUILD__) { @@ -193,21 +72,52 @@ function wrapTransactionWithProfiling(transaction: Transaction): Transaction { const client = getCurrentHub().getClient(); const options = client && client.getOptions(); + if (!options) { + __DEBUG_BUILD__ && logger.log('[Profiling] Profiling disabled, no options found.'); + return transaction; + } - // @ts-ignore not part of the browser options yet - const profilesSampleRate = (options && options.profilesSampleRate) || 0; - if (profilesSampleRate === undefined) { - if (__DEBUG_BUILD__) { - logger.log('[Profiling] Profiling disabled, enable it by setting `profilesSampleRate` option to SDK init call.'); - } + // @ts-ignore profilesSampler is not part of the browser options yet + const profilesSampler = options.profilesSampler; + // @ts-ignore profilesSampleRate is not part of the browser options yet + let profilesSampleRate: number | boolean | undefined = options.profilesSampleRate; + + // Prefer sampler to sample rate if both are provided. + if (typeof profilesSampler === 'function') { + profilesSampleRate = profilesSampler({ transactionContext: transaction.toContext() }); + } + + // Since this is coming from the user (or from a function provided by the user), who knows what we might get. (The + // only valid values are booleans or numbers between 0 and 1.) + if (!isValidSampleRate(profilesSampleRate)) { + __DEBUG_BUILD__ && logger.warn('[Profiling] Discarding profile because of invalid sample rate.'); return transaction; } + // if the function returned 0 (or false), or if `profileSampleRate` is 0, it's a sign the profile should be dropped + if (!profilesSampleRate) { + __DEBUG_BUILD__ && + logger.log( + `[Profiling] Discarding profile because ${ + typeof profilesSampler === 'function' + ? 'profileSampler returned 0 or false' + : 'a negative sampling decision was inherited or profileSampleRate is set to 0' + }`, + ); + return transaction; + } + + // Now we roll the dice. Math.random is inclusive of 0, but not of 1, so strict < is safe here. In case sampleRate is + // a boolean, the < comparison will cause it to be automatically cast to 1 if it's true and 0 if it's false. + const sampled = profilesSampleRate === true ? true : Math.random() < profilesSampleRate; // Check if we should sample this profile - if (Math.random() > profilesSampleRate) { - if (__DEBUG_BUILD__) { - logger.log('[Profiling] Skip profiling transaction due to sampling.'); - } + if (!sampled) { + __DEBUG_BUILD__ && + logger.log( + `[Profiling] Discarding profile because it's not included in the random sample (sampling rate = ${Number( + profilesSampleRate, + )})`, + ); return transaction; } @@ -254,19 +164,19 @@ function wrapTransactionWithProfiling(transaction: Transaction): Transaction { // event of an error or user mistake (calling transaction.finish multiple times), it is important that the behavior of onProfileHandler // is idempotent as we do not want any timings or profiles to be overriden by the last call to onProfileHandler. // After the original finish method is called, the event will be reported through the integration and delegated to transport. - let processedProfile: ProcessedJSSelfProfile | null = null; + const processedProfile: ProcessedJSSelfProfile | null = null; /** * Idempotent handler for profile stop */ - function onProfileHandler(): void { + async function onProfileHandler(): Promise { // Check if the profile exists and return it the behavior has to be idempotent as users may call transaction.finish multiple times. if (!transaction) { - return; + return null; } // Satisfy the type checker, but profiler will always be defined here. if (!profiler) { - return; + return null; } if (processedProfile) { if (__DEBUG_BUILD__) { @@ -276,12 +186,12 @@ function wrapTransactionWithProfiling(transaction: Transaction): Transaction { 'already exists, returning early', ); } - return; + return null; } - profiler + return profiler .stop() - .then((p: JSSelfProfile): void => { + .then((p: JSSelfProfile): null => { if (maxDurationTimeoutID) { WINDOW.clearTimeout(maxDurationTimeoutID); maxDurationTimeoutID = undefined; @@ -299,16 +209,16 @@ function wrapTransactionWithProfiling(transaction: Transaction): Transaction { 'this may indicate an overlapping transaction or a call to stopProfiling with a profile title that was never started', ); } - return; + return null; } // If a profile has less than 2 samples, it is not useful and should be discarded. if (p.samples.length < 2) { - return; + return null; } - processedProfile = { ...p, profile_id: profileId }; - sendProfile(profileId, processedProfile); + addToProfileQueue({ ...p, profile_id: profileId }); + return null; }) .catch(error => { if (__DEBUG_BUILD__) { @@ -326,6 +236,7 @@ function wrapTransactionWithProfiling(transaction: Transaction): Transaction { transaction.name || transaction.description, ); } + // If the timeout exceeds, we want to stop profiling, but not finish the transaction void onProfileHandler(); }, MAX_PROFILE_DURATION_MS); @@ -337,18 +248,23 @@ function wrapTransactionWithProfiling(transaction: Transaction): Transaction { * startProfiling is called after the call to startTransaction in order to avoid our own code from * being profiled. Because of that same reason, stopProfiling is called before the call to stopTransaction. */ - function profilingWrappedTransactionFinish(): Promise { + function profilingWrappedTransactionFinish(): Transaction { if (!transaction) { return originalFinish(); } // onProfileHandler should always return the same profile even if this is called multiple times. // Always call onProfileHandler to ensure stopProfiling is called and the timeout is cleared. - onProfileHandler(); - - // Set profile context - transaction.setContext('profile', { profile_id: profileId }); + void onProfileHandler() + .then(() => { + transaction.setContext('profile', { profile_id: profileId }); + originalFinish(); + }) + .catch(() => { + // If onProfileHandler fails, we still want to call the original finish method. + originalFinish(); + }); - return originalFinish(); + return transaction; } transaction.finish = profilingWrappedTransactionFinish; diff --git a/packages/browser/src/profiling/integration.ts b/packages/browser/src/profiling/integration.ts index cd79fc56916d..67b8affe1037 100644 --- a/packages/browser/src/profiling/integration.ts +++ b/packages/browser/src/profiling/integration.ts @@ -1,20 +1,23 @@ -import type { BrowserClient } from '@sentry/browser'; -import type { Event, EventProcessor, Hub, Integration, Transaction } from '@sentry/types'; +import type { EventProcessor, Hub, Integration, Transaction } from '@sentry/types'; import { logger } from '@sentry/utils'; -import { PROFILING_EVENT_CACHE } from './cache'; -import { MAX_PROFILE_DURATION_MS, maybeProfileTransaction } from './hubextensions'; -import { addProfilesToEnvelope, findProfiledTransactionsFromEnvelope } from './utils'; +import type { BrowserClient } from './../client'; +import { wrapTransactionWithProfiling } from './hubextensions'; +import type { ProcessedJSSelfProfile, SentryProfile } from './jsSelfProfiling'; +import type { ProfiledEvent } from './utils'; +import { addProfilesToEnvelope, createProfilingEvent, findProfiledTransactionsFromEnvelope } from './utils'; -const MAX_PROFILE_QUEUE_LENGTH = 50; -const PROFILE_QUEUE: RawThreadCpuProfile[] = []; -const PROFILE_TIMEOUTS: Record = {}; +const MAX_PROFILE_QUEUE_SIZE = 50; +const PROFILE_QUEUE: ProcessedJSSelfProfile[] = []; -function addToProfileQueue(profile: RawThreadCpuProfile): void { +/** + * Adds the profile to the queue of profiles to be sent + */ +export function addToProfileQueue(profile: ProcessedJSSelfProfile): void { PROFILE_QUEUE.push(profile); // We only want to keep the last n profiles in the queue. - if (PROFILE_QUEUE.length > MAX_PROFILE_QUEUE_LENGTH) { + if (PROFILE_QUEUE.length > MAX_PROFILE_QUEUE_SIZE) { PROFILE_QUEUE.shift(); } } @@ -41,55 +44,12 @@ export class BrowserProfilingIntegration implements Integration { if (client && typeof client.on === 'function') { client.on('startTransaction', (transaction: Transaction) => { - const profile_id = maybeProfileTransaction(client, transaction, undefined); - - if (profile_id) { - const options = client.getOptions(); - // Not intended for external use, hence missing types, but we want to profile a couple of things at Sentry that - // currently exceed the default timeout set by the SDKs. - const maxProfileDurationMs = - (options._experiments && options._experiments['maxProfileDurationMs']) || MAX_PROFILE_DURATION_MS; - - // Enqueue a timeout to prevent profiles from running over max duration. - if (PROFILE_TIMEOUTS[profile_id]) { - global.clearTimeout(PROFILE_TIMEOUTS[profile_id]); - delete PROFILE_TIMEOUTS[profile_id]; - } - - PROFILE_TIMEOUTS[profile_id] = global.setTimeout(() => { - __DEBUG_BUILD__ && - logger.log('[Profiling] max profile duration elapsed, stopping profiling for:', transaction.name); - - const profile = stopTransactionProfile(transaction, profile_id); - if (profile) { - addToProfileQueue(profile); - } - }, maxProfileDurationMs); - - transaction.setContext('profile', { profile_id }); - // @ts-expect-error profile_id is not part of the metadata type - transaction.setMetadata({ profile_id: profile_id }); - } - }); - - client.on('finishTransaction', transaction => { - // @ts-expect-error profile_id is not part of the metadata type - const profile_id = transaction && transaction.metadata && transaction.metadata.profile_id; - if (profile_id) { - if (PROFILE_TIMEOUTS[profile_id]) { - global.clearTimeout(PROFILE_TIMEOUTS[profile_id]); - delete PROFILE_TIMEOUTS[profile_id]; - } - const profile = stopTransactionProfile(transaction, profile_id); - - if (profile) { - addToProfileQueue(profile); - } - } + wrapTransactionWithProfiling(transaction); }); client.on('beforeEnvelope', (envelope): void => { // if not profiles are in queue, there is nothing to add to the envelope. + if (!PROFILE_QUEUE.length) { return; } @@ -99,17 +59,21 @@ export class BrowserProfilingIntegration implements Integration { return; } - const profilesToAddToEnvelope: Profile[] = []; + const profilesToAddToEnvelope: SentryProfile[] = []; for (const profiledTransaction of profiledTransactionEvents) { - const profile_id = profiledTransaction?.contexts?.['profile']?.['profile_id']; + const profile_id = + profiledTransaction && + profiledTransaction.contexts && + profiledTransaction.contexts['profile'] && + profiledTransaction.contexts['profile']['profile_id']; if (!profile_id) { throw new TypeError('[Profiling] cannot find profile for a transaction without a profile context'); } // Remove the profile from the transaction context before sending, relay will take care of the rest. - if (profiledTransaction?.contexts?.['.profile']) { + if (profiledTransaction && profiledTransaction.contexts && profiledTransaction.contexts['.profile']) { delete profiledTransaction.contexts.profile; } @@ -128,10 +92,10 @@ export class BrowserProfilingIntegration implements Integration { // Remove the profile from the queue. PROFILE_QUEUE.splice(profileIndex, 1); - const profile = createProfilingEvent(cpuProfile, profiledTransaction); + const profileEvent = createProfilingEvent(cpuProfile, profiledTransaction as ProfiledEvent); - if (profile) { - profilesToAddToEnvelope.push(profile); + if (profileEvent) { + profilesToAddToEnvelope.push(profileEvent); } } @@ -141,20 +105,4 @@ export class BrowserProfilingIntegration implements Integration { logger.warn('[Profiling] Client does not support hooks, profiling will be disabled'); } } - - /** - * @inheritDoc - */ - public handleGlobalEvent(event: Event): Event { - const profileId = event.contexts && event.contexts['profile'] && event.contexts['profile']['profile_id']; - - if (profileId && typeof profileId === 'string') { - if (__DEBUG_BUILD__) { - logger.log('[Profiling] Profiling event found, caching it.'); - } - PROFILING_EVENT_CACHE.add(profileId, event); - } - - return event; - } } diff --git a/packages/browser/src/profiling/jsSelfProfiling.ts b/packages/browser/src/profiling/jsSelfProfiling.ts index 778342ba0193..60b10c9896ab 100644 --- a/packages/browser/src/profiling/jsSelfProfiling.ts +++ b/packages/browser/src/profiling/jsSelfProfiling.ts @@ -51,9 +51,6 @@ declare global { } } -export interface RawThreadCpuProfile extends JSSelfProfile { - profile_id: string; -} export interface ThreadCpuProfile { samples: { stack_id: number; diff --git a/packages/browser/src/profiling/utils.ts b/packages/browser/src/profiling/utils.ts index 751e7a92948a..4b327bef87e8 100644 --- a/packages/browser/src/profiling/utils.ts +++ b/packages/browser/src/profiling/utils.ts @@ -1,36 +1,14 @@ /* eslint-disable max-lines */ import { DEFAULT_ENVIRONMENT, getCurrentHub } from '@sentry/core'; -import type { - DebugImage, - DsnComponents, - DynamicSamplingContext, - Envelope, - Event, - EventEnvelope, - EventEnvelopeHeaders, - EventItem, - SdkInfo, - SdkMetadata, - StackFrame, - StackParser, -} from '@sentry/types'; -import { - createEnvelope, - dropUndefinedKeys, - dsnToString, - forEachEnvelopeItem, - GLOBAL_OBJ, - logger, - uuid4, -} from '@sentry/utils'; +import type { DebugImage, Envelope, Event, StackFrame, StackParser } from '@sentry/types'; +import { forEachEnvelopeItem, GLOBAL_OBJ, logger, uuid4 } from '@sentry/utils'; import { WINDOW } from '../helpers'; import type { JSSelfProfile, JSSelfProfileStack, ProcessedJSSelfProfile, - RawThreadCpuProfile, SentryProfile, ThreadCpuProfile, } from './jsSelfProfiling'; @@ -42,9 +20,9 @@ const THREAD_ID_STRING = String(0); const THREAD_NAME = 'main'; // Machine properties (eval only once) -let OS_PLATFORM = ''; // macos -let OS_PLATFORM_VERSION = ''; // 13.2 -let OS_ARCH = ''; // arm64 +let OS_PLATFORM = ''; +let OS_PLATFORM_VERSION = ''; +let OS_ARCH = ''; let OS_BROWSER = (WINDOW.navigator && WINDOW.navigator.userAgent) || ''; let OS_MODEL = ''; const OS_LOCALE = @@ -91,7 +69,9 @@ if (isUserAgentData(userAgentData)) { .catch(e => void e); } -function isRawThreadCpuProfile(profile: ThreadCpuProfile | RawThreadCpuProfile): profile is RawThreadCpuProfile { +function isProcessedJSSelfProfile( + profile: ThreadCpuProfile | ProcessedJSSelfProfile, +): profile is ProcessedJSSelfProfile { return !('thread_metadata' in profile); } @@ -100,8 +80,8 @@ function isRawThreadCpuProfile(profile: ThreadCpuProfile | RawThreadCpuProfile): /** * */ -export function enrichWithThreadInformation(profile: ThreadCpuProfile | RawThreadCpuProfile): ThreadCpuProfile { - if (!isRawThreadCpuProfile(profile)) { +export function enrichWithThreadInformation(profile: ThreadCpuProfile | ProcessedJSSelfProfile): ThreadCpuProfile { + if (!isProcessedJSSelfProfile(profile)) { return profile; } @@ -112,52 +92,7 @@ export function enrichWithThreadInformation(profile: ThreadCpuProfile | RawThrea // by the integration before the event is processed by other integrations. export interface ProfiledEvent extends Event { sdkProcessingMetadata: { - profile?: RawThreadCpuProfile; - }; -} - -/** Extract sdk info from from the API metadata */ -function getSdkMetadataForEnvelopeHeader(metadata?: SdkMetadata): SdkInfo | undefined { - if (!metadata || !metadata.sdk) { - return undefined; - } - - return { name: metadata.sdk.name, version: metadata.sdk.version } as SdkInfo; -} - -/** - * Apply SdkInfo (name, version, packages, integrations) to the corresponding event key. - * Merge with existing data if any. - **/ -function enhanceEventWithSdkInfo(event: Event, sdkInfo?: SdkInfo): Event { - if (!sdkInfo) { - return event; - } - event.sdk = event.sdk || {}; - event.sdk.name = event.sdk.name || sdkInfo.name || 'unknown sdk'; - event.sdk.version = event.sdk.version || sdkInfo.version || 'unknown sdk version'; - event.sdk.integrations = [...(event.sdk.integrations || []), ...(sdkInfo.integrations || [])]; - event.sdk.packages = [...(event.sdk.packages || []), ...(sdkInfo.packages || [])]; - return event; -} - -function createEventEnvelopeHeaders( - event: Event, - sdkInfo: SdkInfo | undefined, - tunnel: string | undefined, - dsn: DsnComponents, -): EventEnvelopeHeaders { - const dynamicSamplingContext = event.sdkProcessingMetadata && event.sdkProcessingMetadata['dynamicSamplingContext']; - - return { - event_id: event.event_id as string, - sent_at: new Date().toISOString(), - ...(sdkInfo && { sdk: sdkInfo }), - ...(!!tunnel && { dsn: dsnToString(dsn) }), - ...(event.type === 'transaction' && - dynamicSamplingContext && { - trace: dropUndefinedKeys({ ...dynamicSamplingContext }) as DynamicSamplingContext, - }), + profile?: ProcessedJSSelfProfile; }; } @@ -190,50 +125,30 @@ function getTraceId(event: Event): string { /** * Creates a profiling event envelope from a Sentry event. */ -export function createProfilingEventEnvelope( - event: ProfiledEvent, - dsn: DsnComponents, - metadata?: SdkMetadata, - tunnel?: string, -): EventEnvelope | null { +export function createProfilePayload(event: ProfiledEvent, processedProfile: ProcessedJSSelfProfile): SentryProfile { if (event.type !== 'transaction') { // createProfilingEventEnvelope should only be called for transactions, // we type guard this behavior with isProfiledTransactionEvent. throw new TypeError('Profiling events may only be attached to transactions, this should never occur.'); } - const rawProfile = event.sdkProcessingMetadata['profile'] as ProcessedJSSelfProfile | null; - - if (rawProfile === undefined || rawProfile === null) { + if (processedProfile === undefined || processedProfile === null) { throw new TypeError( - `Cannot construct profiling event envelope without a valid profile. Got ${rawProfile} instead.`, + `Cannot construct profiling event envelope without a valid profile. Got ${processedProfile} instead.`, ); } - if (!rawProfile.profile_id) { + if (!processedProfile.profile_id) { throw new TypeError('Profile is missing profile_id'); } - if (rawProfile.samples.length <= 1) { - if (__DEBUG_BUILD__) { - // Log a warning if the profile has less than 2 samples so users can know why - // they are not seeing any profiling data and we cant avoid the back and forth - // of asking them to provide us with a dump of the profile data. - logger.log('[Profiling] Discarding profile because it contains less than 2 samples'); - } - return null; - } - const traceId = getTraceId(event); - const sdkInfo = getSdkMetadataForEnvelopeHeader(metadata); - enhanceEventWithSdkInfo(event, metadata && metadata.sdk); - const envelopeHeaders = createEventEnvelopeHeaders(event, sdkInfo, tunnel, dsn); - const enrichedThreadProfile = enrichWithThreadInformation(rawProfile); + const enrichedThreadProfile = enrichWithThreadInformation(processedProfile); const transactionStartMs = typeof event.start_timestamp === 'number' ? event.start_timestamp * 1000 : Date.now(); const transactionEndMs = typeof event.timestamp === 'number' ? event.timestamp * 1000 : Date.now(); const profile: SentryProfile = { - event_id: rawProfile.profile_id, + event_id: processedProfile.profile_id, timestamp: new Date(transactionStartMs).toISOString(), platform: 'javascript', version: '1', @@ -256,7 +171,7 @@ export function createProfilingEventEnvelope( is_emulator: false, }, debug_meta: { - images: applyDebugMetadata(rawProfile.resources), + images: applyDebugMetadata(processedProfile.resources), }, profile: enrichedThreadProfile, transactions: [ @@ -271,15 +186,7 @@ export function createProfilingEventEnvelope( ], }; - const envelopeItem: EventItem = [ - { - type: 'profile', - }, - // @ts-ignore this is missing in typedef - profile, - ]; - - return createEnvelope(envelopeHeaders, [envelopeItem]); + return profile; } /** @@ -289,21 +196,6 @@ export function isProfiledTransactionEvent(event: Event): event is ProfiledEvent return !!(event.sdkProcessingMetadata && event.sdkProcessingMetadata['profile']); } -// Due to how profiles are attached to event metadata, we may sometimes want to remove them to ensure -// they are not processed by other Sentry integrations. This can be the case when we cannot construct a valid -// profile from the data we have or some of the mechanisms to send the event (Hub, Transport etc) are not available to us. -/** - * - */ -export function maybeRemoveProfileFromSdkMetadata(event: Event | ProfiledEvent): Event { - if (!isProfiledTransactionEvent(event)) { - return event; - } - - delete event.sdkProcessingMetadata.profile; - return event; -} - /** * Converts a JSSelfProfile to a our sampled format. * Does not currently perform stack indexing. @@ -532,3 +424,34 @@ export function isValidSampleRate(rate: unknown): boolean { } return true; } + +function isValidProfile(profile: ProcessedJSSelfProfile): profile is ProcessedJSSelfProfile & { profile_id: string } { + if (profile.samples.length <= 1) { + if (__DEBUG_BUILD__) { + // Log a warning if the profile has less than 2 samples so users can know why + // they are not seeing any profiling data and we cant avoid the back and forth + // of asking them to provide us with a dump of the profile data. + logger.log('[Profiling] Discarding profile because it contains less than 2 samples'); + } + return false; + } + + if (!profile.profile_id) { + return false; + } + + return true; +} + +/** + * Creates a profiling envelope item, if the profile does not pass validation, returns null. + * @param event + * @returns {Profile | null} + */ +export function createProfilingEvent(profile: ProcessedJSSelfProfile, event: ProfiledEvent): SentryProfile | null { + if (!isValidProfile(profile)) { + return null; + } + + return createProfilePayload(event, profile); +} diff --git a/packages/replay/src/util/dedupePerformanceEntries.benchmark.ts b/packages/replay/src/util/dedupePerformanceEntries.benchmark.ts deleted file mode 100644 index 279cb720cfb4..000000000000 --- a/packages/replay/src/util/dedupePerformanceEntries.benchmark.ts +++ /dev/null @@ -1,47 +0,0 @@ -const Benchmark = require('benchmark'); - -const fns = require('./dedupePerformanceEntries'); -const fnsNew = require('./dedupePerformanceEntries.new'); - -const data = JSON.parse( - '[{"name":"https://sentry.sentry.io/issues/","entryType":"navigation","startTime":0,"duration":1316.5,"initiatorType":"navigation","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":464.7000000476837,"domainLookupStart":466.89999997615814,"domainLookupEnd":498.2000000476837,"connectStart":498.2000000476837,"secureConnectionStart":530.6000000238419,"connectEnd":602.3999999761581,"requestStart":602.3999999761581,"responseStart":951.3000000715256,"responseEnd":957.3000000715256,"transferSize":7984,"encodedBodySize":7684,"decodedBodySize":19215,"responseStatus":200,"serverTiming":[],"unloadEventStart":0,"unloadEventEnd":0,"domInteractive":1056.3999999761581,"domContentLoadedEventStart":1056.3999999761581,"domContentLoadedEventEnd":1056.5,"domComplete":1315.1000000238419,"loadEventStart":1315.1000000238419,"loadEventEnd":1316.5,"type":"navigate","redirectCount":0,"activationStart":0},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/entrypoints-hashed/sentry-TynoRHRu_eq0ob3bedRRtUK-KuSAERzrmgEKRbzAXCI.css","entryType":"resource","startTime":963.8999999761581,"duration":20.700000047683716,"initiatorType":"link","nextHopProtocol":"","renderBlockingStatus":"blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":963.8999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":984.6000000238419,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://js.sentry-cdn.com/c51734c603c4430eb57cb0a5728a479d.min.js","entryType":"resource","startTime":964.1000000238419,"duration":23.299999952316284,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":964.1000000238419,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":987.3999999761581,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":200,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/entrypoints-hashed/app-CcPyCILeKKdnKtN3PEQ8pUuiC3YiM7FoxWRZaq-pv8A.js","entryType":"resource","startTime":964.2000000476837,"duration":24.299999952316284,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":964.2000000476837,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":988.5,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/541fb42adc5d8c91924cc9755b0ae223/sentry/js/ads.js","entryType":"resource","startTime":964.3000000715256,"duration":23.5,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":964.3000000715256,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":987.8000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://js.stripe.com/v3/","entryType":"resource","startTime":964.3999999761581,"duration":322.7000000476837,"initiatorType":"script","nextHopProtocol":"h2","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":964.3999999761581,"domainLookupStart":1033.8999999761581,"domainLookupEnd":1045.2000000476837,"connectStart":1045.2000000476837,"secureConnectionStart":1122.2000000476837,"connectEnd":1203.3000000715256,"requestStart":1203.5,"responseStart":1284.1000000238419,"responseEnd":1287.1000000238419,"transferSize":300,"encodedBodySize":127071,"decodedBodySize":474393,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/541fb42adc5d8c91924cc9755b0ae223/sentry/images/sentry-loader.svg","entryType":"resource","startTime":964.5,"duration":75.70000004768372,"initiatorType":"img","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":964.5,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1040.2000000476837,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://static.zdassets.com/ekr/snippet.js?key=99cb65b7-1616-43cd-b8be-203f91ec932e","entryType":"resource","startTime":964.5,"duration":68.80000007152557,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":964.5,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1033.3000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"head-start","entryType":"mark","startTime":1030.3000000715256,"duration":0},{"name":"app.page.body-load","entryType":"measure","startTime":1030.3000000715256,"duration":25.5},{"name":"app.page.bundle-load","entryType":"measure","startTime":1030.3000000715256,"duration":217.69999992847443},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_bootstrap_index_tsx.b99c6b7cd539e00e7e04.js","entryType":"resource","startTime":1033.6000000238419,"duration":7.5,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1033.6000000238419,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1041.1000000238419,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_sentry_core_esm_exports_js-node_modules_moment_moment_js.2a74ee6a7220aedbc010.js","entryType":"resource","startTime":1033.8000000715256,"duration":8.199999928474426,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1033.8000000715256,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1042,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_emotion_react_jsx-runtime_dist_emotion-react-jsx-runtime_browser_esm_js--5816c0.e8a1be9dbda970aac154.js","entryType":"resource","startTime":1033.8999999761581,"duration":12.5,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1033.8999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1046.3999999761581,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/node_modules_emotion_unitless_dist_emotion-unitless_esm_js-app_bootstrap_initializeLocale_tsx-a2b5a60.3df912d3033a82371b06.js","entryType":"resource","startTime":1034.1000000238419,"duration":11.899999976158142,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1034.1000000238419,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1046,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://reload.getsentry.net/page/","entryType":"resource","startTime":1037.7000000476837,"duration":174.29999995231628,"initiatorType":"xmlhttprequest","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1037.7000000476837,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1212,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":201,"serverTiming":[]},{"name":"head-end","entryType":"mark","startTime":1038.3999999761581,"duration":0},{"name":"https://cdn.pendo.io/agent/static/dc5c6fad-c3ae-4441-49ce-0ae37103aed7/pendo.js","entryType":"resource","startTime":1038.3999999761581,"duration":103.80000007152557,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1038.3999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1142.2000000476837,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://ekr.zdassets.com/compose/99cb65b7-1616-43cd-b8be-203f91ec932e","entryType":"resource","startTime":1055.7000000476837,"duration":127.39999997615814,"initiatorType":"xmlhttprequest","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1055.7000000476837,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1183.1000000238419,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":200,"serverTiming":[]},{"name":"body-end","entryType":"mark","startTime":1055.8000000715256,"duration":0},{"name":"first-paint","entryType":"paint","startTime":1058.8000000715256,"duration":0},{"name":"first-contentful-paint","entryType":"paint","startTime":1058.8000000715256,"duration":0},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_internationalized_string_dist_module_js-node_modules_react-aria_focus_di-544641.75d2e5586f6ac68b95f3.js","entryType":"resource","startTime":1062,"duration":4.700000047683716,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1062,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1066.7000000476837,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_react-aria_button_dist_module_js-node_modules_react-aria_gridlist_dist_m-81a0c4.bb623b51efc44bf23e31.js","entryType":"resource","startTime":1062.2000000476837,"duration":6.600000023841858,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1062.2000000476837,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1068.8000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_react-aria_radio_dist_module_js-node_modules_react-stately_list_dist_mod-7bc4f5.ce5e7d7fd11388c76110.js","entryType":"resource","startTime":1062.5,"duration":4.700000047683716,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1062.5,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1067.2000000476837,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_react-aria_selection_dist_module_js-node_modules_lodash_cloneDeep_js-nod-d70379.d688b691982475d8de57.js","entryType":"resource","startTime":1062.8999999761581,"duration":7,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1062.8999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1069.8999999761581,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_date-fns_format_index_js.ecf7cb2fa6edc821f4eb.js","entryType":"resource","startTime":1063.1000000238419,"duration":5,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1063.1000000238419,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1068.1000000238419,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_buffer_index_js.dcacea8575981fed3f5c.js","entryType":"resource","startTime":1063.3000000715256,"duration":5.899999976158142,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1063.3000000715256,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1069.2000000476837,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_echarts-for-react_lib_core_js-node_modules_echarts_core_js-node_modules_-be3c62.ed7280025d8653d5ad4a.js","entryType":"resource","startTime":1063.5,"duration":24.300000071525574,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1063.5,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1087.8000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_moment-timezone_index_js-node_modules_reflux_src_index_js.9cc3b3392494216b18c8.js","entryType":"resource","startTime":1063.6000000238419,"duration":22.700000047683716,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1063.6000000238419,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1086.3000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_emotion_is-prop-valid_dist_is-prop-valid_browser_esm_js-node_modules_emo-f27c2a.c8a681442de6bd91116a.js","entryType":"resource","startTime":1063.7000000476837,"duration":27.299999952316284,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1063.7000000476837,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1091,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_core-js_modules_es_array_at_js-node_modules_core-js_modules_es_string_at-ac4873.6673d5eace8f33b8e81b.js","entryType":"resource","startTime":1063.8000000715256,"duration":7.799999952316284,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1063.8000000715256,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1071.6000000238419,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_js-beautify_js_index_js.0a8d3ce59a51dc11f6fd.js","entryType":"resource","startTime":1063.8000000715256,"duration":14,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1063.8000000715256,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1077.8000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_focus-trap_dist_focus-trap_esm_js-node_modules_history_lib_createMemoryH-9f114c.82628466bbc3011927af.js","entryType":"resource","startTime":1063.8999999761581,"duration":14.600000023841858,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1063.8999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1078.5,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-node_modules_react-aria_interactions_dist_module_js-node_modules_react-aria_tabs_dist-0dd1d1.da9ab3a97943160dcae2.js","entryType":"resource","startTime":1064.1000000238419,"duration":12.5,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1064.1000000238419,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1076.6000000238419,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-getsentry_node_modules_lodash__baseClone_js-getsentry_node_modules_lodash__baseIsEqua-18ca52.1a0051e2efb17920535c.js","entryType":"resource","startTime":1064.3000000715256,"duration":10.199999928474426,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1064.3000000715256,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1074.5,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/vendors-getsentry_node_modules_amplitude_analytics-browser_lib_esm_index_js-getsentry_node_mo-2275d3.394f54209591e3d776cb.js","entryType":"resource","startTime":1064.3999999761581,"duration":12.400000095367432,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1064.3999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1076.8000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_components_featureFeedback_feedbackModal_tsx.cfb6a3f320673aceab2f.js","entryType":"resource","startTime":1064.5,"duration":10.600000023841858,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1064.5,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1075.1000000238419,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_components_tag_tsx-app_components_textOverflow_tsx-app_components_timeSince_tsx-app_utils-b137eb.f41224d66223c5b07f08.js","entryType":"resource","startTime":1064.8999999761581,"duration":10.800000071525574,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1064.8999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1075.7000000476837,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_components_acl_feature_tsx-app_components_assistant_guideAnchor_tsx-app_components_clipbo-a9c4fa.b0ca9f703fe2c2389484.js","entryType":"resource","startTime":1065,"duration":13.700000047683716,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1065,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1078.7000000476837,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_components_events_interfaces_frame_utils_tsx-app_components_segmentedControl_tsx.036777a408266806394e.js","entryType":"resource","startTime":1065.2000000476837,"duration":10.799999952316284,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1065.2000000476837,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1076,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_components_asyncComponent_tsx.4e8e1eece3af7680e5b0.js","entryType":"resource","startTime":1065.3999999761581,"duration":10.900000095367432,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1065.3999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1076.3000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_actionCreators_guides_tsx-app_components_charts_utils_tsx-app_utils_discover_fieldRendere-6404c2.57f08970b136b7ab5492.js","entryType":"resource","startTime":1065.3999999761581,"duration":23.600000023841858,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1065.3999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1089,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_components_searchSyntax_parser_tsx-app_components_searchSyntax_utils_tsx-app_utils_withPa-338bbb.30bc1943da4795e58e13.js","entryType":"resource","startTime":1065.7000000476837,"duration":12,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1065.7000000476837,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1077.7000000476837,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_actionCreators_navigation_tsx-app_components_pagination_tsx-app_utils_useRouter_tsx-app_u-e3e402.a492cd094ceb8cebdc8b.js","entryType":"resource","startTime":1065.8000000715256,"duration":12.399999976158142,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1065.8000000715256,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1078.2000000476837,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_components_alerts_toastIndicator_tsx-app_components_assistant_getGuidesContent_tsx-app_co-3627de.49c1887d6fb6ab1bf842.js","entryType":"resource","startTime":1065.8999999761581,"duration":22.600000023841858,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1065.8999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1088.5,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_components_assigneeSelector_tsx-app_components_charts_barChart_tsx-app_components_organiz-1c0127.5cc379e8a2e3c80c8d3d.js","entryType":"resource","startTime":1066,"duration":17.300000071525574,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1066,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1083.3000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_components_eventOrGroupHeader_tsx-app_utils_useParams_tsx.0ae6c7e8cf1492bfec03.js","entryType":"resource","startTime":1066.3999999761581,"duration":13.100000023841858,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1066.3999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1079.5,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_components_deprecatedforms_selectField_tsx-app_components_forms_apiForm_tsx-app_component-fe94fb.91f9f63fa45bc4790767.js","entryType":"resource","startTime":1066.3999999761581,"duration":18.40000009536743,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1066.3999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1084.8000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_components_onboarding_documentationWrapper_tsx-app_components_onboarding_footer_tsx-app_v-7ba665.54c11556cadee8f8e5cc.js","entryType":"resource","startTime":1066.5,"duration":13.600000023841858,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1066.5,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1080.1000000238419,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_components_actions_button_tsx-app_components_dropdownAutoComplete_autoCompleteFilter_tsx--91f7e8.77d1c40bdaa6bb9db5d4.js","entryType":"resource","startTime":1066.7000000476837,"duration":14,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1066.7000000476837,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1080.7000000476837,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_components_banner_tsx-app_components_charts_optionSelector_tsx.bc62abd018a73f0f63f7.js","entryType":"resource","startTime":1066.7000000476837,"duration":14.199999928474426,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1066.7000000476837,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1080.8999999761581,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_actionCreators_account_tsx-app_actionCreators_discoverSavedQueries_tsx-app_components_eve-338d0c.cada450527f8ceb0f451.js","entryType":"resource","startTime":1067.1000000238419,"duration":22.799999952316284,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1067.1000000238419,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1089.8999999761581,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_views_onboarding_setupDocs_tsx.e47b4c53ba4bbfa504e7.js","entryType":"resource","startTime":1067.3000000715256,"duration":14.099999904632568,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1067.3000000715256,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1081.3999999761581,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_views_organizationStats_usageStatsOrg_tsx.d3d29fe5626988e28762.js","entryType":"resource","startTime":1067.3999999761581,"duration":14.300000071525574,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1067.3999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1081.7000000476837,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/getsentry_static_getsentry_gsApp_registerHooks_tsx-app_components_codeSnippet_tsx-getsentry_s-61ae35.7e6a34df145cbecac219.js","entryType":"resource","startTime":1067.3999999761581,"duration":19.90000009536743,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1067.3999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1087.3000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/getsentry_static_getsentry_gsApp_initializeBundleMetrics_tsx.9fe7b144490c0ce9c4c6.js","entryType":"resource","startTime":1067.6000000238419,"duration":14.700000047683716,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1067.6000000238419,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1082.3000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/node_modules_emotion_unitless_dist_emotion-unitless_esm_js-app_bootstrap_initializeMain_tsx-n-f02164.cb9d501fc041dc503ed2.js","entryType":"resource","startTime":1067.6000000238419,"duration":21.700000047683716,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1067.6000000238419,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1089.3000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_plugins_index_tsx.929e41736b0670e5e0ba.js","entryType":"resource","startTime":1226.1000000238419,"duration":1.399999976158142,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1226.1000000238419,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1227.5,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://s1.sentry-cdn.com/_static/dist/sentry/chunks/app_bootstrap_initializeApp_tsx.1cbf31514ffcc3a3528f.js","entryType":"resource","startTime":1226.2000000476837,"duration":1.7999999523162842,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1226.2000000476837,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1228,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"sentry-tracing-init","entryType":"mark","startTime":1243,"duration":0},{"name":"https://o1.ingest.sentry.io/api/11276/envelope/?sentry_key=c51734c603c4430eb57cb0a5728a479d&sentry_version=7&sentry_client=sentry.javascript.react%2F7.46.0","entryType":"resource","startTime":1247.8999999761581,"duration":74.10000002384186,"initiatorType":"fetch","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1247.8999999761581,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1322,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":200,"serverTiming":[]},{"name":"sentry-app-init","entryType":"mark","startTime":1248,"duration":0},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/?detailed=0","entryType":"resource","startTime":1259.7000000476837,"duration":262.2999999523163,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1259.7000000476837,"domainLookupStart":1259.7000000476837,"domainLookupEnd":1259.7000000476837,"connectStart":1259.7000000476837,"secureConnectionStart":1259.7000000476837,"connectEnd":1259.7000000476837,"requestStart":1260.8999999761581,"responseStart":1520.7000000476837,"responseEnd":1522,"transferSize":4982,"encodedBodySize":4682,"decodedBodySize":15837,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/projects/?all_projects=1&collapse=latestDeploys","entryType":"resource","startTime":1260.1000000238419,"duration":611.7999999523163,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1260.1000000238419,"domainLookupStart":1262.3999999761581,"domainLookupEnd":1262.3999999761581,"connectStart":1262.3999999761581,"secureConnectionStart":1293.6000000238419,"connectEnd":1332.6000000238419,"requestStart":1333,"responseStart":1870.7000000476837,"responseEnd":1871.8999999761581,"transferSize":23383,"encodedBodySize":23083,"decodedBodySize":148289,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/teams/","entryType":"resource","startTime":1260.3000000715256,"duration":547.6999999284744,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1260.3000000715256,"domainLookupStart":1261.2000000476837,"domainLookupEnd":1261.2000000476837,"connectStart":1261.2000000476837,"secureConnectionStart":1294,"connectEnd":1332.8000000715256,"requestStart":1333.1000000238419,"responseStart":1806.7000000476837,"responseEnd":1808,"transferSize":18228,"encodedBodySize":17928,"decodedBodySize":205169,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/organizations/?member=1","entryType":"resource","startTime":1261.3999999761581,"duration":371.40000009536743,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1261.3999999761581,"domainLookupStart":1263.2000000476837,"domainLookupEnd":1263.2000000476837,"connectStart":1263.2000000476837,"secureConnectionStart":1295.3000000715256,"connectEnd":1332.8999999761581,"requestStart":1333.2000000476837,"responseStart":1631.8000000715256,"responseEnd":1632.8000000715256,"transferSize":3486,"encodedBodySize":3186,"decodedBodySize":28039,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/internal/health/","entryType":"resource","startTime":1261.6000000238419,"duration":128.39999997615814,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1261.6000000238419,"domainLookupStart":1262.2000000476837,"domainLookupEnd":1262.3000000715256,"connectStart":1262.3000000715256,"secureConnectionStart":1295.3999999761581,"connectEnd":1332.8999999761581,"requestStart":1333.2000000476837,"responseStart":1388.7000000476837,"responseEnd":1390,"transferSize":300,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/assistant/","entryType":"resource","startTime":1262.5,"duration":158.39999997615814,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1262.5,"domainLookupStart":1262.8999999761581,"domainLookupEnd":1262.8999999761581,"connectStart":1262.8999999761581,"secureConnectionStart":1295,"connectEnd":1332.8999999761581,"requestStart":1333.3000000715256,"responseStart":1419.2000000476837,"responseEnd":1420.8999999761581,"transferSize":1009,"encodedBodySize":709,"decodedBodySize":709,"responseStatus":200,"serverTiming":[]},{"name":"@grammarly-extension:checkScriptInitStart","entryType":"mark","startTime":1302.8000000715256,"duration":0},{"name":"@grammarly-extension:checkScriptInitEnd","entryType":"mark","startTime":1303.8000000715256,"duration":0},{"name":"https://js.stripe.com/v3/m-outer-93afeeb17bc37e711759584dbfc50d47.html#url=https%3A%2F%2Fsentry.sentry.io%2Fissues%2F&title=Sentry&referrer=&muid=78f25c63-c9aa-49b3-b21e-d24aa1a9e8a524eeea&sid=NA&version=6&preview=false","entryType":"resource","startTime":1316.5,"duration":5.899999976158142,"initiatorType":"iframe","nextHopProtocol":"h2","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1316.5,"domainLookupStart":1316.5,"domainLookupEnd":1316.5,"connectStart":1316.5,"secureConnectionStart":1316.5,"connectEnd":1316.5,"requestStart":1319.3000000715256,"responseStart":1319.7000000476837,"responseEnd":1322.3999999761581,"transferSize":0,"encodedBodySize":122,"decodedBodySize":200,"responseStatus":0,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/client-state/","entryType":"resource","startTime":1523.8000000715256,"duration":247.5,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1523.8000000715256,"domainLookupStart":1523.8000000715256,"domainLookupEnd":1523.8000000715256,"connectStart":1523.8000000715256,"secureConnectionStart":1523.8000000715256,"connectEnd":1523.8000000715256,"requestStart":1524.6000000238419,"responseStart":1770.5,"responseEnd":1771.3000000715256,"transferSize":302,"encodedBodySize":2,"decodedBodySize":2,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/subscriptions/sentry/","entryType":"resource","startTime":1538.5,"duration":238.20000004768372,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1538.5,"domainLookupStart":1538.5,"domainLookupEnd":1538.5,"connectStart":1538.5,"secureConnectionStart":1538.5,"connectEnd":1538.5,"requestStart":1541.8999999761581,"responseStart":1775.3000000715256,"responseEnd":1776.7000000476837,"transferSize":2094,"encodedBodySize":1794,"decodedBodySize":5762,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/broadcasts/","entryType":"resource","startTime":1538.8999999761581,"duration":238.20000004768372,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1538.8999999761581,"domainLookupStart":1538.8999999761581,"domainLookupEnd":1538.8999999761581,"connectStart":1538.8999999761581,"secureConnectionStart":1538.8999999761581,"connectEnd":1538.8999999761581,"requestStart":1633,"responseStart":1775.3000000715256,"responseEnd":1777.1000000238419,"transferSize":1105,"encodedBodySize":805,"decodedBodySize":805,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/promotions/trigger-check/","entryType":"resource","startTime":1540.7000000476837,"duration":139.79999995231628,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1540.7000000476837,"domainLookupStart":1540.7000000476837,"domainLookupEnd":1540.7000000476837,"connectStart":1540.7000000476837,"secureConnectionStart":1540.7000000476837,"connectEnd":1540.7000000476837,"requestStart":1542.2000000476837,"responseStart":1680,"responseEnd":1680.5,"transferSize":398,"encodedBodySize":98,"decodedBodySize":98,"responseStatus":200,"serverTiming":[]},{"name":"https://t687h3m0nh65.statuspage.io/api/v2/incidents/unresolved.json","entryType":"resource","startTime":1541.1000000238419,"duration":130.89999997615814,"initiatorType":"fetch","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1541.1000000238419,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1672,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/tags/?statsPeriod=14d&use_cache=1","entryType":"resource","startTime":1544.3000000715256,"duration":1457.3999999761581,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1544.3000000715256,"domainLookupStart":1544.3000000715256,"domainLookupEnd":1544.3000000715256,"connectStart":1544.3000000715256,"secureConnectionStart":1544.3000000715256,"connectEnd":1544.3000000715256,"requestStart":1680.8000000715256,"responseStart":2996.100000023842,"responseEnd":3001.7000000476837,"transferSize":7419,"encodedBodySize":7119,"decodedBodySize":25782,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/users/","entryType":"resource","startTime":1544.6000000238419,"duration":2509.7999999523163,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1544.6000000238419,"domainLookupStart":1544.6000000238419,"domainLookupEnd":1544.6000000238419,"connectStart":1544.6000000238419,"secureConnectionStart":1544.6000000238419,"connectEnd":1544.6000000238419,"requestStart":1771.7000000476837,"responseStart":3961.8000000715256,"responseEnd":4054.399999976158,"transferSize":45219,"encodedBodySize":44919,"decodedBodySize":261770,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/searches/","entryType":"resource","startTime":1544.8999999761581,"duration":374.5,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1544.8999999761581,"domainLookupStart":1544.8999999761581,"domainLookupEnd":1544.8999999761581,"connectStart":1544.8999999761581,"secureConnectionStart":1544.8999999761581,"connectEnd":1544.8999999761581,"requestStart":1777.3999999761581,"responseStart":1918.6000000238419,"responseEnd":1919.3999999761581,"transferSize":1445,"encodedBodySize":1145,"decodedBodySize":4268,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/organization-avatar/24f6f762f7a7473888b259c566da5adb/?s=120","entryType":"resource","startTime":1545.3000000715256,"duration":290.7999999523163,"initiatorType":"img","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1545.3000000715256,"domainLookupStart":1545.3000000715256,"domainLookupEnd":1545.3000000715256,"connectStart":1545.3000000715256,"secureConnectionStart":1545.3000000715256,"connectEnd":1545.3000000715256,"requestStart":1777.5,"responseStart":1835.3999999761581,"responseEnd":1836.1000000238419,"transferSize":6603,"encodedBodySize":6303,"decodedBodySize":6303,"responseStatus":200,"serverTiming":[]},{"name":"https://o1.ingest.sentry.io/api/11276/envelope/?sentry_key=c51734c603c4430eb57cb0a5728a479d&sentry_version=7&sentry_client=sentry.javascript.react%2F7.46.0","entryType":"resource","startTime":1600,"duration":38.300000071525574,"initiatorType":"fetch","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1600,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":1638.3000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/prompts-activity/?feature=deactivated_member_alert&feature=errors_overage_alert&feature=attachments_overage_alert&feature=transactions_overage_alert&feature=replays_overage_alert&feature=errors_warning_alert&feature=attachments_warning_alert&feature=transactions_warning_alert&feature=replays_warning_alert&organization_id=1","entryType":"resource","startTime":1780.8999999761581,"duration":91.60000002384186,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1780.8999999761581,"domainLookupStart":1780.8999999761581,"domainLookupEnd":1780.8999999761581,"connectStart":1780.8999999761581,"secureConnectionStart":1780.8999999761581,"connectEnd":1780.8999999761581,"requestStart":1808.3000000715256,"responseStart":1872.2000000476837,"responseEnd":1872.5,"transferSize":315,"encodedBodySize":15,"decodedBodySize":15,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/pendo-details/","entryType":"resource","startTime":1791.5,"duration":219.5,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1791.5,"domainLookupStart":1791.5,"domainLookupEnd":1791.5,"connectStart":1791.5,"secureConnectionStart":1791.5,"connectEnd":1791.5,"requestStart":1836.3999999761581,"responseStart":2010.2000000476837,"responseEnd":2011,"transferSize":1092,"encodedBodySize":792,"decodedBodySize":792,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/processingissues/","entryType":"resource","startTime":1962.7000000476837,"duration":235.39999997615814,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1962.7000000476837,"domainLookupStart":1962.7000000476837,"domainLookupEnd":1962.7000000476837,"connectStart":1962.7000000476837,"secureConnectionStart":1962.7000000476837,"connectEnd":1962.7000000476837,"requestStart":1963.7000000476837,"responseStart":2196.5,"responseEnd":2198.100000023842,"transferSize":676,"encodedBodySize":376,"decodedBodySize":3988,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/issues/?collapse=stats&expand=owners&expand=inbox&limit=25&query=is%3Aunresolved&shortIdLookup=1&statsPeriod=14d","entryType":"resource","startTime":1963.3000000715256,"duration":314.5,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":1963.3000000715256,"domainLookupStart":1963.3000000715256,"domainLookupEnd":1963.3000000715256,"connectStart":1963.3000000715256,"secureConnectionStart":1963.3000000715256,"connectEnd":1963.3000000715256,"requestStart":1963.8999999761581,"responseStart":2275.7000000476837,"responseEnd":2277.8000000715256,"transferSize":5092,"encodedBodySize":4792,"decodedBodySize":27778,"responseStatus":200,"serverTiming":[]},{"name":"https://data.pendo.io/data/ptm.gif/dc5c6fad-c3ae-4441-49ce-0ae37103aed7?v=2.181.0_prod&ct=1682429095854&jzb=eJwtj81qwzAQhN9lz8a2_KPKPpdAoJAWUnooJcixQmQcS6xWLibk3bN1rYtWMzv6mO870OINtDA63UMCHbrfYPBE9saqkKqoiiZvalU1Ccw2WHJ4sj0HRCpkpQpZckqfzy5OtBksRBx5uhL50GZZMBPhkm6XdZkNIZqQ8aJH5wO095W_UVWdp2WznhcpaiUevKeR00fd7RkxxXFMgP4fcCx28eNd7N6G2WtzqPjXC-qbWc3XfP4U-dD1l3L_Ja7yr-JChpFc7PHzBAHgTzM","entryType":"resource","startTime":2030.8000000715256,"duration":123.19999992847443,"initiatorType":"img","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":2030.8000000715256,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":2154,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://data.pendo.io/data/guide.js/dc5c6fad-c3ae-4441-49ce-0ae37103aed7?id=4&jzb=eJxtVE1zo0gM_S-csQ3kYzK-eexkK1WTneyQvezFJdMCK2m6KXXDlHdr_vuoAUPGmxP0k1p6kp76v6gjR97yo4rWUbpMb6_vsturKI6gKGxr_IDLuWUtf0fvG7derRwaz6fl-CG7IudadCtxrNGDAg_RegoefukyQetwzDpBbDUKAKomI0dyO-C3J6sELEE7jCOn3v6EGp14jbkrG49_r9CBK5gavzyw_SHh4-oIi8H6gRMjFP6MNyd_tGapXsFMEReFpgt7qcG9fRDLBJJxdASXi-2FwTgJTtYIU8-tMB9NOTr3AfwdGw2n9-gTeqZio5H9BBeS5dsPg-y2YTbR-iaOGravWPgRyK7iqCR2_r4LPKgO_cySNFsk6SK9fsmydXK3vsmWn9L0Lvn8T9_leyON16geTV5LrnOr6yELn7b9BEyrdc_sGbm0XIMp8LGf-jvWz2xL0hM-hurF0ZfyvdU4Ur39NFbfN2RowDmSlim0UAXyaPZ_fIl-ToKctdRzf2Cc1UHuCYxcE_MQh9wLE4hwJ4d745EbJoeXlndlPUv-S3PeugaNCrFHrLh0EiBHXebI3cxJyjJB03W2P7SOjJS7l9HsoS2lgGB9IZQNCR7DNID1aaNsI0TPdXjrQT9hfZDRi2tHsig-LAyKyjtU98y2t7Dwm-HfdThfAw4JB9-xrVs5kTR3REV7oHeiyK9YCjrM3nIFhv6FEG8ThnOV3IjeZIjfzA6lcyoPLZr7IWlJIT9Y3rm_G4daejUUFEh1KGqpbYh2ziBiHoA59SINgepGmKOaLoRyhGYp0--VPtD__Ra5r-D89lRoFAZBKL3rLEsl7jmFeZ_DbjXIykgFfdbWeVsj72wNNG8siYIq7pvQP0Maire4In9sD_ErMcSNKJBV609xh1ygnoHQ7tYfJV0X-hKuV9ZW8ugFMu54sMBqXI_0cyIgucJKlBxkmn-1GHaxt17filUa_4W0JlNtlJKZz5X9z_KA4FuWkV1sqni8w4a35UhNWNOxYNm8Blj6tpn2TyB54PuX5WaVXK-yJAuvt_AMmxzgZXqXLpO9jFNFP3_-Ams9Pkk&v=2.181.0_prod&ct=1682429095856","entryType":"resource","startTime":2032.7000000476837,"duration":142.10000002384186,"initiatorType":"script","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":2032.7000000476837,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":2174.8000000715256,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":0,"serverTiming":[]},{"name":"https://reload.getsentry.net/metric/","entryType":"resource","startTime":2270.2000000476837,"duration":38.199999928474426,"initiatorType":"xmlhttprequest","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":2270.2000000476837,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":2308.399999976158,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":201,"serverTiming":[]},{"name":"IssueList-Body-vcsd-start","entryType":"mark","startTime":2295.2000000476837,"duration":0},{"name":"IssueList-Body-vcsd-end-pre-timeout","entryType":"mark","startTime":2297,"duration":0},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/issues-stats/?groups=3622378978&groups=4050674861&groups=3899312585&groups=3915010727&groups=3899249705&groups=4057453162&groups=3935262512&groups=3935139508&groups=4057455327&groups=4012287646&groups=3920436468&groups=3991114523&groups=4046641574&groups=4090532740&groups=3670893465&groups=3899249419&groups=4077639192&groups=4074870668&groups=3899261560&groups=3919710734&groups=3248727627&groups=4113029290&groups=3911631555&groups=3740335939&groups=3899257705&query=is%3Aunresolved&statsPeriod=14d","entryType":"resource","startTime":2304.5,"duration":696.6000000238419,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":2304.5,"domainLookupStart":2304.5,"domainLookupEnd":2304.5,"connectStart":2304.5,"secureConnectionStart":2304.5,"connectEnd":2304.5,"requestStart":2305.7000000476837,"responseStart":2995.399999976158,"responseEnd":3001.100000023842,"transferSize":4468,"encodedBodySize":4168,"decodedBodySize":17200,"responseStatus":200,"serverTiming":[]},{"name":"IssueList-Body-vcsd-start","entryType":"mark","startTime":2314.5,"duration":0},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/issues-count/?query=is%3Aunresolved%20is%3Afor_review%20assigned_or_suggested%3A%5Bme%2C%20none%5D&query=is%3Aignored&query=is%3Areprocessing&statsPeriod=14d","entryType":"resource","startTime":2320.399999976158,"duration":707.3000000715256,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":2320.399999976158,"domainLookupStart":2320.399999976158,"domainLookupEnd":2320.399999976158,"connectStart":2320.399999976158,"secureConnectionStart":2320.399999976158,"connectEnd":2320.399999976158,"requestStart":2321.399999976158,"responseStart":3026.3000000715256,"responseEnd":3027.7000000476837,"transferSize":405,"encodedBodySize":105,"decodedBodySize":105,"responseStatus":200,"serverTiming":[]},{"name":"IssueList-Body-vcsd-start","entryType":"mark","startTime":2328.3000000715256,"duration":0},{"name":"https://sentry.sentry.io/api/0/organizations/sentry/replay-count/?project=11276&query=issue.id%3A%5B3740335939%5D&statsPeriod=14d","entryType":"resource","startTime":2386,"duration":166.30000007152557,"initiatorType":"fetch","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":2386,"domainLookupStart":2386,"domainLookupEnd":2386,"connectStart":2386,"secureConnectionStart":2386,"connectEnd":2386,"requestStart":2388.7000000476837,"responseStart":2551.600000023842,"responseEnd":2552.3000000715256,"transferSize":317,"encodedBodySize":17,"decodedBodySize":17,"responseStatus":200,"serverTiming":[]},{"name":"IssueList-Body-vcsd-start","entryType":"mark","startTime":2399.100000023842,"duration":0},{"name":"VCD [IssueList-Body] #1","entryType":"measure","startTime":2399.100000023842,"duration":50},{"name":"IssueList-Body-vcsd-end","entryType":"mark","startTime":2449.100000023842,"duration":0},{"name":"https://api2.amplitude.com/2/httpapi","entryType":"resource","startTime":2457,"duration":542.3999999761581,"initiatorType":"fetch","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":2457,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":2999.399999976158,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":200,"serverTiming":[]},{"name":"https://reload.getsentry.net/event/","entryType":"resource","startTime":3219.7000000476837,"duration":33.89999997615814,"initiatorType":"xmlhttprequest","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":3219.7000000476837,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":3253.600000023842,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":201,"serverTiming":[]},{"name":"IssueList-Body-vcsd-start","entryType":"mark","startTime":3251.100000023842,"duration":0},{"name":"https://reload.getsentry.net/metric/","entryType":"resource","startTime":3316.2000000476837,"duration":36.799999952316284,"initiatorType":"xmlhttprequest","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":3316.2000000476837,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":3353,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":201,"serverTiming":[]},{"name":"IssueList-Body-vcsd-start","entryType":"mark","startTime":3326.7000000476837,"duration":0},{"name":"keydown","entryType":"first-input","startTime":4007.899999976158,"duration":8,"processingStart":4011.600000023842,"processingEnd":4013,"cancelable":true},{"name":"IssueList-Body-vcsd-start","entryType":"mark","startTime":4077.600000023842,"duration":0},{"name":"https://sentry.sentry.io/avatar/ca66558c539e408eaaa450a096e24ebf/?s=120","entryType":"resource","startTime":4166,"duration":92.5,"initiatorType":"img","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":4166,"domainLookupStart":4166,"domainLookupEnd":4166,"connectStart":4166,"secureConnectionStart":4166,"connectEnd":4166,"requestStart":4168.300000071526,"responseStart":4255.200000047684,"responseEnd":4258.5,"transferSize":6105,"encodedBodySize":5805,"decodedBodySize":5805,"responseStatus":200,"serverTiming":[]},{"name":"https://sentry.sentry.io/avatar/ba59b4e18344480794c5a623dbf6ef6a/?s=120","entryType":"resource","startTime":4166.100000023842,"duration":101,"initiatorType":"img","nextHopProtocol":"http/1.1","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":4166.100000023842,"domainLookupStart":4166.100000023842,"domainLookupEnd":4166.100000023842,"connectStart":4166.100000023842,"secureConnectionStart":4166.100000023842,"connectEnd":4166.100000023842,"requestStart":4167.700000047684,"responseStart":4266.5,"responseEnd":4267.100000023842,"transferSize":21805,"encodedBodySize":21505,"decodedBodySize":21505,"responseStatus":200,"serverTiming":[]},{"name":"IssueList-Body-vcsd-start","entryType":"mark","startTime":4175,"duration":0},{"name":"https://api2.amplitude.com/2/httpapi","entryType":"resource","startTime":4317,"duration":258.7000000476837,"initiatorType":"fetch","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":4317,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":4575.700000047684,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":200,"serverTiming":[]},{"name":"https://reload.getsentry.net/metric/","entryType":"resource","startTime":4323.800000071526,"duration":34.799999952316284,"initiatorType":"xmlhttprequest","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":4323.800000071526,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":4358.600000023842,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":201,"serverTiming":[]},{"name":"https://o1.ingest.sentry.io/api/11276/envelope/?sentry_key=c51734c603c4430eb57cb0a5728a479d&sentry_version=7&sentry_client=sentry.javascript.react%2F7.46.0","entryType":"resource","startTime":4454.5,"duration":75.39999997615814,"initiatorType":"fetch","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":4454.5,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":4529.899999976158,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":200,"serverTiming":[]},{"name":"https://o1.ingest.sentry.io/api/11276/envelope/?sentry_key=c51734c603c4430eb57cb0a5728a479d&sentry_version=7&sentry_client=sentry.javascript.react%2F7.46.0","entryType":"resource","startTime":5931.800000071526,"duration":69.19999992847443,"initiatorType":"fetch","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":5931.800000071526,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":6001,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":200,"serverTiming":[]},{"name":"https://o1.ingest.sentry.io/api/11276/envelope/?sentry_key=c51734c603c4430eb57cb0a5728a479d&sentry_version=7&sentry_client=sentry.javascript.react%2F7.46.0","entryType":"resource","startTime":9973.300000071526,"duration":45.09999990463257,"initiatorType":"fetch","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":9973.300000071526,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":10018.399999976158,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":200,"serverTiming":[]},{"name":"https://o1.ingest.sentry.io/api/11276/envelope/?sentry_key=c51734c603c4430eb57cb0a5728a479d&sentry_version=7&sentry_client=sentry.javascript.react%2F7.46.0","entryType":"resource","startTime":68177.70000004768,"duration":100.19999992847443,"initiatorType":"fetch","nextHopProtocol":"","renderBlockingStatus":"non-blocking","workerStart":0,"redirectStart":0,"redirectEnd":0,"fetchStart":68177.70000004768,"domainLookupStart":0,"domainLookupEnd":0,"connectStart":0,"secureConnectionStart":0,"connectEnd":0,"requestStart":0,"responseStart":0,"responseEnd":68277.89999997616,"transferSize":0,"encodedBodySize":0,"decodedBodySize":0,"responseStatus":200,"serverTiming":[]}]', -); - -const half = data.slice(0, Math.round(data.length / 2)); -// add tests -new Benchmark.Suite() - .add('new list (old)', function () { - const entries = fns.dedupePerformanceEntries([], data); - }) - .add('new list (new)', function () { - const entries = fnsNew.dedupePerformanceEntries([], data); - }) - .add('diff list half (old)', function () { - const entries = fns.dedupePerformanceEntries(half, data); - }) - .add('diff list half (new)', function () { - const entries = fnsNew.dedupePerformanceEntries(half, data); - }) - .add('same list (old)', function () { - const entries = fns.dedupePerformanceEntries(data, data); - }) - .add('same list half (new)', function () { - const entries = fnsNew.dedupePerformanceEntries(data, data); - }) - // @ts-ignore - .on('error', function (event) { - // @ts-ignore - console.log(event.target.error); - }) - // @ts-ignore - .on('cycle', function (event) { - // @ts-ignore - console.log(String(event.target)); - }) - .on('complete', function () { - // @ts-ignore - console.log(`Fastest is ${this.filter('fastest').map('name')}`); - }) - .run({ async: false }); - -module.exports = {}; diff --git a/packages/replay/src/util/dedupePerformanceEntries.new.ts b/packages/replay/src/util/dedupePerformanceEntries.new.ts deleted file mode 100644 index 94d430a78182..000000000000 --- a/packages/replay/src/util/dedupePerformanceEntries.new.ts +++ /dev/null @@ -1,102 +0,0 @@ -import type { PerformanceNavigationTiming, PerformancePaintTiming } from '../types'; - -const NAVIGATION_ENTRY_KEYS: Array = [ - 'name', - 'type', - 'startTime', - 'transferSize', - 'duration', -]; - -/** - * There are some difficulties diagnosing why there are duplicate navigation - * entries. We've witnessed several intermittent results: - * - duplicate entries have duration = 0 - * - duplicate entries are the same object reference - * - none of the above - * - * Compare the values of several keys to determine if the entries are duplicates or not. - */ -// TODO (high-prio): Figure out wth is returned here -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type -function dedupePerformanceEntries( - currentList: PerformanceEntryList, - newList: PerformanceEntryList, -): PerformanceEntryList { - if (!currentList.length && !newList.length) { - return []; - } - - // if (currentList.length === 0) { - // return newList.slice().sort((a, b) => a.startTime - b.startTime); - // } - - // Partition `currentList` into 3 different lists based on entryType - const [existingNavigationEntries, existingLcpEntries, existingEntries] = currentList.reduce( - (acc: [PerformanceNavigationTiming[], PerformancePaintTiming[], PerformanceEntryList], entry) => { - if (entry.entryType === 'navigation') { - acc[0].push(entry as PerformanceNavigationTiming); - } else if (entry.entryType === 'largest-contentful-paint') { - acc[1].push(entry as PerformancePaintTiming); - } else { - acc[2].push(entry); - } - return acc; - }, - [[], [], []], - ); - - const newEntries: PerformanceEntryList = []; - const newNavigationEntries: PerformanceNavigationTiming[] = []; - let newLcpEntry: PerformancePaintTiming | undefined = existingLcpEntries[existingLcpEntries.length - 1]; // Take the last element as list is sorted - let foundNewLcp = false; - - for (let i = newList.length - 1; i >= 0; i--) { - const entry = newList[i]; - if (entry.entryType !== 'navigation' && entry.entryType !== 'largest-contentful-paint') { - newEntries.push(entry); - continue; - } - - if (entry.entryType === 'navigation') { - const navigationEntry = entry as PerformanceNavigationTiming; - - if (entry.duration <= 0) { - // Ignore any navigation entries with duration 0, as they are likely duplicates - continue; - } - - // Check if the navigation entry is contained in currentList or newList - if ( - // Ensure new entry does not already exist in existing entries - !existingNavigationEntries.find(a => { - return a === navigationEntry || NAVIGATION_ENTRY_KEYS.every(key => a[key] === navigationEntry[key]); - }) && - // Ensure new entry does not already exist in new list of navigation entries - !newNavigationEntries.find(a => { - return a === navigationEntry || NAVIGATION_ENTRY_KEYS.every(key => a[key] === navigationEntry[key]); - }) - ) { - newNavigationEntries.push(navigationEntry); - } - - // Otherwise this navigation entry is considered a duplicate and is thrown away - continue; - } - - if (entry.entryType === 'largest-contentful-paint' && !foundNewLcp) { - // We want the latest LCP event only - if (!newLcpEntry || newLcpEntry.startTime < entry.startTime) { - newLcpEntry = entry; - foundNewLcp = true; - } - continue; - } - } - - return newEntries - .concat(newNavigationEntries, existingEntries, existingNavigationEntries, newLcpEntry ? [newLcpEntry] : []) - .sort((a, b) => a.startTime - b.startTime); -} - -exports.dedupePerformanceEntries = dedupePerformanceEntries;