Skip to content

Commit

Permalink
[UX] Fix core vitals empty state (#81781)
Browse files Browse the repository at this point in the history
  • Loading branch information
shahzad31 authored Oct 28, 2020
1 parent e7f425a commit 2a4337e
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ interface Props {
loading: boolean;
}

function formatTitle(unit: string, value?: number) {
if (typeof value === 'undefined') return DATA_UNDEFINED_LABEL;
function formatTitle(unit: string, value?: number | null) {
if (typeof value === 'undefined' || value === null)
return DATA_UNDEFINED_LABEL;
return formatToSec(value, unit);
}

Expand Down Expand Up @@ -85,8 +86,8 @@ export function KeyUXMetrics({ data, loading }: Props) {
<EuiStat
titleSize="s"
title={
longTaskData?.noOfLongTasks
? numeral(longTaskData.noOfLongTasks).format('0,0')
longTaskData?.noOfLongTasks !== undefined
? numeral(longTaskData?.noOfLongTasks).format('0,0')
: DATA_UNDEFINED_LABEL
}
description={NO_OF_LONG_TASK}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ describe('KeyUXMetrics', () => {
lcpRanks: [69, 17, 14],
fidRanks: [83, 6, 11],
clsRanks: [90, 7, 3],
coreVitalPages: 1000,
}}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import React, { useContext } from 'react';
import {
EuiFlexGroup,
EuiFlexItem,
Expand All @@ -18,6 +18,7 @@ import { KeyUXMetrics } from './KeyUXMetrics';
import { useFetcher } from '../../../../hooks/useFetcher';
import { useUxQuery } from '../hooks/useUxQuery';
import { CoreVitals } from '../../../../../../observability/public';
import { CsmSharedContext } from '../CsmSharedContext';
import { useUrlParams } from '../../../../hooks/useUrlParams';
import { getPercentileLabel } from './translations';

Expand All @@ -43,6 +44,10 @@ export function UXMetrics() {
[uxQuery]
);

const {
sharedData: { totalPageViews },
} = useContext(CsmSharedContext);

return (
<EuiPanel>
<EuiFlexGroup justifyContent="spaceBetween" wrap>
Expand All @@ -62,7 +67,12 @@ export function UXMetrics() {
<EuiFlexGroup justifyContent="spaceBetween" wrap>
<EuiFlexItem grow={1} data-cy={`client-metrics`}>
<EuiSpacer size="s" />
<CoreVitals data={data} loading={status !== 'success'} />
<CoreVitals
data={data}
totalPageViews={totalPageViews}
loading={status !== 'success'}
displayTrafficMetric={true}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,11 @@ export function UserPercentile() {
{
value: '50',
text: I18LABELS.percentile50thMedian,
dropdownDisplay: I18LABELS.percentile50thMedian,
'data-test-subj': 'p50Percentile',
},
{
value: '75',
text: I18LABELS.percentile75th,
dropdownDisplay: I18LABELS.percentile75th,
'data-test-subj': 'p75Percentile',
},
{
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 36 additions & 25 deletions x-pack/plugins/apm/server/lib/rum_client/get_web_core_vitals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
FCP_FIELD,
FID_FIELD,
LCP_FIELD,
USER_AGENT_NAME,
TBT_FIELD,
} from '../../../common/elasticsearch_fieldnames';

Expand All @@ -35,17 +34,17 @@ export async function getWebCoreVitals({
size: 0,
query: {
bool: {
filter: [
...projection.body.query.bool.filter,
{
term: {
[USER_AGENT_NAME]: 'Chrome',
},
},
],
filter: [...projection.body.query.bool.filter],
},
},
aggs: {
coreVitalPages: {
filter: {
exists: {
field: 'transaction.experience',
},
},
},
lcp: {
percentiles: {
field: LCP_FIELD,
Expand Down Expand Up @@ -104,37 +103,49 @@ export async function getWebCoreVitals({
const { apmEventClient } = setup;

const response = await apmEventClient.search(params);
const { lcp, cls, fid, tbt, fcp, lcpRanks, fidRanks, clsRanks } =
response.aggregations ?? {};
const {
lcp,
cls,
fid,
tbt,
fcp,
lcpRanks,
fidRanks,
clsRanks,
coreVitalPages,
} = response.aggregations ?? {};

const getRanksPercentages = (
ranks: Array<{ key: number; value: number }>
ranks?: Array<{ key: number; value: number }>
) => {
const ranksVal = ranks.map(({ value }) => value?.toFixed(0) ?? 0);
const ranksVal = ranks?.map(({ value }) => value?.toFixed(0) ?? 0) ?? [];
return [
Number(ranksVal?.[0]),
Number(ranksVal?.[1]) - Number(ranksVal?.[0]),
100 - Number(ranksVal?.[1]),
];
};

const defaultRanks = [
{ value: 0, key: 0 },
{ value: 0, key: 0 },
];
const defaultRanks = [100, 0, 0];

const pkey = percentile.toFixed(1);

// Divide by 1000 to convert ms into seconds
return {
cls: String(cls?.values[pkey]?.toFixed(2) || 0),
fid: fid?.values[pkey] ?? 0,
lcp: lcp?.values[pkey] ?? 0,
coreVitalPages: coreVitalPages?.doc_count ?? 0,
cls: cls?.values[pkey]?.toFixed(3) || null,
fid: fid?.values[pkey],
lcp: lcp?.values[pkey],
tbt: tbt?.values[pkey] ?? 0,
fcp: fcp?.values[pkey] ?? 0,
fcp: fcp?.values[pkey],

lcpRanks: getRanksPercentages(lcpRanks?.values ?? defaultRanks),
fidRanks: getRanksPercentages(fidRanks?.values ?? defaultRanks),
clsRanks: getRanksPercentages(clsRanks?.values ?? defaultRanks),
lcpRanks: lcp?.values[pkey]
? getRanksPercentages(lcpRanks?.values)
: defaultRanks,
fidRanks: fid?.values[pkey]
? getRanksPercentages(fidRanks?.values)
: defaultRanks,
clsRanks: cls?.values[pkey]
? getRanksPercentages(clsRanks?.values)
: defaultRanks,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const response: UxFetchDataResponse = {
lcp: 1942.6666666666667,
tbt: 281.55833333333334,
fcp: 1487,
coreVitalPages: 100,
lcpRanks: [65, 19, 16],
fidRanks: [73, 11, 16],
clsRanks: [86, 8, 6],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export interface Thresholds {

interface Props {
title: string;
value?: string;
value?: string | null;
ranks?: number[];
loading: boolean;
thresholds: Thresholds;
Expand Down Expand Up @@ -88,14 +88,14 @@ export function CoreVitalItem({

const biggestValIndex = ranks.indexOf(Math.max(...ranks));

if (value === undefined && ranks[0] === 100 && !loading) {
if ((value === null || value !== undefined) && ranks[0] === 100 && !loading) {
return <EuiCard title={title} isDisabled={true} description={NO_DATA} />;
}
return (
<>
<EuiStat
titleSize="s"
title={value}
title={value ?? ''}
description={
<>
{title}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ import { WebCoreVitalsTitle } from './web_core_vitals_title';
import { ServiceName } from './service_name';

export interface UXMetrics {
cls: string;
fid: number;
lcp: number;
cls: string | null;
fid?: number | null;
lcp?: number | null;
tbt: number;
fcp: number;
fcp?: number | null;
coreVitalPages: number;
lcpRanks: number[];
fidRanks: number[];
clsRanks: number[];
Expand All @@ -48,21 +49,35 @@ interface Props {
data?: UXMetrics | null;
displayServiceName?: boolean;
serviceName?: string;
totalPageViews?: number;
displayTrafficMetric?: boolean;
}

function formatValue(value?: number) {
if (typeof value === 'undefined') {
return undefined;
function formatValue(value?: number | null) {
if (typeof value === 'undefined' || value === null) {
return null;
}
return formatToSec(value, 'ms');
}

export function CoreVitals({ data, loading, displayServiceName, serviceName }: Props) {
const { lcp, lcpRanks, fid, fidRanks, cls, clsRanks } = data || {};
export function CoreVitals({
data,
loading,
displayServiceName,
serviceName,
totalPageViews,
displayTrafficMetric = false,
}: Props) {
const { lcp, lcpRanks, fid, fidRanks, cls, clsRanks, coreVitalPages } = data || {};

return (
<>
<WebCoreVitalsTitle />
<WebCoreVitalsTitle
loading={loading}
coreVitalPages={coreVitalPages}
totalPageViews={totalPageViews}
displayTrafficMetric={displayTrafficMetric}
/>
<EuiSpacer size="s" />
{displayServiceName && <ServiceName name={serviceName!} />}
<EuiSpacer size="s" />
Expand Down Expand Up @@ -90,7 +105,7 @@ export function CoreVitals({ data, loading, displayServiceName, serviceName }: P
<EuiFlexItem style={{ flexBasis: 380 }}>
<CoreVitalItem
title={CLS_LABEL}
value={cls}
value={cls ?? null}
ranks={clsRanks}
loading={loading}
thresholds={CoreVitalsThresholds.CLS}
Expand Down
Loading

0 comments on commit 2a4337e

Please sign in to comment.