Browse Source

feat(trace-timing): Add ttid and ttfd to the UI (#45951)

- This updates a bunch of the constant lists on the frontend to include
time to initial & full display so they show up in the UI as expected
  - This includes:
   - Event Details span waterfall having the measurement lines

![image](https://user-images.githubusercontent.com/4205004/225738927-1a6c36cf-e486-4db1-95d9-2b09e646988a.png)
   - The sidebar of event details with the measurement values

![image](https://user-images.githubusercontent.com/4205004/225739087-2422273f-722f-43ec-be4c-b1ab208f7925.png)
   - The Trace View having the measurement lines

![image](https://user-images.githubusercontent.com/4205004/225739125-90d40e67-6499-42cb-b842-95b2c0d2fd66.png)
   - Discover parameter dropdown

![image](https://user-images.githubusercontent.com/4205004/225739206-261d3a34-06b7-4fc0-8802-8144b7a065a9.png)
   - Smart Search & definitions

![image](https://user-images.githubusercontent.com/4205004/225739235-59e72025-a3eb-444a-9130-eb3076374763.png)
- Closes #45880
William Mak 2 years ago
parent
commit
52e61078e5

+ 2 - 2
static/app/components/events/interfaces/spans/measurementsPanel.tsx

@@ -5,7 +5,7 @@ import {toPercent} from 'sentry/components/performance/waterfall/utils';
 import {Tooltip} from 'sentry/components/tooltip';
 import {space} from 'sentry/styles/space';
 import {defined} from 'sentry/utils';
-import {WEB_VITAL_DETAILS} from 'sentry/utils/performance/vitals/constants';
+import {VITAL_DETAILS} from 'sentry/utils/performance/vitals/constants';
 import {Vital} from 'sentry/utils/performance/vitals/types';
 
 import {
@@ -48,7 +48,7 @@ function MeasurementsPanel(props: Props) {
         }
 
         const vitalLabels: VitalLabel[] = Object.keys(verticalMark.marks).map(name => ({
-          vital: WEB_VITAL_DETAILS[`measurements.${name}`],
+          vital: VITAL_DETAILS[`measurements.${name}`],
           isPoorValue: verticalMark.marks[name].failedThreshold,
         }));
 

+ 7 - 5
static/app/components/events/interfaces/spans/utils.tsx

@@ -11,9 +11,9 @@ import {Organization} from 'sentry/types';
 import {EntrySpans, EntryType, EventTransaction} from 'sentry/types/event';
 import {assert} from 'sentry/types/utils';
 import trackAdvancedAnalyticsEvent from 'sentry/utils/analytics/trackAdvancedAnalyticsEvent';
-import {WebVital} from 'sentry/utils/fields';
+import {MobileVital, WebVital} from 'sentry/utils/fields';
 import {TraceError, TraceFullDetailed} from 'sentry/utils/performance/quickTrace/types';
-import {WEB_VITAL_DETAILS} from 'sentry/utils/performance/vitals/constants';
+import {VITAL_DETAILS} from 'sentry/utils/performance/vitals/constants';
 
 import {MERGE_LABELS_THRESHOLD_PERCENT} from './constants';
 import SpanTreeModel from './spanTreeModel';
@@ -526,7 +526,7 @@ export type VerticalMark = {
 
 function hasFailedThreshold(marks: Measurements): boolean {
   const names = Object.keys(marks);
-  const records = Object.values(WEB_VITAL_DETAILS).filter(vital =>
+  const records = Object.values(VITAL_DETAILS).filter(vital =>
     names.includes(vital.slug)
   );
 
@@ -557,6 +557,8 @@ export function getMeasurements(
     WebVital.FID,
     WebVital.LCP,
     WebVital.TTFB,
+    MobileVital.TimeToFullDisplay,
+    MobileVital.TimeToInitialDisplay,
   ]);
 
   const measurements = Object.keys(event.measurements)
@@ -598,7 +600,7 @@ export function getMeasurements(
       if (positionDelta <= MERGE_LABELS_THRESHOLD_PERCENT) {
         const verticalMark = mergedMeasurements.get(otherPos)!;
 
-        const {poorThreshold} = WEB_VITAL_DETAILS[`measurements.${name}`];
+        const {poorThreshold} = VITAL_DETAILS[`measurements.${name}`];
 
         verticalMark.marks = {
           ...verticalMark.marks,
@@ -618,7 +620,7 @@ export function getMeasurements(
       }
     }
 
-    const {poorThreshold} = WEB_VITAL_DETAILS[`measurements.${name}`];
+    const {poorThreshold} = VITAL_DETAILS[`measurements.${name}`];
 
     const marks = {
       [name]: {

+ 14 - 0
static/app/utils/fields/index.ts

@@ -148,6 +148,8 @@ export enum MobileVital {
   StallTotalTime = 'measurements.stall_total_time',
   StallLongestTime = 'measurements.stall_longest_time',
   StallPercentage = 'measurements.stall_percentage',
+  TimeToFullDisplay = 'measurements.time_to_full_display',
+  TimeToInitialDisplay = 'measurements.time_to_initial_display',
 }
 
 export enum SpanOpBreakdown {
@@ -416,6 +418,18 @@ export const MEASUREMENT_FIELDS: Record<WebVital | MobileVital, FieldDefinition>
     kind: FieldKind.METRICS,
     valueType: FieldValueType.PERCENTAGE,
   },
+  [MobileVital.TimeToFullDisplay]: {
+    desc: t(
+      'The time between application launch and complete display of all resources and views'
+    ),
+    kind: FieldKind.METRICS,
+    valueType: FieldValueType.DURATION,
+  },
+  [MobileVital.TimeToInitialDisplay]: {
+    desc: t('The time it takes for an application to produce its first frame'),
+    kind: FieldKind.METRICS,
+    valueType: FieldValueType.DURATION,
+  },
 };
 
 export const SPAN_OP_FIELDS: Record<SpanOpBreakdown, FieldDefinition> = {

+ 19 - 0
static/app/utils/performance/vitals/constants.tsx

@@ -165,8 +165,27 @@ export const MOBILE_VITAL_DETAILS: Record<MobileVital, Vital> = {
     ),
     type: measurementType(MobileVital.StallPercentage),
   },
+  [MobileVital.TimeToFullDisplay]: {
+    slug: 'time_to_full_display',
+    name: t('Time To Full Display'),
+    acronym: 'TTFD',
+    description: t(
+      'The time between application launch and complete display of all resources and views.'
+    ),
+    type: measurementType(MobileVital.TimeToFullDisplay),
+  },
+  [MobileVital.TimeToInitialDisplay]: {
+    slug: 'time_to_initial_display',
+    name: t('Time To Initial Display'),
+    acronym: 'TTID',
+    description: t('The time it takes for an application to produce its first frame.'),
+    poorThreshold: 2000,
+    type: measurementType(MobileVital.TimeToInitialDisplay),
+  },
 };
 
+export const VITAL_DETAILS = Object.assign({}, WEB_VITAL_DETAILS, MOBILE_VITAL_DETAILS);
+
 export enum Browser {
   CHROME = 'Chrome',
   EDGE = 'Edge',