Skip to content

Commit 031b0ee

Browse files
authored
ref(perf): Add perf asset collection (#36012)
This adds some new measurements to collect assets for a page, only if one of the components is wrapped with the provided component from performanceForSentry. This is an experiment to check the usefulness of asset measurement in code, we can extend this into the sdk once we work out any issues with this approach.
1 parent 26380a4 commit 031b0ee

File tree

2 files changed

+100
-18
lines changed

2 files changed

+100
-18
lines changed

static/app/utils/performanceForSentry.tsx

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,3 +309,82 @@ export const VisuallyCompleteWithData = ({
309309
</Profiler>
310310
);
311311
};
312+
313+
interface OpAssetMeasurementDefinition {
314+
key: string;
315+
}
316+
317+
const OP_ASSET_MEASUREMENT_MAP: Record<string, OpAssetMeasurementDefinition> = {
318+
'resource.script': {
319+
key: 'script',
320+
},
321+
'resource.css': {
322+
key: 'css',
323+
},
324+
'resource.link': {
325+
key: 'link',
326+
},
327+
'resource.img': {
328+
key: 'img',
329+
},
330+
};
331+
const ASSET_MEASUREMENT_ALL = 'allResources';
332+
333+
export const MeasureAssetsOnTransaction = ({children}: {children: ReactNode}) => {
334+
useEffect(() => {
335+
try {
336+
const transaction: any = getCurrentSentryReactTransaction(); // Using any to override types for private api.
337+
if (!transaction) {
338+
return;
339+
}
340+
341+
transaction.registerBeforeFinishCallback((t: Transaction) => {
342+
const spans: any[] = (t as any).spanRecorder?.spans;
343+
const measurements = (t as any)._measurements;
344+
345+
if (!spans) {
346+
return;
347+
}
348+
349+
if (measurements[ASSET_MEASUREMENT_ALL]) {
350+
return;
351+
}
352+
353+
let allTransfered = 0;
354+
let allEncoded = 0;
355+
let allCount = 0;
356+
357+
for (const [op, definition] of Object.entries(OP_ASSET_MEASUREMENT_MAP)) {
358+
const filtered = spans.filter(s => s.op === op);
359+
const count = filtered.length;
360+
const transfered = filtered.reduce(
361+
(acc, curr) => acc + curr.data['Transfer Size'] ?? 0,
362+
0
363+
);
364+
const encoded = filtered.reduce(
365+
(acc, curr) => acc + curr.data['Encoded Body Size'] ?? 0,
366+
0
367+
);
368+
369+
if (op === 'resource.script') {
370+
t.setMeasurement(`assets.${definition.key}.encoded`, encoded, '');
371+
t.setMeasurement(`assets.${definition.key}.transfer`, transfered, '');
372+
t.setMeasurement(`assets.${definition.key}.count`, count, '');
373+
}
374+
375+
allCount += count;
376+
allTransfered += transfered;
377+
allEncoded += encoded;
378+
}
379+
380+
t.setMeasurement(`${ASSET_MEASUREMENT_ALL}.encoded`, allEncoded, '');
381+
t.setMeasurement(`${ASSET_MEASUREMENT_ALL}.transfer`, allTransfered, '');
382+
t.setMeasurement(`${ASSET_MEASUREMENT_ALL}.count`, allCount, '');
383+
});
384+
} catch (_) {
385+
// Defensive catch since this code is auxiliary.
386+
}
387+
}, []);
388+
389+
return <Fragment>{children}</Fragment>;
390+
};

static/app/views/performance/content.tsx

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {PageFilters, Project} from 'sentry/types';
1313
import trackAdvancedAnalyticsEvent from 'sentry/utils/analytics/trackAdvancedAnalyticsEvent';
1414
import {MEPSettingProvider} from 'sentry/utils/performance/contexts/metricsEnhancedSetting';
1515
import {PerformanceEventViewProvider} from 'sentry/utils/performance/contexts/performanceEventViewContext';
16+
import {MeasureAssetsOnTransaction} from 'sentry/utils/performanceForSentry';
1617
import useApi from 'sentry/utils/useApi';
1718
import useOrganization from 'sentry/utils/useOrganization';
1819
import usePrevious from 'sentry/utils/usePrevious';
@@ -159,24 +160,26 @@ function PerformanceContent({selection, location, demoMode}: Props) {
159160
},
160161
}}
161162
>
162-
<PerformanceLanding
163-
eventView={eventView}
164-
setError={setError}
165-
handleSearch={handleSearch}
166-
handleTrendsClick={() =>
167-
handleTrendsClick({
168-
location,
169-
organization,
170-
projectPlatforms: getSelectedProjectPlatforms(location, projects),
171-
})
172-
}
173-
onboardingProject={onboardingProject}
174-
organization={organization}
175-
location={location}
176-
projects={projects}
177-
selection={selection}
178-
withStaticFilters={withStaticFilters}
179-
/>
163+
<MeasureAssetsOnTransaction>
164+
<PerformanceLanding
165+
eventView={eventView}
166+
setError={setError}
167+
handleSearch={handleSearch}
168+
handleTrendsClick={() =>
169+
handleTrendsClick({
170+
location,
171+
organization,
172+
projectPlatforms: getSelectedProjectPlatforms(location, projects),
173+
})
174+
}
175+
onboardingProject={onboardingProject}
176+
organization={organization}
177+
location={location}
178+
projects={projects}
179+
selection={selection}
180+
withStaticFilters={withStaticFilters}
181+
/>
182+
</MeasureAssetsOnTransaction>
180183
</PageFiltersContainer>
181184
</MEPSettingProvider>
182185
</PerformanceEventViewProvider>

0 commit comments

Comments
 (0)