Browse Source

feat(browser-starfish): add bundle size overtime graph (#65996)

More work towards #64090 
Adds a bundle size overtime chart
<img width="1262" alt="image"
src="https://github.com/getsentry/sentry/assets/44422760/53633241-0517-493c-aabd-450589587df1">

This is all with fake data and all behind a feature flag, but it puts
the pieces in place necessary to feed the real data into.
Dominik Buszowiecki 1 year ago
parent
commit
73166096ca

+ 1 - 1
static/app/views/performance/browser/resources/resourceView/index.tsx

@@ -62,7 +62,7 @@ function ResourceView() {
   return (
     <Fragment>
       <SpanTimeCharts
-        moduleName={ModuleName.OTHER}
+        moduleName={ModuleName.RESOURCE}
         appliedFilters={spanTimeChartsFilters}
         throughputUnit={RESOURCE_THROUGHPUT_UNIT}
         extraQuery={extraQuery}

+ 72 - 2
static/app/views/starfish/views/spans/spanTimeCharts.tsx

@@ -9,6 +9,7 @@ import {RateUnit} from 'sentry/utils/discover/fields';
 import {DiscoverDatasets} from 'sentry/utils/discover/types';
 import {formatRate} from 'sentry/utils/formatters';
 import {EMPTY_OPTION_VALUE} from 'sentry/utils/tokenizeSearch';
+import useOrganization from 'sentry/utils/useOrganization';
 import usePageFilters from 'sentry/utils/usePageFilters';
 import {AVG_COLOR, ERRORS_COLOR, THROUGHPUT_COLOR} from 'sentry/views/starfish/colours';
 import Chart, {useSynchronizeCharts} from 'sentry/views/starfish/components/chart';
@@ -57,6 +58,7 @@ export function SpanTimeCharts({
   extraQuery,
 }: Props) {
   const {selection} = usePageFilters();
+  const {features} = useOrganization();
 
   const eventView = getEventView(moduleName, selection, appliedFilters, spanCategory);
   if (extraQuery) {
@@ -80,7 +82,11 @@ export function SpanTimeCharts({
       {title: getDurationChartTitle(moduleName), Comp: DurationChart},
     ],
     [ModuleName.DB]: [],
-    [ModuleName.RESOURCE]: [],
+    [ModuleName.RESOURCE]: features.includes(
+      'starfish-browser-resource-module-bundle-analysis'
+    )
+      ? [{title: DataTitles.bundleSize, Comp: BundleSizeChart}]
+      : [],
     [ModuleName.HTTP]: [{title: DataTitles.errorCount, Comp: ErrorChart}],
     [ModuleName.OTHER]: [],
   };
@@ -263,6 +269,70 @@ function ErrorChart({moduleName, filters}: ChartProps): JSX.Element {
   );
 }
 
+/** This fucntion is just to generate mock data based on other time stamps we have found */
+const mockSeries = ({moduleName, filters, extraQuery}: ChartProps) => {
+  const pageFilters = usePageFilters();
+  const eventView = getEventView(moduleName, pageFilters.selection, filters);
+  if (extraQuery) {
+    eventView.query += ` ${extraQuery.join(' ')}`;
+  }
+
+  const label = `avg(${SPAN_SELF_TIME})`;
+
+  const {isLoading, data} = useSpansQuery<
+    {
+      'avg(span.self_time)': number;
+      interval: number;
+      'spm()': number;
+    }[]
+  >({
+    eventView,
+    initialData: [],
+    referrer: 'api.starfish.span-time-charts',
+  });
+  const dataByGroup = {[label]: data};
+
+  const avgSeries = Object.keys(dataByGroup).map(groupName => {
+    const groupData = dataByGroup[groupName];
+
+    return {
+      seriesName: label,
+      data: (groupData ?? []).map(datum => ({
+        value: datum[`avg(${SPAN_SELF_TIME})`],
+        name: datum.interval,
+      })),
+    };
+  });
+  const seriesTimes = avgSeries[0].data.map(({name}) => name);
+  const assetTypes = ['javascript', 'css', 'fonts', 'images'];
+
+  const mockData: Series[] = assetTypes.map(
+    type =>
+      ({
+        seriesName: type,
+        data: seriesTimes.map((time, i) => ({
+          name: time,
+          value: 1000 + Math.ceil(i / 100) * 100,
+        })),
+      }) satisfies Series
+  );
+
+  return {isLoading, data: mockData};
+};
+
+function BundleSizeChart(props: ChartProps) {
+  const {isLoading, data} = mockSeries(props);
+  return (
+    <Chart
+      stacked
+      loading={isLoading}
+      data={data}
+      aggregateOutputFormat="size"
+      height={CHART_HEIGHT}
+    />
+  );
+}
+
 const SPAN_FILTER_KEYS = ['span_operation', SPAN_DOMAIN, 'action'];
 
 const getEventView = (
@@ -305,7 +375,7 @@ const buildDiscoverQueryConditions = (
 
   result.push(`has:${SPAN_DESCRIPTION}`);
 
-  if (moduleName !== ModuleName.ALL) {
+  if (moduleName !== ModuleName.ALL && moduleName !== ModuleName.RESOURCE) {
     result.push(`${SPAN_MODULE}:${moduleName}`);
   }
 

+ 3 - 1
static/app/views/starfish/views/spans/types.tsx

@@ -18,7 +18,8 @@ export type DataKey =
   | 'count'
   | 'avg(http.response_content_length)'
   | 'avg(http.decoded_response_content_length)'
-  | 'avg(http.response_transfer_size)';
+  | 'avg(http.response_transfer_size)'
+  | 'bundleSize';
 
 export const DataTitles: Record<DataKey, string> = {
   change: t('Change'),
@@ -34,6 +35,7 @@ export const DataTitles: Record<DataKey, string> = {
   slowFrames: t('Slow Frames %'),
   ttid: t('Time To Initial Display'),
   ttfd: t('Time To Full Display'),
+  bundleSize: t('Bundle size'),
   'avg(http.response_content_length)': t('Avg Encoded Size'),
   'avg(http.decoded_response_content_length)': t('Avg Decoded Size'),
   'avg(http.response_transfer_size)': t('Avg Transfer Size'),