Skip to content

Commit

Permalink
[RUM Dashboard] Replace FID with INP (#172467)
Browse files Browse the repository at this point in the history
  • Loading branch information
shahzad31 authored Dec 5, 2023
1 parent dc88dee commit 9695939
Showing 38 changed files with 560 additions and 140 deletions.
Original file line number Diff line number Diff line change
@@ -63,6 +63,10 @@ export async function getServiceTransactionTypes({
params
);
const transactionTypes =
aggregations?.types.buckets.map((bucket) => bucket.key as string) || [];
aggregations?.types.buckets
.map((bucket) => bucket.key as string)
// we exclude page-exit transactions because they are not relevant for the apm app
// and are only used for the INP values
.filter((value) => value !== 'page-exit') || [];
return { transactionTypes };
}
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ import { ReportViewType } from '../../types';
import {
CLS_FIELD,
FCP_FIELD,
FID_FIELD,
INP_FIELD,
LCP_FIELD,
TBT_FIELD,
TRANSACTION_DURATION,
@@ -31,7 +31,7 @@ import {
ENVIRONMENT_LABEL,
EVENT_DATASET_LABEL,
FCP_LABEL,
FID_LABEL,
INP_LABEL,
HEATMAP_LABEL,
HOST_NAME_LABEL,
KPI_LABEL,
@@ -102,7 +102,7 @@ export const FieldLabels: Record<string, string> = {
[LCP_FIELD]: LCP_LABEL,
[FCP_FIELD]: FCP_LABEL,
[TBT_FIELD]: TBT_LABEL,
[FID_FIELD]: FID_LABEL,
[INP_FIELD]: INP_LABEL,
[CLS_FIELD]: CLS_LABEL,

[SYNTHETICS_CLS]: CLS_LABEL,
Original file line number Diff line number Diff line change
@@ -129,6 +129,7 @@ export const FCP_FIELD = 'transaction.marks.agent.firstContentfulPaint';
export const LCP_FIELD = 'transaction.marks.agent.largestContentfulPaint';
export const TBT_FIELD = 'transaction.experience.tbt';
export const FID_FIELD = 'transaction.experience.fid';
export const INP_FIELD = 'numeric_labels.inp_value';
export const CLS_FIELD = 'transaction.experience.cls';

export const PROFILE_ID = 'profile.id';
Original file line number Diff line number Diff line change
@@ -82,6 +82,10 @@ export const FID_LABEL = i18n.translate('xpack.exploratoryView.expView.fieldLabe
defaultMessage: 'First input delay',
});

export const INP_LABEL = i18n.translate('xpack.exploratoryView.expView.fieldLabels.inp', {
defaultMessage: 'Interaction to next paint',
});

export const CLS_LABEL = i18n.translate('xpack.exploratoryView.expView.fieldLabels.cls', {
defaultMessage: 'Cumulative layout shift',
});
Original file line number Diff line number Diff line change
@@ -15,11 +15,11 @@ import {
ReportTypes,
USE_BREAK_DOWN_COLUMN,
} from '../constants';
import { buildPhraseFilter } from '../utils';
import { buildPhraseFilter, buildPhrasesFilter } from '../utils';
import {
CLIENT_GEO_COUNTRY_NAME,
CLS_FIELD,
FID_FIELD,
INP_FIELD,
LCP_FIELD,
PROCESSOR_EVENT,
SERVICE_NAME,
@@ -32,8 +32,9 @@ import {
USER_AGENT_OS_VERSION,
URL_FULL,
SERVICE_ENVIRONMENT,
FID_FIELD,
} from '../constants/elasticsearch_fieldnames';
import { CLS_LABEL, FID_LABEL, LCP_LABEL } from '../constants/labels';
import { CLS_LABEL, FID_LABEL, INP_LABEL, LCP_LABEL } from '../constants/labels';

export function getCoreWebVitalsConfig({ dataView }: ConfigProps): SeriesConfig {
const statusPallete = euiPaletteForStatus(3);
@@ -87,7 +88,7 @@ export function getCoreWebVitalsConfig({ dataView }: ConfigProps): SeriesConfig
URL_FULL,
],
baseFilters: [
...buildPhraseFilter(TRANSACTION_TYPE, 'page-load', dataView),
...buildPhrasesFilter(TRANSACTION_TYPE, ['page-load', 'page-exit'], dataView),
...buildPhraseFilter(PROCESSOR_EVENT, 'transaction', dataView),
],
labels: { ...FieldLabels, [SERVICE_NAME]: 'Web Application' },
@@ -113,21 +114,21 @@ export function getCoreWebVitalsConfig({ dataView }: ConfigProps): SeriesConfig
],
},
{
label: FID_LABEL,
id: FID_FIELD,
label: INP_LABEL,
id: INP_FIELD,
columnType: FILTER_RECORDS,
columnFilters: [
{
language: 'kuery',
query: `${FID_FIELD} < 100`,
query: `${INP_FIELD} < 200`,
},
{
language: 'kuery',
query: `${FID_FIELD} > 100 and ${FID_FIELD} < 300`,
query: `${INP_FIELD} > 200 and ${INP_FIELD} < 500`,
},
{
language: 'kuery',
query: `${FID_FIELD} > 300`,
query: `${INP_FIELD} > 500`,
},
],
},
@@ -150,12 +151,31 @@ export function getCoreWebVitalsConfig({ dataView }: ConfigProps): SeriesConfig
},
],
},
{
label: FID_LABEL,
id: FID_FIELD,
columnType: FILTER_RECORDS,
columnFilters: [
{
language: 'kuery',
query: `${FID_FIELD} < 100`,
},
{
language: 'kuery',
query: `${FID_FIELD} > 100 and ${FID_FIELD} < 300`,
},
{
language: 'kuery',
query: `${FID_FIELD} > 300`,
},
],
},
],
yConfig: [
{ color: statusPallete[0], forAccessor: 'y-axis-column' },
{ color: statusPallete[1], forAccessor: 'y-axis-column-1' },
{ color: statusPallete[2], forAccessor: 'y-axis-column-2' },
],
query: { query: 'transaction.type: "page-load"', language: 'kuery' },
query: { query: 'transaction.type: ("page-load" or "page-exit")', language: 'kuery' },
};
}
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ import {
CLIENT_GEO_COUNTRY_NAME,
CLS_FIELD,
FCP_FIELD,
FID_FIELD,
INP_FIELD,
LCP_FIELD,
PROCESSOR_EVENT,
SERVICE_ENVIRONMENT,
@@ -37,7 +37,7 @@ import {
BACKEND_TIME_LABEL,
CLS_LABEL,
FCP_LABEL,
FID_LABEL,
INP_LABEL,
LCP_LABEL,
PAGE_LOAD_TIME_LABEL,
PAGES_LOADED_LABEL,
@@ -97,7 +97,7 @@ export function getRumDistributionConfig({ dataView }: ConfigProps): SeriesConfi
{ label: FCP_LABEL, id: FCP_FIELD, field: FCP_FIELD },
{ label: TBT_LABEL, id: TBT_FIELD, field: TBT_FIELD },
{ label: LCP_LABEL, id: LCP_FIELD, field: LCP_FIELD },
{ label: FID_LABEL, id: FID_FIELD, field: FID_FIELD },
{ label: INP_LABEL, id: INP_FIELD, field: INP_FIELD },
{ label: CLS_LABEL, id: CLS_FIELD, field: CLS_FIELD },
],
baseFilters: [
Original file line number Diff line number Diff line change
@@ -77,6 +77,18 @@ export const rumFieldFormats: FieldFormat[] = [
},
},
},
{
field: FID_FIELD,
format: {
id: 'duration',
params: {
inputFormat: 'milliseconds',
outputFormat: 'humanizePrecise',
showSuffix: true,
useShortSuffix: true,
},
},
},
{
field: TRANSACTION_TIME_TO_FIRST_BYTE,
format: {
Original file line number Diff line number Diff line change
@@ -86,7 +86,7 @@ export const sampleAttributeCoreWebVital = {
filter: {
language: 'kuery',
query:
'transaction.type: page-load and processor.event: transaction and transaction.marks.agent.largestContentfulPaint < 2500',
'transaction.type: (page-load or page-exit) and processor.event: transaction and transaction.marks.agent.largestContentfulPaint < 2500',
},
isBucketed: false,
label: 'Good',
@@ -104,7 +104,7 @@ export const sampleAttributeCoreWebVital = {
query: {
language: 'kuery',
query:
'transaction.type: page-load and processor.event: transaction and transaction.type: "page-load"',
'transaction.type: (page-load or page-exit) and processor.event: transaction and transaction.type: ("page-load" or "page-exit")',
},
visualization: {
axisTitlesVisibilitySettings: {
1 change: 0 additions & 1 deletion x-pack/plugins/observability/public/index.ts
Original file line number Diff line number Diff line change
@@ -52,7 +52,6 @@ export {

export type { SloEditLocatorParams } from './locators/slo_edit';

export type { UXMetrics } from './pages/overview/components/sections/ux/core_web_vitals/core_vitals';
export { getCoreVitalsComponent } from './pages/overview/components/sections/ux/core_web_vitals/get_core_web_vitals_lazy';

export { DatePicker } from './pages/overview/components/date_picker/date_picker';
Original file line number Diff line number Diff line change
@@ -41,6 +41,7 @@ interface Props {
thresholds: Thresholds;
isCls?: boolean;
helpLabel: string;
dataTestSubj?: string;
}

export function getCoreVitalTooltipMessage(
@@ -82,6 +83,7 @@ export function CoreVitalItem({
ranks = [100, 0, 0],
isCls,
helpLabel,
dataTestSubj,
}: Props) {
const palette = euiPaletteForStatus(3);

@@ -96,6 +98,7 @@ export function CoreVitalItem({
return (
<>
<EuiStat
data-test-subj={dataTestSubj}
aria-label={`${title} ${value}`} // aria-label is required when passing a component, instead of a string, as the description
titleSize="s"
title={value ?? ''}
Original file line number Diff line number Diff line change
@@ -7,11 +7,12 @@

import * as React from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import type { UXMetrics } from '@kbn/observability-shared-plugin/public';
import {
CLS_HELP_LABEL,
CLS_LABEL,
FID_HELP_LABEL,
FID_LABEL,
INP_HELP_LABEL,
INP_LABEL,
LCP_HELP_LABEL,
LCP_LABEL,
} from './translations';
@@ -28,18 +29,6 @@ export interface CoreVitalProps {
displayTrafficMetric?: boolean;
}

export interface UXMetrics {
cls: number | null;
fid?: number | null;
lcp?: number | null;
tbt: number;
fcp?: number | null;
coreVitalPages: number;
lcpRanks: number[];
fidRanks: number[];
clsRanks: number[];
}

function formatToSec(value?: number | string, fromUnit = 'MicroSec'): string {
const valueInMs = Number(value ?? 0) / (fromUnit === 'MicroSec' ? 1000 : 1);

@@ -58,7 +47,7 @@ function formatToMilliseconds(value?: number | null) {

const CoreVitalsThresholds = {
LCP: { good: '2.5s', bad: '4.0s' },
FID: { good: '100ms', bad: '300ms' },
INP: { good: '200ms', bad: '500ms' },
CLS: { good: '0.1', bad: '0.25' },
};

@@ -71,7 +60,7 @@ export default function CoreVitals({
totalPageViews,
displayTrafficMetric = false,
}: CoreVitalProps) {
const { lcp, lcpRanks, fid, fidRanks, cls, clsRanks, coreVitalPages } = data || {};
const { lcp, lcpRanks, inp, inpRanks, cls, clsRanks, coreVitalPages } = data || {};

return (
<>
@@ -93,16 +82,18 @@ export default function CoreVitals({
loading={loading}
thresholds={CoreVitalsThresholds.LCP}
helpLabel={LCP_HELP_LABEL}
dataTestSubj={'lcp-core-vital'}
/>
</EuiFlexItem>
<EuiFlexItem style={{ flexBasis: 380 }}>
<CoreVitalItem
title={FID_LABEL}
value={formatToMilliseconds(fid)}
ranks={fidRanks}
title={INP_LABEL}
value={formatToMilliseconds(inp)}
ranks={inpRanks}
loading={loading}
thresholds={CoreVitalsThresholds.FID}
helpLabel={FID_HELP_LABEL}
thresholds={CoreVitalsThresholds.INP}
helpLabel={INP_HELP_LABEL}
dataTestSubj={'inp-core-vital'}
/>
</EuiFlexItem>
<EuiFlexItem style={{ flexBasis: 380 }}>
@@ -114,6 +105,7 @@ export default function CoreVitals({
thresholds={CoreVitalsThresholds.CLS}
isCls={true}
helpLabel={CLS_HELP_LABEL}
dataTestSubj={'cls-core-vital'}
/>
</EuiFlexItem>
</EuiFlexGroup>
Original file line number Diff line number Diff line change
@@ -15,8 +15,8 @@ export const LCP_LABEL = i18n.translate('xpack.observability.ux.coreVitals.lcp',
defaultMessage: 'Largest contentful paint',
});

export const FID_LABEL = i18n.translate('xpack.observability.ux.coreVitals.fip', {
defaultMessage: 'First input delay',
export const INP_LABEL = i18n.translate('xpack.observability.ux.coreVitals.inp', {
defaultMessage: 'Interaction to Next Paint',
});

export const CLS_LABEL = i18n.translate('xpack.observability.ux.coreVitals.cls', {
@@ -71,9 +71,9 @@ export const LCP_HELP_LABEL = i18n.translate('xpack.observability.ux.coreVitals.
'Largest contentful paint measures loading performance. To provide a good user experience, LCP should occur within 2.5 seconds of when the page first starts loading.',
});

export const FID_HELP_LABEL = i18n.translate('xpack.observability.ux.coreVitals.fid.help', {
export const INP_HELP_LABEL = i18n.translate('xpack.observability.ux.coreVitals.inp.help', {
defaultMessage:
'First input delay measures interactivity. To provide a good user experience, pages should have a FID of less than 100 milliseconds.',
'INP assesses responsiveness using data from the Event Timing API. When an interaction causes a page to become unresponsive, that is a poor user experience. INP observes the latency of all interactions a user has made with the page, and reports a single value which all (or nearly all) interactions were below. A low INP means the page was consistently able to respond quickly to all—or the vast majority—of user interactions.',
});

export const CLS_HELP_LABEL = i18n.translate('xpack.observability.ux.coreVitals.cls.help', {
Original file line number Diff line number Diff line change
@@ -11,13 +11,13 @@ export const response: UxFetchDataResponse = {
appLink: '/app/ux',
coreWebVitals: {
cls: 0.01,
fid: 13.5,
lcp: 1942.6666666666667,
tbt: 281.55833333333334,
fcp: 1487,
inp: 285,
coreVitalPages: 100,
lcpRanks: [65, 19, 16],
fidRanks: [73, 11, 16],
inpRanks: [73, 11, 16],
clsRanks: [86, 8, 6],
},
};
Original file line number Diff line number Diff line change
@@ -60,7 +60,7 @@ describe('UXSection', () => {
expect(getByText('elastic-co-frontend')).toBeInTheDocument();
expect(getByText('Largest contentful paint')).toBeInTheDocument();
expect(getByText('1.94 s')).toBeInTheDocument();
expect(getByText('14 ms')).toBeInTheDocument();
expect(getByText('285 ms')).toBeInTheDocument();
expect(getByText('0.010')).toBeInTheDocument();

// LCP Rank Values
Original file line number Diff line number Diff line change
@@ -5,8 +5,8 @@
* 2.0.
*/

import { UXMetrics } from '@kbn/observability-shared-plugin/public';
import type { ObservabilityApp } from '../../../typings/common';
import type { UXMetrics } from '../../pages/overview/components/sections/ux/core_web_vitals/core_vitals';
import { ApmIndicesConfig } from '../../../common/typings';

export interface Stat {
Loading

0 comments on commit 9695939

Please sign in to comment.