mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[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:
parent
f296abb6c9
commit
abfe96ff89
9 changed files with 105 additions and 131 deletions
|
@ -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} />;
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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),
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
|
@ -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),
|
||||
},
|
||||
],
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
@ -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)',
|
||||
});
|
||||
|
|
|
@ -57,7 +57,7 @@ export const StepMetrics = () => {
|
|||
previous={prevVal?.value ?? 0}
|
||||
helpText={helpText}
|
||||
currentFormatted={formatted}
|
||||
previousFormatted={prevVal?.formatted!}
|
||||
previousFormatted={prevVal?.formatted}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue