From 1f183922570600544aea4f7390e23435be9f493d Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Sat, 18 Nov 2023 09:16:40 +0000 Subject: [PATCH 01/18] feat: network payload capture draft 2 --- frontend/src/loadPostHogJS.tsx | 7 +- .../components/ItemPerformanceEvent.tsx | 17 +- .../inspector/performance-event-utils.ts | 154 +++++++++--------- frontend/src/types.ts | 4 + 4 files changed, 103 insertions(+), 79 deletions(-) diff --git a/frontend/src/loadPostHogJS.tsx b/frontend/src/loadPostHogJS.tsx index 2acd266241f82..c75b17774ea01 100644 --- a/frontend/src/loadPostHogJS.tsx +++ b/frontend/src/loadPostHogJS.tsx @@ -27,9 +27,10 @@ export function loadPostHogJS(): void { bootstrap: window.POSTHOG_USER_IDENTITY_WITH_FLAGS ? window.POSTHOG_USER_IDENTITY_WITH_FLAGS : {}, opt_in_site_apps: true, loaded: (posthog) => { - if (posthog.webPerformance) { - posthog.webPerformance._forceAllowLocalhost = true - } + // TODO we still need to do this? + // if (posthog.webPerformance) { + // posthog.webPerformance._forceAllowLocalhost = true + // } if (window.IMPERSONATED_SESSION) { posthog.opt_out_capturing() diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx b/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx index 96c4a9e01a143..b001cab2d80be 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx +++ b/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx @@ -140,7 +140,7 @@ export function ItemPerformanceEvent({ expanded, setExpanded, }: ItemPerformanceEvent): JSX.Element { - const [activeTab, setActiveTab] = useState<'timings' | 'headers' | 'payload' | 'response_body'>('timings') + const [activeTab, setActiveTab] = useState<'timings' | 'headers' | 'payload' | 'response_body' | 'raw'>('timings') const bytes = humanizeBytes(item.encoded_body_size || item.decoded_body_size || 0) const startTime = item.start_time || item.fetch_start || 0 @@ -176,7 +176,11 @@ export function ItemPerformanceEvent({ return acc } - if (['response_headers', 'request_headers', 'request_body', 'response_body', 'response_status'].includes(key)) { + if ( + ['response_headers', 'request_headers', 'request_body', 'response_body', 'response_status', 'raw'].includes( + key + ) + ) { return acc } @@ -392,6 +396,15 @@ export function ItemPerformanceEvent({ ), } : false, + { + key: 'raw', + label: 'Json', + content: ( + + {JSON.stringify(item.raw, null, 2)} + + ), + }, ]} /> diff --git a/frontend/src/scenes/session-recordings/player/inspector/performance-event-utils.ts b/frontend/src/scenes/session-recordings/player/inspector/performance-event-utils.ts index 51d9770d0e41f..f3732a28bf3e9 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/performance-event-utils.ts +++ b/frontend/src/scenes/session-recordings/player/inspector/performance-event-utils.ts @@ -1,10 +1,8 @@ import { eventWithTime } from '@rrweb/types' -import posthog from 'posthog-js' import { PerformanceEvent } from '~/types' const NETWORK_PLUGIN_NAME = 'posthog/network@1' const RRWEB_NETWORK_PLUGIN_NAME = 'rrweb/network@1' -const IGNORED_POSTHOG_PATHS = ['/s/', '/e/', '/i/v0/e/'] export const PerformanceEventReverseMapping: { [key: number]: keyof PerformanceEvent } = { // BASE_PERFORMANCE_EVENT_COLUMNS @@ -58,8 +56,72 @@ export const PerformanceEventReverseMapping: { [key: number]: keyof PerformanceE 40: 'timestamp', } +export const RRWebPerformanceEventReverseMapping: Record = { + // BASE_PERFORMANCE_EVENT_COLUMNS + entryType: 'entry_type', + timeOrigin: 'time_origin', + name: 'name', + + // RESOURCE_EVENT_COLUMNS + startTime: 'start_time', + redirectStart: 'redirect_start', + redirectEnd: 'redirect_end', + workerStart: 'worker_start', + fetchStart: 'fetch_start', + domainLookupStart: 'domain_lookup_start', + domainLookupEnd: 'domain_lookup_end', + connectStart: 'connect_start', + secureConnectionStart: 'secure_connection_start', + connectEnd: 'connect_end', + requestStart: 'request_start', + responseStart: 'response_start', + responseEnd: 'response_end', + decodedBodySize: 'decoded_body_size', + encodedBodySize: 'encoded_body_size', + initiatorType: 'initiator_type', + nextHopProtocol: 'next_hop_protocol', + renderBlockingStatus: 'render_blocking_status', + responseStatus: 'response_status', + transferSize: 'transfer_size', + + // LARGEST_CONTENTFUL_PAINT_EVENT_COLUMNS + largestContentfulPaintElement: 'largest_contentful_paint_element', + largestContentfulPaintRenderTime: 'largest_contentful_paint_render_time', + largestContentfulPaintLoadTime: 'largest_contentful_paint_load_time', + largestContentfulPaintSize: 'largest_contentful_paint_size', + largestContentfulPaintId: 'largest_contentful_paint_id', + largestContentfulPaintUrl: 'largest_contentful_paint_url', + + // NAVIGATION_EVENT_COLUMNS + domComplete: 'dom_complete', + domContentLoadedEvent: 'dom_content_loaded_event', + domInteractive: 'dom_interactive', + loadEventEnd: 'load_event_end', + loadEventStart: 'load_event_start', + redirectCount: 'redirect_count', + navigationType: 'navigation_type', + unloadEventEnd: 'unload_event_end', + unloadEventStart: 'unload_event_start', + + // Added after v1 + duration: 'duration', + timestamp: 'timestamp', + + //rrweb/network@1 + isInitial: 'is_initial', + requestHeaders: 'request_headers', + responseHeaders: 'response_headers', + requestBody: 'request_body', + responseBody: 'response_body', + method: 'method', +} + export function matchNetworkEvents(snapshotsByWindowId: Record): PerformanceEvent[] { - const eventsMapping: Record> = {} + // we only support rrweb/network@1 events or posthog/network@1 events in any one recording + // apart from during testing, where we might have both + // if we have both, we only display posthog/network@1 events + const events: PerformanceEvent[] = [] + const rrwebEvents: PerformanceEvent[] = [] // we could do this in one pass, but it's easier to log missing events // when we have all the posthog/network@1 events first @@ -83,93 +145,37 @@ export function matchNetworkEvents(snapshotsByWindowId: Record { - const snapshots = snapshotsByWindowId[1] - snapshots.forEach((snapshot: eventWithTime) => { if ( snapshot.type === 6 && // RRWeb plugin event type snapshot.data.plugin === RRWEB_NETWORK_PLUGIN_NAME ) { const payload = snapshot.data.payload as any + if (!Array.isArray(payload.requests) || payload.requests.length === 0) { return } payload.requests.forEach((capturedRequest: any) => { - const matchedURL = eventsMapping[capturedRequest.url] - - const matchedStartTime = matchedURL ? matchedURL[capturedRequest.startTime] : null - - if (matchedStartTime && matchedStartTime.length === 1) { - matchedStartTime[0].response_status = capturedRequest.status - matchedStartTime[0].request_headers = capturedRequest.requestHeaders - matchedStartTime[0].request_body = capturedRequest.requestBody - matchedStartTime[0].response_headers = capturedRequest.responseHeaders - matchedStartTime[0].response_body = capturedRequest.responseBody - matchedStartTime[0].method = capturedRequest.method - } else if (matchedStartTime && matchedStartTime.length > 1) { - // find in eventsMapping[capturedRequest.url][capturedRequest.startTime] by matching capturedRequest.endTime and element.response_end - const matchedEndTime = matchedStartTime.find( - (x) => - typeof x.response_end === 'number' && - Math.round(x.response_end) === capturedRequest.endTime - ) - if (matchedEndTime) { - matchedEndTime.response_status = capturedRequest.status - matchedEndTime.request_headers = capturedRequest.requestHeaders - matchedEndTime.request_body = capturedRequest.requestBody - matchedEndTime.response_headers = capturedRequest.responseHeaders - matchedEndTime.response_body = capturedRequest.responseBody - matchedEndTime.method = capturedRequest.method - } else { - const capturedURL = new URL(capturedRequest.url) - const capturedPath = capturedURL.pathname - - if (!IGNORED_POSTHOG_PATHS.some((x) => capturedPath === x)) { - posthog.capture('Had matches but still could not match rrweb/network@1 event', { - rrwebNetworkEvent: payload, - possibleMatches: matchedStartTime, - totalMatchedURLs: Object.keys(eventsMapping).length, - }) - } - } - } else { - const capturedURL = new URL(capturedRequest.url) - const capturedPath = capturedURL.pathname - if (!IGNORED_POSTHOG_PATHS.some((x) => capturedPath === x)) { - posthog.capture('Could not match rrweb/network@1 event', { - rrwebNetworkEvent: payload, - possibleMatches: eventsMapping[capturedRequest.url], - totalMatchedURLs: Object.keys(eventsMapping).length, - }) - } + const data: Partial = { + timestamp: snapshot.timestamp, + window_id: windowId, + raw: capturedRequest, } + + Object.entries(RRWebPerformanceEventReverseMapping).forEach(([key, value]) => { + if (key in capturedRequest) { + data[value] = capturedRequest[key] + } + }) + + rrwebEvents.push(data as PerformanceEvent) }) } }) }) - // now flatten the eventsMapping into a single array - return Object.values(eventsMapping).reduce((acc: PerformanceEvent[], eventsByURL) => { - Object.values(eventsByURL).forEach((eventsByTime) => { - acc.push(...eventsByTime) - }) - return acc - }, []) + return events.length ? events : rrwebEvents } diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 4ff7c9c7dcbd9..eeab43aea2167 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -1149,6 +1149,10 @@ export interface PerformanceEvent { request_body?: Body response_body?: Body method?: string + + //rrweb/network@1 - i.e. not in ClickHouse table + is_initial?: boolean + raw?: Record } export interface CurrentBillCycleType { From c4408733813ee0fa1231efdf981188a466545ab0 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Sat, 18 Nov 2023 12:41:57 +0000 Subject: [PATCH 02/18] force allow local host --- frontend/src/loadPostHogJS.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/frontend/src/loadPostHogJS.tsx b/frontend/src/loadPostHogJS.tsx index c75b17774ea01..bcd03f327260a 100644 --- a/frontend/src/loadPostHogJS.tsx +++ b/frontend/src/loadPostHogJS.tsx @@ -27,10 +27,9 @@ export function loadPostHogJS(): void { bootstrap: window.POSTHOG_USER_IDENTITY_WITH_FLAGS ? window.POSTHOG_USER_IDENTITY_WITH_FLAGS : {}, opt_in_site_apps: true, loaded: (posthog) => { - // TODO we still need to do this? - // if (posthog.webPerformance) { - // posthog.webPerformance._forceAllowLocalhost = true - // } + if (posthog.sessionRecording) { + posthog.sessionRecording._forceAllowLocalhostNetworkCapture = true + } if (window.IMPERSONATED_SESSION) { posthog.opt_out_capturing() From 77287c7bedb1cb307785368d72e545a3086fe847 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Sat, 18 Nov 2023 12:42:11 +0000 Subject: [PATCH 03/18] Smaller button --- .../player/inspector/components/Timing/NetworkRequestTiming.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx index f77aeadf524dd..ddd7713eb1cd9 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx +++ b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx @@ -288,6 +288,7 @@ export const NetworkRequestTiming = ({
setTimelineMode(!timelineMode)} data-attr={`switch-timing-to-${timelineMode ? 'table' : 'timeline'}-view`} From d052a8436bb4b5278326ff49b13f7a4f8fb4b310 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Sat, 18 Nov 2023 15:08:52 +0000 Subject: [PATCH 04/18] correctly show when loading from cache --- .../components/ItemPerformanceEvent.tsx | 10 +- .../Timing/NetworkRequestTiming.tsx | 145 +++++++++++------- .../Timing/calculatePerformanceParts.test.ts | 74 +++++++++ .../inspector/performance-event-utils.ts | 35 +++-- 4 files changed, 193 insertions(+), 71 deletions(-) create mode 100644 frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx b/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx index b001cab2d80be..7b3f78a3daa9c 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx +++ b/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx @@ -483,6 +483,11 @@ function StatusRow({ item }: { item: PerformanceEvent }): JSX.Element | null { let statusRow = null let methodRow = null + let fromDiskCache = false + if (item.transfer_size === 0 && item.response_body) { + fromDiskCache = true + } + if (item.response_status) { const statusDescription = `${item.response_status} ${friendlyHttpStatus[item.response_status] || ''}` @@ -496,7 +501,10 @@ function StatusRow({ item }: { item: PerformanceEvent }): JSX.Element | null { statusRow = (
Status code
- {statusDescription} +
+ {statusDescription} + {fromDiskCache && (from cache)} +
) } diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx index ddd7713eb1cd9..72c5a5ee6c49b 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx +++ b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx @@ -3,7 +3,6 @@ import { getSeriesColor } from 'lib/colors' import { humanFriendlyMilliseconds } from 'lib/utils' import { Tooltip } from 'lib/lemon-ui/Tooltip' import { useState } from 'react' -import { LemonBanner } from 'lib/lemon-ui/LemonBanner' import { LemonDivider } from 'lib/lemon-ui/LemonDivider' import { SimpleKeyValueList } from 'scenes/session-recordings/player/inspector/components/SimpleKeyValueList' import { LemonButton } from 'lib/lemon-ui/LemonButton' @@ -67,6 +66,8 @@ function colorForSection(section: (typeof perfSections)[number]): string { } } +type PerformanceMeasures = Record + /** * There are defined sections to performance measurement. We may have data for some or all of them * @@ -109,79 +110,104 @@ function colorForSection(section: (typeof perfSections)[number]): string { * * see https://nicj.net/resourcetiming-in-practice/ */ -function calculatePerformanceParts(perfEntry: PerformanceEvent): Record { +export function calculatePerformanceParts(perfEntry: PerformanceEvent): PerformanceMeasures { const performanceParts: Record = {} - if (perfEntry.redirect_start && perfEntry.redirect_end) { - performanceParts['redirect'] = { - start: perfEntry.redirect_start, - end: perfEntry.redirect_end, - color: colorForSection('redirect'), + if (isPresent(perfEntry.redirect_start) && isPresent(perfEntry.redirect_end)) { + if (perfEntry.redirect_end - perfEntry.redirect_start > 0) { + performanceParts['redirect'] = { + start: perfEntry.redirect_start, + end: perfEntry.redirect_end, + color: colorForSection('redirect'), + } } } - if (perfEntry.fetch_start && perfEntry.domain_lookup_start) { - performanceParts['app cache'] = { - start: perfEntry.fetch_start, - end: perfEntry.domain_lookup_start, - color: colorForSection('app cache'), + if (isPresent(perfEntry.fetch_start) && isPresent(perfEntry.domain_lookup_start)) { + if (perfEntry.domain_lookup_start - perfEntry.fetch_start > 0) { + performanceParts['app cache'] = { + start: perfEntry.fetch_start, + end: perfEntry.domain_lookup_start, + color: colorForSection('app cache'), + } } } - if (perfEntry.domain_lookup_end && perfEntry.domain_lookup_start) { - performanceParts['dns lookup'] = { - start: perfEntry.domain_lookup_start, - end: perfEntry.domain_lookup_end, - color: colorForSection('dns lookup'), + if (isPresent(perfEntry.domain_lookup_end) && isPresent(perfEntry.domain_lookup_start)) { + if (perfEntry.domain_lookup_end - perfEntry.domain_lookup_start > 0) { + performanceParts['dns lookup'] = { + start: perfEntry.domain_lookup_start, + end: perfEntry.domain_lookup_end, + color: colorForSection('dns lookup'), + } } } - if (perfEntry.connect_end && perfEntry.connect_start) { - performanceParts['connection time'] = { - start: perfEntry.connect_start, - end: perfEntry.connect_end, - color: colorForSection('connection time'), - } - - if (perfEntry.secure_connection_start) { - performanceParts['tls time'] = { - start: perfEntry.secure_connection_start, + if (isPresent(perfEntry.connect_end) && isPresent(perfEntry.connect_start)) { + if (perfEntry.connect_end - perfEntry.connect_start > 0) { + performanceParts['connection time'] = { + start: perfEntry.connect_start, end: perfEntry.connect_end, - color: colorForSection('tls time'), - reducedHeight: true, + color: colorForSection('connection time'), + } + + if (isPresent(perfEntry.secure_connection_start)) { + performanceParts['tls time'] = { + start: perfEntry.secure_connection_start, + end: perfEntry.connect_end, + color: colorForSection('tls time'), + reducedHeight: true, + } } } } - if (perfEntry.connect_end && perfEntry.request_start && perfEntry.connect_end !== perfEntry.request_start) { - performanceParts['request queuing time'] = { - start: perfEntry.connect_end, - end: perfEntry.request_start, - color: colorForSection('request queuing time'), + if ( + isPresent(perfEntry.connect_end) && + isPresent(perfEntry.request_start) && + perfEntry.connect_end !== perfEntry.request_start + ) { + if (perfEntry.request_start - perfEntry.connect_end > 0) { + performanceParts['request queuing time'] = { + start: perfEntry.connect_end, + end: perfEntry.request_start, + color: colorForSection('request queuing time'), + } } } - if (perfEntry.response_start && perfEntry.request_start) { - performanceParts['waiting for first byte'] = { - start: perfEntry.request_start, - end: perfEntry.response_start, - color: colorForSection('waiting for first byte'), + if (isPresent(perfEntry.response_start) && isPresent(perfEntry.request_start)) { + if (perfEntry.request_start - perfEntry.response_start > 0) { + performanceParts['waiting for first byte'] = { + start: perfEntry.request_start, + end: perfEntry.response_start, + color: colorForSection('waiting for first byte'), + } } } - if (perfEntry.response_start && perfEntry.response_end) { - performanceParts['receiving response'] = { - start: perfEntry.response_start, - end: perfEntry.response_end, - color: colorForSection('receiving response'), + if (isPresent(perfEntry.response_start) && isPresent(perfEntry.response_end)) { + if (perfEntry.response_end - perfEntry.response_start > 0) { + // if loading from disk cache then response_start is 0 but fetch_start is not + let start = perfEntry.response_start + if (perfEntry.response_start === 0 && isPresent(perfEntry.fetch_start)) { + start = perfEntry.fetch_start + } + performanceParts['receiving response'] = { + start: start, + end: perfEntry.response_end, + color: colorForSection('receiving response'), + } } } - if (perfEntry.response_end && perfEntry.load_event_end) { - performanceParts['document processing'] = { - start: perfEntry.response_end, - end: perfEntry.load_event_end, - color: colorForSection('document processing'), + if (isPresent(perfEntry.response_end) && isPresent(perfEntry.load_event_end)) { + if (perfEntry.load_event_end - perfEntry.response_end > 0) { + performanceParts['document processing'] = { + start: perfEntry.response_end, + end: perfEntry.load_event_end, + color: colorForSection('document processing'), + } } } @@ -208,15 +234,15 @@ function percentagesWithinEventRange({ return { startPercentage: `${partStartPercentage}%`, widthPercentage: `${partPercentage}%` } } -const TimeLineView = ({ performanceEvent }: { performanceEvent: PerformanceEvent }): JSX.Element => { +const TimeLineView = ({ performanceEvent }: { performanceEvent: PerformanceEvent }): JSX.Element | null => { const rangeStart = performanceEvent.start_time const rangeEnd = performanceEvent.response_end if (typeof rangeStart === 'number' && typeof rangeEnd === 'number') { - const performanceParts = calculatePerformanceParts(performanceEvent) + const timings = calculatePerformanceParts(performanceEvent) return (
{perfSections.map((section) => { - const matchedSection = performanceParts[section] + const matchedSection = timings[section] const start = matchedSection?.start const end = matchedSection?.end const partDuration = end - start @@ -263,7 +289,7 @@ const TimeLineView = ({ performanceEvent }: { performanceEvent: PerformanceEvent
) } - return Cannot render performance timeline for this request + return null } const TableView = ({ performanceEvent }: { performanceEvent: PerformanceEvent }): JSX.Element => { @@ -283,6 +309,9 @@ export const NetworkRequestTiming = ({ }): JSX.Element | null => { const [timelineMode, setTimelineMode] = useState(true) + // if timeline view renders null then we fall back to table view + const timelineView = timelineMode ? : null + return (
@@ -297,11 +326,11 @@ export const NetworkRequestTiming = ({
- {timelineMode ? ( - - ) : ( - - )} + {timelineMode && timelineView ? timelineView : }
) } + +function isPresent(x: number | undefined): x is number { + return typeof x === 'number' +} diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts new file mode 100644 index 0000000000000..9232aa858bb0a --- /dev/null +++ b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts @@ -0,0 +1,74 @@ +import { mapRRWebNetworkRequest } from 'scenes/session-recordings/player/inspector/performance-event-utils' +import { InitiatorType } from '../../../../../../../../.yalc/posthog-js' +import { calculatePerformanceParts } from 'scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming' + +jest.mock('lib/colors', () => { + return { + getSeriesColor: jest.fn(() => '#000000'), + } +}) + +describe('calculatePerformanceParts', () => { + it('can handle gravatar timings', () => { + const gravatarReqRes = { + name: 'https://www.gravatar.com/avatar/2e7d95b60efbe947f71009a1af1ba8d0?s=96&d=404', + entryType: 'resource', + initiatorType: 'fetch' as InitiatorType, + deliveryType: '', + nextHopProtocol: '', + renderBlockingStatus: 'non-blocking', + workerStart: 0, + redirectStart: 0, + redirectEnd: 0, + domainLookupStart: 0, + domainLookupEnd: 0, + connectStart: 0, + secureConnectionStart: 0, + connectEnd: 0, + requestStart: 0, + responseStart: 0, + firstInterimResponseStart: 0, + // only fetch start and response end + // and transfer size is 0 + // loaded from disk cache + startTime: 18229, + fetchStart: 18228.5, + responseEnd: 18267.5, + endTime: 18268, + duration: 39, + transferSize: 0, + encodedBodySize: 0, + decodedBodySize: 0, + responseStatus: 200, + serverTiming: [], + timeOrigin: 1700296048424, + timestamp: 1700296066652, + method: 'GET', + status: 200, + requestHeaders: {}, + requestBody: null, + responseHeaders: { + 'cache-control': 'max-age=300', + 'content-length': '13127', + 'content-type': 'image/png', + expires: 'Sat, 18 Nov 2023 08:32:46 GMT', + 'last-modified': 'Wed, 02 Feb 2022 09:11:05 GMT', + }, + responseBody: '�PNGblah', + } + const mappedToPerfEvent = mapRRWebNetworkRequest(gravatarReqRes, 'windowId', 1700296066652) + expect(calculatePerformanceParts(mappedToPerfEvent)).toEqual({ + // 'app cache' not included - end would be before beginning + // 'connection time' has 0 length + // 'dns lookup' has 0 length + // 'redirect has 0 length + // 'tls time' has 0 length + // TTFB has 0 length + 'receiving response': { + color: '#000000', + end: 18267.5, + start: 18228.5, + }, + }) + }) +}) diff --git a/frontend/src/scenes/session-recordings/player/inspector/performance-event-utils.ts b/frontend/src/scenes/session-recordings/player/inspector/performance-event-utils.ts index f3732a28bf3e9..564b96fb865db 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/performance-event-utils.ts +++ b/frontend/src/scenes/session-recordings/player/inspector/performance-event-utils.ts @@ -1,4 +1,5 @@ import { eventWithTime } from '@rrweb/types' +import { CapturedNetworkRequest } from 'posthog-js' import { PerformanceEvent } from '~/types' const NETWORK_PLUGIN_NAME = 'posthog/network@1' @@ -116,6 +117,26 @@ export const RRWebPerformanceEventReverseMapping: Record = { + timestamp: timestamp, + window_id: windowId, + raw: capturedRequest, + } + + Object.entries(RRWebPerformanceEventReverseMapping).forEach(([key, value]) => { + if (key in capturedRequest) { + data[value] = capturedRequest[key] + } + }) + + return data as PerformanceEvent +} + export function matchNetworkEvents(snapshotsByWindowId: Record): PerformanceEvent[] { // we only support rrweb/network@1 events or posthog/network@1 events in any one recording // apart from during testing, where we might have both @@ -159,19 +180,9 @@ export function matchNetworkEvents(snapshotsByWindowId: Record { - const data: Partial = { - timestamp: snapshot.timestamp, - window_id: windowId, - raw: capturedRequest, - } - - Object.entries(RRWebPerformanceEventReverseMapping).forEach(([key, value]) => { - if (key in capturedRequest) { - data[value] = capturedRequest[key] - } - }) + const data: PerformanceEvent = mapRRWebNetworkRequest(capturedRequest, windowId, snapshot.timestamp) - rrwebEvents.push(data as PerformanceEvent) + rrwebEvents.push(data) }) } }) From ba7f8df86fe4e6dfbbed4af6c9524332aea8dfd5 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Sat, 18 Nov 2023 15:16:11 +0000 Subject: [PATCH 05/18] better tls connection time handling --- .../Timing/NetworkRequestTiming.tsx | 2 +- .../Timing/calculatePerformanceParts.test.ts | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx index 72c5a5ee6c49b..354391ea8c14a 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx +++ b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx @@ -151,7 +151,7 @@ export function calculatePerformanceParts(perfEntry: PerformanceEvent): Performa color: colorForSection('connection time'), } - if (isPresent(perfEntry.secure_connection_start)) { + if (isPresent(perfEntry.secure_connection_start) && perfEntry.secure_connection_start > 0) { performanceParts['tls time'] = { start: perfEntry.secure_connection_start, end: perfEntry.connect_end, diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts index 9232aa858bb0a..d2c72e03a1237 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts +++ b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts @@ -71,4 +71,62 @@ describe('calculatePerformanceParts', () => { }, }) }) + + it('can handle no TLS connection timing', () => { + const tlsFreeReqRes = { + name: 'http://localhost:8000/decide/?v=3&ip=1&_=1700319068450&ver=1.91.1', + entryType: 'resource', + startTime: 6648, + duration: 93.40000003576279, + initiatorType: 'xmlhttprequest' as InitiatorType, + deliveryType: '', + nextHopProtocol: 'http/1.1', + renderBlockingStatus: 'non-blocking', + workerStart: 0, + redirectStart: 0, + redirectEnd: 0, + fetchStart: 6647.699999988079, + domainLookupStart: 6648.800000011921, + domainLookupEnd: 6648.800000011921, + connectStart: 6648.800000011921, + secureConnectionStart: 0, + connectEnd: 6649.300000011921, + requestStart: 6649.5, + responseStart: 6740.800000011921, + firstInterimResponseStart: 0, + responseEnd: 6741.100000023842, + transferSize: 2383, + encodedBodySize: 2083, + decodedBodySize: 2083, + responseStatus: 200, + serverTiming: [], + endTime: 6741, + timeOrigin: 1700319061802, + timestamp: 1700319068449, + isInitial: true, + } + const mappedToPerfEvent = mapRRWebNetworkRequest(tlsFreeReqRes, 'windowId', 1700319068449) + expect(calculatePerformanceParts(mappedToPerfEvent)).toEqual({ + 'app cache': { + color: '#000000', + end: 6648.800000011921, + start: 6647.699999988079, + }, + 'connection time': { + color: '#000000', + end: 6649.300000011921, + start: 6648.800000011921, + }, + 'receiving response': { + color: '#000000', + end: 6741.100000023842, + start: 6740.800000011921, + }, + 'request queuing time': { + color: '#000000', + end: 6649.5, + start: 6649.300000011921, + }, + }) + }) }) From 695a20c4a8da8f39c2e959d33b19dd29830fa863 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Sat, 18 Nov 2023 15:22:03 +0000 Subject: [PATCH 06/18] better timeline --- .../player/inspector/components/Timing/NetworkRequestTiming.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx index 354391ea8c14a..c251d309be654 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx +++ b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx @@ -236,7 +236,7 @@ function percentagesWithinEventRange({ const TimeLineView = ({ performanceEvent }: { performanceEvent: PerformanceEvent }): JSX.Element | null => { const rangeStart = performanceEvent.start_time - const rangeEnd = performanceEvent.response_end + const rangeEnd = performanceEvent.load_event_end ? performanceEvent.load_event_end : performanceEvent.response_end if (typeof rangeStart === 'number' && typeof rangeEnd === 'number') { const timings = calculatePerformanceParts(performanceEvent) return ( From 370c975c2b543cc15fd895c733d4c51bebe598e9 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 18 Nov 2023 15:24:38 +0000 Subject: [PATCH 07/18] Update UI snapshots for `chromium` (2) --- ...components-networkrequesttiming--basic.png | Bin 10527 -> 9837 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/frontend/__snapshots__/components-networkrequesttiming--basic.png b/frontend/__snapshots__/components-networkrequesttiming--basic.png index 8247b433f71c8f2b4e1682d1e2f887655045bc2b..ecf55d302c5c9c44c5affcdbb8f0f299258d8119 100644 GIT binary patch literal 9837 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 literal 10527 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 Date: Sat, 18 Nov 2023 15:44:52 +0000 Subject: [PATCH 08/18] fix --- .../player/inspector/components/ItemPerformanceEvent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx b/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx index 7b3f78a3daa9c..ed2046208bfd1 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx +++ b/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx @@ -484,7 +484,7 @@ function StatusRow({ item }: { item: PerformanceEvent }): JSX.Element | null { let methodRow = null let fromDiskCache = false - if (item.transfer_size === 0 && item.response_body) { + if (item.transfer_size === 0 && item.response_body && item.response_status && item.response_status < 400) { fromDiskCache = true } From d86f597f4f49c03e311c969adbe6aa782ac2fd65 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Sat, 18 Nov 2023 19:29:10 +0000 Subject: [PATCH 09/18] fix --- .../Timing/NetworkRequestTiming.tsx | 2 +- .../Timing/calculatePerformanceParts.test.ts | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx index c251d309be654..ff01b5195db6d 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx +++ b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx @@ -177,7 +177,7 @@ export function calculatePerformanceParts(perfEntry: PerformanceEvent): Performa } if (isPresent(perfEntry.response_start) && isPresent(perfEntry.request_start)) { - if (perfEntry.request_start - perfEntry.response_start > 0) { + if (perfEntry.response_start - perfEntry.request_start > 0) { performanceParts['waiting for first byte'] = { start: perfEntry.request_start, end: perfEntry.response_start, diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts index d2c72e03a1237..7535e66d721be 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts +++ b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts @@ -9,6 +9,61 @@ jest.mock('lib/colors', () => { }) describe('calculatePerformanceParts', () => { + it('can calculte TTFB', () => { + const perfEvent = { + connect_end: 9525.599999964237, + connect_start: 9525.599999964237, + decoded_body_size: 18260, + domain_lookup_end: 9525.599999964237, + domain_lookup_start: 9525.599999964237, + duration: 935.5, + encoded_body_size: 18260, + entry_type: 'resource', + fetch_start: 9525.599999964237, + initiator_type: 'fetch', + name: 'http://localhost:8000/api/organizations/@current/plugins/repository/', + next_hop_protocol: 'http/1.1', + redirect_end: 0, + redirect_start: 0, + render_blocking_status: 'non-blocking', + request_start: 9803.099999964237, + response_end: 10461.099999964237, + response_start: 10428.399999976158, + response_status: 200, + secure_connection_start: 0, + start_time: 9525.599999964237, + time_origin: '1699990397357', + timestamp: 1699990406882, + transfer_size: 18560, + window_id: '018bcf51-b1f0-7fe0-ac05-10543621f4f2', + worker_start: 0, + uuid: '12345', + distinct_id: '23456', + session_id: 'abcde', + pageview_id: 'fghij', + current_url: 'http://localhost:8000/insights', + } + + expect(calculatePerformanceParts(perfEvent)).toEqual({ + 'request queuing time': { + color: '#000000', + end: 9803.099999964237, + start: 9525.599999964237, + }, + + 'waiting for first byte': { + color: '#000000', + end: 10428.399999976158, + start: 9803.099999964237, + }, + 'receiving response': { + color: '#000000', + end: 10461.099999964237, + start: 10428.399999976158, + }, + }) + }) + it('can handle gravatar timings', () => { const gravatarReqRes = { name: 'https://www.gravatar.com/avatar/2e7d95b60efbe947f71009a1af1ba8d0?s=96&d=404', @@ -117,6 +172,11 @@ describe('calculatePerformanceParts', () => { end: 6649.300000011921, start: 6648.800000011921, }, + 'waiting for first byte': { + color: '#000000', + end: 6740.800000011921, + start: 6649.5, + }, 'receiving response': { color: '#000000', end: 6741.100000023842, From 41b6b1665dcc748e0b6235d86079b9f3941e94fe Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Sat, 18 Nov 2023 19:31:08 +0000 Subject: [PATCH 10/18] fix --- .../components/Timing/calculatePerformanceParts.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts index 7535e66d721be..38356ef807f53 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts +++ b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts @@ -1,5 +1,5 @@ import { mapRRWebNetworkRequest } from 'scenes/session-recordings/player/inspector/performance-event-utils' -import { InitiatorType } from '../../../../../../../../.yalc/posthog-js' +import { InitiatorType } from 'posthog-js' import { calculatePerformanceParts } from 'scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming' jest.mock('lib/colors', () => { From 60c8352e13deee7a418cb503ef8e17dd95b34131 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Sat, 18 Nov 2023 19:31:22 +0000 Subject: [PATCH 11/18] fix --- .../components/Timing/calculatePerformanceParts.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts index 38356ef807f53..24f59d7f4af3d 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts +++ b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/calculatePerformanceParts.test.ts @@ -9,7 +9,7 @@ jest.mock('lib/colors', () => { }) describe('calculatePerformanceParts', () => { - it('can calculte TTFB', () => { + it('can calculate TTFB', () => { const perfEvent = { connect_end: 9525.599999964237, connect_start: 9525.599999964237, From 98397ea34f754e0882cf47bcbb5f5ab83c3a6421 Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Sat, 18 Nov 2023 19:37:55 +0000 Subject: [PATCH 12/18] fix --- .../Timing/NetworkRequestTiming.stories.tsx | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.stories.tsx b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.stories.tsx index a02e9bf3dce03..815eefed8bdfb 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.stories.tsx +++ b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.stories.tsx @@ -19,27 +19,30 @@ export function Basic(): JSX.Element { Date: Sat, 18 Nov 2023 19:38:16 +0000 Subject: [PATCH 13/18] Update UI snapshots for `chromium` (2) --- ...components-networkrequesttiming--basic.png | Bin 9837 -> 10139 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/frontend/__snapshots__/components-networkrequesttiming--basic.png b/frontend/__snapshots__/components-networkrequesttiming--basic.png index ecf55d302c5c9c44c5affcdbb8f0f299258d8119..bb55a3d9d5018d443814a53eb42995e7dbf767fc 100644 GIT binary patch literal 10139 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 a;QF*5%s1w$3i!4ia8>s@qDI^P;eP=k4^VXg literal 9837 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 From 467b16bd0f0239768504b0838fdcb95243a69bbc Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 18 Nov 2023 19:46:44 +0000 Subject: [PATCH 14/18] Update UI snapshots for `chromium` (2) --- ...components-networkrequesttiming--basic.png | Bin 10139 -> 10613 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/frontend/__snapshots__/components-networkrequesttiming--basic.png b/frontend/__snapshots__/components-networkrequesttiming--basic.png index bb55a3d9d5018d443814a53eb42995e7dbf767fc..effc91c21a0a6da960f47b9bba209a4214394205 100644 GIT binary patch literal 10613 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 literal 10139 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 a;QF*5%s1w$3i!4ia8>s@qDI^P;eP=k4^VXg From 33fd146e588241a6c81c9523c244d0ece379189d Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Sat, 18 Nov 2023 20:14:05 +0000 Subject: [PATCH 15/18] fix --- .../inspector/components/Timing/NetworkRequestTiming.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx index ff01b5195db6d..af8bd9d22680a 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx +++ b/frontend/src/scenes/session-recordings/player/inspector/components/Timing/NetworkRequestTiming.tsx @@ -214,6 +214,10 @@ export function calculatePerformanceParts(perfEntry: PerformanceEvent): Performa return performanceParts } +function percentage(partDuration: number, totalDuration: number, min: number): number { + return Math.min(Math.max(min, (partDuration / totalDuration) * 100), 100) +} + function percentagesWithinEventRange({ partStart, partEnd, @@ -229,8 +233,8 @@ function percentagesWithinEventRange({ const partStartRelativeToTimeline = partStart - rangeStart const partDuration = partEnd - partStart - const partPercentage = Math.max(0.1, (partDuration / totalDuration) * 100) //less than 0.1% is not visible - const partStartPercentage = (partStartRelativeToTimeline / totalDuration) * 100 + const partPercentage = percentage(partDuration, totalDuration, 0.1) + const partStartPercentage = percentage(partStartRelativeToTimeline, totalDuration, 0) return { startPercentage: `${partStartPercentage}%`, widthPercentage: `${partPercentage}%` } } From 143e77f9c68597af7113bf04cc041a2b44b3917c Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Tue, 21 Nov 2023 17:50:08 +0000 Subject: [PATCH 16/18] update posthog-js --- pnpm-lock.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 730433090dd94..29c30c7e95f81 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -216,8 +216,8 @@ dependencies: specifier: ^2.11.0 version: 2.11.0 posthog-js: - specifier: 1.92.0 - version: 1.92.0 + specifier: 1.92.1 + version: 1.92.1 posthog-js-lite: specifier: 2.0.0-alpha5 version: 2.0.0-alpha5 @@ -15793,8 +15793,8 @@ packages: resolution: {integrity: sha512-tlkBdypJuvK/s00n4EiQjwYVfuuZv6vt8BF3g1ooIQa2Gz9Vz80p8q3qsPLZ0V5ErGRy6i3Q4fWC9TDzR7GNRQ==} dev: false - /posthog-js@1.92.0: - resolution: {integrity: sha512-87bZ/qwBbIqvkIV4YYn65oIPEsRcWihA3jX7WV33LvZWaU1InlE6cwj95SleIVLiND4Ofm+cKXZeWwcRnrXkKA==} + /posthog-js@1.92.1: + resolution: {integrity: sha512-xtuTfM/acfDauiEfIdKF6d911KUZQ7RLii2COAYEoPWr3cVUFoNUoRQz9QJvgDlV2j22Zwl+mnXacUeua+Yi1A==} dependencies: fflate: 0.4.8 dev: false From cecd83f66821516f327d524afdb683fd016f42ed Mon Sep 17 00:00:00 2001 From: Paul D'Ambra Date: Tue, 21 Nov 2023 17:52:01 +0000 Subject: [PATCH 17/18] comment --- .../player/inspector/components/ItemPerformanceEvent.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx b/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx index ed2046208bfd1..592d926958224 100644 --- a/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx +++ b/frontend/src/scenes/session-recordings/player/inspector/components/ItemPerformanceEvent.tsx @@ -396,6 +396,8 @@ export function ItemPerformanceEvent({ ), } : false, + // raw is only available if the feature flag is enabled + // TODO before proper release we should put raw behind its own flag { key: 'raw', label: 'Json', From 791493c00634d10ed974f0fb187b275baedbaa0b Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 21 Nov 2023 18:00:48 +0000 Subject: [PATCH 18/18] Update UI snapshots for `chromium` (1) --- .../components-command-bar--actions.png | Bin 20858 -> 23855 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/frontend/__snapshots__/components-command-bar--actions.png b/frontend/__snapshots__/components-command-bar--actions.png index 585c01020c1c50135cf4f487a4a95bcf2a512b9b..302fb86f50402851bb81674e2bfa84b91c2df54c 100644 GIT binary patch literal 23855 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