[Synthetics] Step metrics (#149481)

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Fixes https://github.com/elastic/kibana/issues/145392
This commit is contained in:
Shahzad 2023-02-01 12:19:22 +01:00 committed by GitHub
parent f296abb6c9
commit abfe96ff89
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 105 additions and 131 deletions

View file

@ -38,10 +38,10 @@ export const ThresholdIndicator = ({
loading: boolean;
current: number;
previous?: number | null;
previousFormatted: string;
currentFormatted: string;
asStat?: boolean;
previousFormatted?: string | number;
currentFormatted: string | number;
setHasAnyDelta?: (hasDelta: boolean) => void;
asStat?: boolean;
}) => {
if (loading) {
return <EuiLoadingContent lines={1} />;

View file

@ -10,7 +10,6 @@ import { EuiDescriptionList, EuiSpacer, EuiText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useStepMetrics } from '../../step_details_page/hooks/use_step_metrics';
import { JourneyStepScreenshotContainer } from '../screenshot/journey_step_screenshot_container';
import { formatBytes } from '../../step_details_page/hooks/use_object_metrics';
import { ThresholdIndicator } from '../components/thershold_indicator';
import { useNetworkTimings } from '../../step_details_page/hooks/use_network_timings';
import { useNetworkTimingsPrevious24Hours } from '../../step_details_page/hooks/use_network_timings_prev';
@ -62,16 +61,12 @@ export const ResultDetails = ({
};
export const TimingDetails = ({ step }: { step: JourneyStep }) => {
const { timingsWithLabels, transferSize } = useNetworkTimings(
const { timingsWithLabels } = useNetworkTimings(
step.monitor.check_group,
step.synthetics.step?.index
);
const {
timingsWithLabels: prevTimingsWithLabels,
loading,
transferSizePrev,
} = useNetworkTimingsPrevious24Hours(
const { timingsWithLabels: prevTimingsWithLabels, loading } = useNetworkTimingsPrevious24Hours(
step.synthetics.step?.index,
step['@timestamp'],
step.monitor.check_group
@ -94,19 +89,6 @@ export const TimingDetails = ({ step }: { step: JourneyStep }) => {
};
});
items.push({
title: transferSize.label,
description: (
<ThresholdIndicator
loading={loading}
current={transferSize.value}
previous={transferSizePrev.value}
currentFormatted={formatBytes(transferSize.value ?? 0)}
previousFormatted={formatBytes(transferSizePrev.value ?? 0)}
/>
),
});
return (
<EuiDescriptionList
compressed={true}

View file

@ -18,7 +18,6 @@ import {
SYNTHETICS_TOTAL_TIMINGS,
SYNTHETICS_WAIT_TIMINGS,
} from '@kbn/observability-plugin/common';
import { CONTENT_SIZE_LABEL } from './use_network_timings_prev';
import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants';
import { useReduxEsSearch } from '../../../hooks/use_redux_es_search';
@ -58,12 +57,8 @@ export const useNetworkTimings = (checkGroupIdArg?: string, stepIndexArg?: numbe
index: SYNTHETICS_INDEX_PATTERN,
body: {
size: 0,
runtime_mappings: {
...runTimeMappings,
'synthetics.payload.transfer_size': {
type: 'long',
},
},
runtime_mappings: runTimeMappings,
query: {
bool: {
filter: [
@ -117,11 +112,6 @@ export const useNetworkTimings = (checkGroupIdArg?: string, stepIndexArg?: numbe
field: SYNTHETICS_TOTAL_TIMINGS,
},
},
transferSize: {
sum: {
field: 'synthetics.payload.transfer_size',
},
},
},
},
},
@ -139,15 +129,10 @@ export const useNetworkTimings = (checkGroupIdArg?: string, stepIndexArg?: numbe
wait: aggs?.wait.value ?? 0,
blocked: aggs?.blocked.value ?? 0,
tls: aggs?.tls.value ?? 0,
transferSize: aggs?.transferSize.value ?? 0,
};
return {
timings,
transferSize: {
value: timings.transferSize,
label: CONTENT_SIZE_LABEL,
},
timingsWithLabels: getTimingWithLabels(timings),
};
};

View file

@ -69,12 +69,7 @@ export const useNetworkTimingsPrevious24Hours = (
index: SYNTHETICS_INDEX_PATTERN,
body: {
size: 0,
runtime_mappings: {
...runTimeMappings,
'synthetics.payload.transfer_size': {
type: 'long',
},
},
runtime_mappings: runTimeMappings,
query: {
bool: {
filter: [
@ -158,11 +153,6 @@ export const useNetworkTimingsPrevious24Hours = (
field: SYNTHETICS_TOTAL_TIMINGS,
},
},
transferSize: {
sum: {
field: 'synthetics.payload.transfer_size',
},
},
},
},
},
@ -184,7 +174,6 @@ export const useNetworkTimingsPrevious24Hours = (
const wait: number[] = [];
const blocked: number[] = [];
const ssl: number[] = [];
const transferSize: number[] = [];
aggs?.testRuns.buckets.forEach((bucket) => {
dns.push(bucket.dns.value ?? 0);
@ -194,7 +183,6 @@ export const useNetworkTimingsPrevious24Hours = (
wait.push(bucket.wait.value ?? 0);
blocked.push(bucket.blocked.value ?? 0);
ssl.push(bucket.ssl.value ?? 0);
transferSize.push(bucket.transferSize.value ?? 0);
});
const timings = {
@ -205,21 +193,16 @@ export const useNetworkTimingsPrevious24Hours = (
wait: median(wait),
blocked: median(blocked),
ssl: median(ssl),
transferSize: median(transferSize),
};
return {
loading,
timings,
transferSizePrev: {
value: timings.transferSize,
label: CONTENT_SIZE_LABEL,
},
timingsWithLabels: getTimingWithLabels(timings),
};
};
const median = (arr: number[]): number => {
export const median = (arr: number[]): number => {
if (!arr.length) return 0;
const s = [...arr].sort((a, b) => a - b);
const mid = Math.floor(s.length / 2);

View file

@ -1,24 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { useParams } from 'react-router-dom';
export const useStepFilters = (prevCheckGroupId?: string) => {
const { checkGroupId, stepIndex } = useParams<{ checkGroupId: string; stepIndex: string }>();
return [
{
term: {
'monitor.check_group': prevCheckGroupId ?? checkGroupId,
},
},
{
term: {
'synthetics.step.index': Number(stepIndex),
},
},
];
};

View file

@ -10,7 +10,13 @@ import { useParams } from 'react-router-dom';
import { i18n } from '@kbn/i18n';
import { formatBytes } from './use_object_metrics';
import { formatMillisecond } from '../step_metrics/step_metrics';
import { CLS_HELP_LABEL, DCL_TOOLTIP, FCP_TOOLTIP, LCP_HELP_LABEL } from '../step_metrics/labels';
import {
CLS_HELP_LABEL,
DCL_TOOLTIP,
FCP_TOOLTIP,
LCP_HELP_LABEL,
TRANSFER_SIZE_HELP,
} from '../step_metrics/labels';
import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants';
import { JourneyStep } from '../../../../../../common/runtime_types';
@ -173,7 +179,7 @@ export const useStepMetrics = (step?: JourneyStep) => {
value: metrics?.cls.value,
label: CLS_LABEL,
helpText: CLS_HELP_LABEL,
formatted: formatMillisecond((metrics?.cls.value ?? 0) / 1000),
formatted: metrics?.cls.value ?? 0,
},
{
value: metrics?.dcl.value,
@ -184,7 +190,7 @@ export const useStepMetrics = (step?: JourneyStep) => {
{
value: transferDataVal,
label: TRANSFER_SIZE,
helpText: '',
helpText: TRANSFER_SIZE_HELP,
formatted: formatBytes(transferDataVal ?? 0),
},
],

View file

@ -9,7 +9,6 @@ import { useParams } from 'react-router-dom';
import { useEsSearch } from '@kbn/observability-plugin/public';
import { formatBytes } from './use_object_metrics';
import { formatMillisecond } from '../step_metrics/step_metrics';
import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants';
import {
CLS_LABEL,
DCL_LABEL,
@ -19,6 +18,8 @@ import {
TRANSFER_SIZE,
} from './use_step_metrics';
import { JourneyStep } from '../../../../../../common/runtime_types';
import { median } from './use_network_timings_prev';
import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants';
export const MONITOR_DURATION_US = 'monitor.duration.us';
export const SYNTHETICS_CLS = 'browser.experience.cls';
@ -75,29 +76,37 @@ export const useStepPrevMetrics = (step?: JourneyStep) => {
},
},
aggs: {
fcp: {
avg: {
field: SYNTHETICS_FCP,
testRuns: {
terms: {
field: 'monitor.check_group',
size: 10000,
},
},
lcp: {
avg: {
field: SYNTHETICS_LCP,
},
},
cls: {
avg: {
field: SYNTHETICS_CLS,
},
},
dcl: {
avg: {
field: SYNTHETICS_DCL,
},
},
totalDuration: {
avg: {
field: SYNTHETICS_STEP_DURATION,
aggs: {
fcp: {
sum: {
field: SYNTHETICS_FCP,
},
},
lcp: {
sum: {
field: SYNTHETICS_LCP,
},
},
cls: {
sum: {
field: SYNTHETICS_CLS,
},
},
dcl: {
sum: {
field: SYNTHETICS_DCL,
},
},
stepDuration: {
sum: {
field: SYNTHETICS_STEP_DURATION,
},
},
},
},
},
@ -106,7 +115,6 @@ export const useStepPrevMetrics = (step?: JourneyStep) => {
[monitorId, checkGroupId, stepIndex],
{ name: 'previousStepMetrics' }
);
const { data: transferData } = useEsSearch(
{
index: SYNTHETICS_INDEX_PATTERN,
@ -150,14 +158,17 @@ export const useStepPrevMetrics = (step?: JourneyStep) => {
},
},
aggs: {
transferSize: {
avg: {
field: 'synthetics.payload.transfer_size',
testRuns: {
terms: {
field: 'monitor.check_group',
size: 10000,
},
},
resourceSize: {
avg: {
field: 'synthetics.payload.resource_size',
aggs: {
transferSize: {
sum: {
field: 'synthetics.payload.transfer_size',
},
},
},
},
},
@ -170,40 +181,66 @@ export const useStepPrevMetrics = (step?: JourneyStep) => {
);
const metrics = data?.aggregations;
const transferDataVal = transferData?.aggregations?.transferSize?.value ?? 0;
const transferSize: number[] = [];
transferData?.aggregations?.testRuns.buckets.forEach((bucket) => {
transferSize.push(bucket.transferSize.value ?? 0);
});
const medianTransferSize = median(transferSize);
const lcp: number[] = [];
const fcp: number[] = [];
const cls: number[] = [];
const dcl: number[] = [];
const stepDuration: number[] = [];
metrics?.testRuns.buckets.forEach((bucket) => {
lcp.push(bucket.lcp.value ?? 0);
fcp.push(bucket.fcp.value ?? 0);
cls.push(bucket.cls.value ?? 0);
dcl.push(bucket.dcl.value ?? 0);
stepDuration.push(bucket.stepDuration.value ?? 0);
});
const medianLcp = median(lcp);
const medianFcp = median(fcp);
const medianCls = median(cls);
const medianDcl = median(dcl);
const medianStepDuration = median(stepDuration);
return {
loading,
metrics: [
{
label: STEP_DURATION_LABEL,
value: metrics?.totalDuration.value,
formatted: formatMillisecond((metrics?.totalDuration.value ?? 0) / 1000),
value: medianStepDuration,
formatted: formatMillisecond(medianStepDuration / 1000),
},
{
value: metrics?.lcp.value,
value: medianLcp,
label: LCP_LABEL,
formatted: formatMillisecond((metrics?.lcp.value ?? 0) / 1000),
formatted: formatMillisecond(medianLcp / 1000),
},
{
value: metrics?.fcp.value,
value: medianFcp,
label: FCP_LABEL,
formatted: formatMillisecond((metrics?.fcp.value ?? 0) / 1000),
formatted: formatMillisecond(medianFcp / 1000),
},
{
value: metrics?.cls.value,
value: medianCls,
label: CLS_LABEL,
formatted: formatMillisecond((metrics?.cls.value ?? 0) / 1000),
formatted: medianCls,
},
{
value: metrics?.dcl.value,
value: medianDcl,
label: DCL_LABEL,
formatted: formatMillisecond((metrics?.dcl.value ?? 0) / 1000),
formatted: formatMillisecond(medianDcl / 1000),
},
{
value: transferDataVal,
value: medianTransferSize,
label: TRANSFER_SIZE,
formatted: formatBytes(transferDataVal ?? 0),
formatted: formatBytes(medianTransferSize),
},
],
};

View file

@ -27,6 +27,11 @@ export const DCL_TOOLTIP = i18n.translate('xpack.synthetics.coreVitals.dclToolti
'Triggered when the browser completes parsing the document. Helpful when there are multiple listeners, or logic is executed: domContentLoadedEventEnd - domContentLoadedEventStart.',
});
export const TRANSFER_SIZE_HELP = i18n.translate('xpack.synthetics.fieldLabels.transferSize', {
defaultMessage:
'The transferSize property represents the size of the fetched resource. The size includes the response header fields plus the response payload body',
});
export const LCP_LABEL = i18n.translate('xpack.synthetics.fieldLabels.lcp', {
defaultMessage: 'Largest contentful paint (LCP)',
});

View file

@ -57,7 +57,7 @@ export const StepMetrics = () => {
previous={prevVal?.value ?? 0}
helpText={helpText}
currentFormatted={formatted}
previousFormatted={prevVal?.formatted!}
previousFormatted={prevVal?.formatted}
/>
</EuiFlexItem>
);