From e7e42a47117da9ad2415f0108736842dd3798a8c Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 25 Jan 2021 16:07:53 +0100 Subject: [PATCH] [Uptime] Display networks requests total (#88672) --- .../common/runtime_types/network_events.ts | 1 + .../waterfall/waterfall_chart_container.tsx | 5 +- .../waterfall/waterfall_chart_wrapper.tsx | 5 +- .../network_requests_total.test.tsx | 28 ++++++++++ .../components/network_requests_total.tsx | 44 ++++++++++++++++ .../synthetics/waterfall/components/styles.ts | 7 ++- .../waterfall/components/waterfall_chart.tsx | 16 +++++- .../waterfall/context/waterfall_chart.tsx | 17 +++++- .../public/state/reducers/network_events.ts | 12 ++++- .../lib/requests/get_network_events.test.ts | 52 +++++++++++-------- .../server/lib/requests/get_network_events.ts | 45 +++++++++------- .../network_events/get_network_events.ts | 4 +- 12 files changed, 183 insertions(+), 53 deletions(-) create mode 100644 x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/network_requests_total.test.tsx create mode 100644 x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/network_requests_total.tsx diff --git a/x-pack/plugins/uptime/common/runtime_types/network_events.ts b/x-pack/plugins/uptime/common/runtime_types/network_events.ts index 6104758f28fd82..fc666c803e2c3d 100644 --- a/x-pack/plugins/uptime/common/runtime_types/network_events.ts +++ b/x-pack/plugins/uptime/common/runtime_types/network_events.ts @@ -41,6 +41,7 @@ export type NetworkEvent = t.TypeOf; export const SyntheticsNetworkEventsApiResponseType = t.type({ events: t.array(NetworkEventType), + total: t.number, }); export type SyntheticsNetworkEventsApiResponse = t.TypeOf< diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_container.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_container.tsx index 7657ca7f9c64a9..680e3f257841e7 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_container.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_container.tsx @@ -59,7 +59,10 @@ export const WaterfallChartContainer: React.FC = ({ checkGroup, stepIndex )} {networkEvents && !networkEvents.loading && networkEvents.events.length > 0 && ( - + )} ); diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.tsx index a84765c4ea1541..7b904511b58ab2 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.tsx @@ -48,10 +48,11 @@ export const renderLegendItem: RenderItem = (item) => { }; interface Props { + total: number; data: NetworkItems; } -export const WaterfallChartWrapper: React.FC = ({ data }) => { +export const WaterfallChartWrapper: React.FC = ({ data, total }) => { const [networkData] = useState(data); const { series, domain } = useMemo(() => { @@ -66,6 +67,8 @@ export const WaterfallChartWrapper: React.FC = ({ data }) => { return ( { + it('message in case total is greater than fetched', () => { + const { getByText, getByLabelText } = render( + + ); + + expect(getByText('First 1000/1100 network requests')).toBeInTheDocument(); + expect(getByLabelText('Info')).toBeInTheDocument(); + }); + + it('message in case total is equal to fetched requests', () => { + const { getByText } = render( + + ); + + expect(getByText('500 network requests')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/network_requests_total.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/network_requests_total.tsx new file mode 100644 index 00000000000000..c54e32238f81c0 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/network_requests_total.tsx @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiIconTip } from '@elastic/eui'; +import { NetworkRequestsTotalStyle } from './styles'; + +interface Props { + totalNetworkRequests: number; + fetchedNetworkRequests: number; +} + +export const NetworkRequestsTotal = ({ totalNetworkRequests, fetchedNetworkRequests }: Props) => { + return ( + + + {i18n.translate('xpack.uptime.synthetics.waterfall.requestsTotalMessage', { + defaultMessage: '{numNetworkRequests} network requests', + values: { + numNetworkRequests: + totalNetworkRequests > fetchedNetworkRequests + ? i18n.translate('xpack.uptime.synthetics.waterfall.requestsTotalMessage.first', { + defaultMessage: 'First {count}', + values: { count: `${fetchedNetworkRequests}/${totalNetworkRequests}` }, + }) + : totalNetworkRequests, + }, + })} + + {totalNetworkRequests > fetchedNetworkRequests && ( + + )} + + ); +}; diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/styles.ts b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/styles.ts index 1f70354db154e9..7bf5100730f5e4 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/styles.ts +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/styles.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiPanel, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; import { rgba } from 'polished'; import { euiStyled } from '../../../../../../../observability/public'; import { FIXED_AXIS_HEIGHT } from './constants'; @@ -103,3 +103,8 @@ export const WaterfallChartTooltip = euiStyled.div` color: ${(props) => props.theme.eui.euiColorLightestShade}; padding: ${(props) => props.theme.eui.paddingSizes.s}; `; + +export const NetworkRequestsTotalStyle = euiStyled(EuiText)` + line-height: ${FIXED_AXIS_HEIGHT}px; + margin-left: ${(props) => props.theme.eui.paddingSizes.m} +`; diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_chart.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_chart.tsx index e937c3d35ec08d..e449fed6decf49 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_chart.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_chart.tsx @@ -37,6 +37,7 @@ import { BAR_HEIGHT, CANVAS_MAX_ITEMS, MAIN_GROW_SIZE, SIDEBAR_GROW_SIZE } from import { Sidebar } from './sidebar'; import { Legend } from './legend'; import { useBarCharts } from './use_bar_charts'; +import { NetworkRequestsTotal } from './network_requests_total'; const Tooltip = (tooltipInfo: TooltipInfo) => { const { data, renderTooltipItem } = useWaterfallContext(); @@ -84,7 +85,13 @@ export const WaterfallChart = ({ maxHeight = '800px', fullHeight = false, }: WaterfallChartProps) => { - const { data, sidebarItems, legendItems } = useWaterfallContext(); + const { + data, + sidebarItems, + legendItems, + totalNetworkRequests, + fetchedNetworkRequests, + } = useWaterfallContext(); const [darkMode] = useUiSetting$('theme:darkMode'); @@ -115,7 +122,12 @@ export const WaterfallChart = ({ {shouldRenderSidebar && ( - + + + )} diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/context/waterfall_chart.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/context/waterfall_chart.tsx index ccee9d7994c80a..4cf22f317bbd4d 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/context/waterfall_chart.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/context/waterfall_chart.tsx @@ -8,6 +8,8 @@ import React, { createContext, useContext, Context } from 'react'; import { WaterfallData, WaterfallDataEntry } from '../types'; export interface IWaterfallContext { + totalNetworkRequests: number; + fetchedNetworkRequests: number; data: WaterfallData; sidebarItems?: unknown[]; legendItems?: unknown[]; @@ -20,6 +22,8 @@ export interface IWaterfallContext { export const WaterfallContext = createContext>({}); interface ProviderProps { + totalNetworkRequests: number; + fetchedNetworkRequests: number; data: IWaterfallContext['data']; sidebarItems?: IWaterfallContext['sidebarItems']; legendItems?: IWaterfallContext['legendItems']; @@ -32,9 +36,20 @@ export const WaterfallProvider: React.FC = ({ sidebarItems, legendItems, renderTooltipItem, + totalNetworkRequests, + fetchedNetworkRequests, }) => { return ( - + {children} ); diff --git a/x-pack/plugins/uptime/public/state/reducers/network_events.ts b/x-pack/plugins/uptime/public/state/reducers/network_events.ts index 44a23b0fa53d77..666617f7851829 100644 --- a/x-pack/plugins/uptime/public/state/reducers/network_events.ts +++ b/x-pack/plugins/uptime/public/state/reducers/network_events.ts @@ -18,6 +18,7 @@ export interface NetworkEventsState { [checkGroup: string]: { [stepIndex: number]: { events: NetworkEvent[]; + total: number; loading: boolean; error?: Error; }; @@ -45,16 +46,19 @@ export const networkEventsReducer = handleActions( ...state[checkGroup][stepIndex], loading: true, events: [], + total: 0, } : { loading: true, events: [], + total: 0, }, } : { [stepIndex]: { loading: true, events: [], + total: 0, }, }, }), @@ -62,7 +66,7 @@ export const networkEventsReducer = handleActions( [String(getNetworkEventsSuccess)]: ( state: NetworkEventsState, { - payload: { events, checkGroup, stepIndex }, + payload: { events, total, checkGroup, stepIndex }, }: Action ) => { return { @@ -74,16 +78,19 @@ export const networkEventsReducer = handleActions( ...state[checkGroup][stepIndex], loading: false, events, + total, } : { loading: false, events, + total, }, } : { [stepIndex]: { loading: false, events, + total, }, }, }; @@ -101,11 +108,13 @@ export const networkEventsReducer = handleActions( ...state[checkGroup][stepIndex], loading: false, events: [], + total: 0, error, } : { loading: false, events: [], + total: 0, error, }, } @@ -113,6 +122,7 @@ export const networkEventsReducer = handleActions( [stepIndex]: { loading: false, events: [], + total: 0, error, }, }, diff --git a/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts b/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts index e8618fabc4cca3..2d590e80ca42d2 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts @@ -158,6 +158,7 @@ describe('getNetworkEvents', () => { esClient.search.mockResolvedValueOnce({ body: { hits: { + total: { value: 1 }, hits: mockHits, }, }, @@ -196,6 +197,7 @@ describe('getNetworkEvents', () => { }, }, "size": 1000, + "track_total_hits": true, }, "index": "heartbeat-8*", }, @@ -210,6 +212,7 @@ describe('getNetworkEvents', () => { esClient.search.mockResolvedValueOnce({ body: { hits: { + total: { value: 1 }, hits: mockHits, }, }, @@ -222,30 +225,33 @@ describe('getNetworkEvents', () => { }); expect(result).toMatchInlineSnapshot(` - Array [ - Object { - "loadEndTime": 3287298.251, - "method": "GET", - "mimeType": "image/gif", - "requestSentTime": 3287154.973, - "requestStartTime": 3287155.502, - "status": 200, - "timestamp": "2020-12-14T10:46:39.183Z", - "timings": Object { - "blocked": 0.21400000014182297, - "connect": -1, - "dns": -1, - "proxy": -1, - "queueing": 0.5289999999149586, - "receive": 0.5340000002433953, - "send": 0.18799999998009298, - "ssl": -1, - "total": 143.27800000000934, - "wait": 141.81299999972907, + Object { + "events": Array [ + Object { + "loadEndTime": 3287298.251, + "method": "GET", + "mimeType": "image/gif", + "requestSentTime": 3287154.973, + "requestStartTime": 3287155.502, + "status": 200, + "timestamp": "2020-12-14T10:46:39.183Z", + "timings": Object { + "blocked": 0.21400000014182297, + "connect": -1, + "dns": -1, + "proxy": -1, + "queueing": 0.5289999999149586, + "receive": 0.5340000002433953, + "send": 0.18799999998009298, + "ssl": -1, + "total": 143.27800000000934, + "wait": 141.81299999972907, + }, + "url": "www.test.com", }, - "url": "www.test.com", - }, - ] + ], + "total": 1, + } `); }); }); diff --git a/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts b/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts index 1353175a8f94d2..ec1fffd62350d9 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts @@ -14,9 +14,10 @@ interface GetNetworkEventsParams { export const getNetworkEvents: UMElasticsearchQueryFn< GetNetworkEventsParams, - NetworkEvent[] + { events: NetworkEvent[]; total: number } > = async ({ uptimeEsClient, checkGroup, stepIndex }) => { const params = { + track_total_hits: true, query: { bool: { filter: [ @@ -36,24 +37,28 @@ export const getNetworkEvents: UMElasticsearchQueryFn< const microToMillis = (micro: number): number => (micro === -1 ? -1 : micro * 1000); - return result.hits.hits.map((event: any) => { - const requestSentTime = microToMillis(event._source.synthetics.payload.request_sent_time); - const loadEndTime = microToMillis(event._source.synthetics.payload.load_end_time); - const requestStartTime = - event._source.synthetics.payload.response && event._source.synthetics.payload.response.timing - ? microToMillis(event._source.synthetics.payload.response.timing.request_time) - : undefined; + return { + total: result.hits.total.value, + events: result.hits.hits.map((event: any) => { + const requestSentTime = microToMillis(event._source.synthetics.payload.request_sent_time); + const loadEndTime = microToMillis(event._source.synthetics.payload.load_end_time); + const requestStartTime = + event._source.synthetics.payload.response && + event._source.synthetics.payload.response.timing + ? microToMillis(event._source.synthetics.payload.response.timing.request_time) + : undefined; - return { - timestamp: event._source['@timestamp'], - method: event._source.synthetics.payload?.method, - url: event._source.synthetics.payload?.url, - status: event._source.synthetics.payload?.status, - mimeType: event._source.synthetics.payload?.response?.mime_type, - requestSentTime, - requestStartTime, - loadEndTime, - timings: event._source.synthetics.payload.timings, - }; - }); + return { + timestamp: event._source['@timestamp'], + method: event._source.synthetics.payload?.method, + url: event._source.synthetics.payload?.url, + status: event._source.synthetics.payload?.status, + mimeType: event._source.synthetics.payload?.response?.mime_type, + requestSentTime, + requestStartTime, + loadEndTime, + timings: event._source.synthetics.payload.timings, + }; + }), + }; }; diff --git a/x-pack/plugins/uptime/server/rest_api/network_events/get_network_events.ts b/x-pack/plugins/uptime/server/rest_api/network_events/get_network_events.ts index f24b319baff005..7a6355ea4247dd 100644 --- a/x-pack/plugins/uptime/server/rest_api/network_events/get_network_events.ts +++ b/x-pack/plugins/uptime/server/rest_api/network_events/get_network_events.ts @@ -26,8 +26,6 @@ export const createNetworkEventsRoute: UMRestApiRouteFactory = (libs: UMServerLi stepIndex, }); - return { - events: result, - }; + return result; }, });