Skip to content

Commit

Permalink
[Uptime] Synthetics UI (#77960)
Browse files Browse the repository at this point in the history
* Checkpoint

* Various

* Display synthetics steps.

* Add loading state for snapshots. Add error and stack trace fields.

* Lazy load screenshot images and cache screenshot GET endpoint.

* Fix extra requests bug.

* Improve screenshot empty state.

* Switch to use of code block for stack and error.

* Add onmouseenter and onmouseleave for image input/popover.

* Add image overlay.

* Support `skipped` state.

* Add synthetics type for Ping.

* Fix type references in reducer, api request, components.

* Add required mapping logic to journey request function.

* Modularize new components.

* Delete obsolete code.

* Delete unused code.

* Test expanded row changes.

* Add a test for ping list expand check.

* Various fixes

* Extract code accordion to new component

* Subsume synthetics type into Ping type.

* Add new journey viz for 0 steps case.

* Use code block for console output.

* Expand step count cap.

* Improve formatting of console steps visualization.

* Improve empty prompt.

* Extract empty prompt to dedicated file.

* Extract executed journey UI to dedicated file.

* Extract console step list components to dedicated files.

* Update empty journey prompt to accept only check_group.

* Clean up script expanded row component.

* Translate console output steps component.

* Fix logic error.

* Clean up console step component.

* Translate empty journey component.

* Translate status badge component.

* Translate screenshot component.

* Add experimental warning callout.

* Re-introduce deleted code.

* Simplify console output step list.

* Support skipped step for executed journeys.

* Simplify executed journey component.

* Add translations for executed step.

* Refresh outdated test snapshots.

* Simplify journey reducer signature.

* Repair types.

* Fix broken i18n naming.

* Add summary field to outdated ping test data.

* Fix linting error.

* Remove @ts-ignore comment.

* Add tests for step screenshot display.

* Add tests for status badge.

* Rename test file.

* Add tests for script expanded row.

* Add tests for executed step.

* Delete request and response fields from Ping's `synthetics` field.

* Fix screenshot querying effect, add flag to journey step state.

* Update screenshot api route to reply 404 when screenshot is null.

* Simplify screenshot image fetching.

* Delete obsolete code.

* Rename BrowserExpandedRow component.

* Remove all references to "suitejourney".

* Add intentional var names.

* Rename Console components to use "event" terminology instead of "step".

* Employ better copy.

* First names always bad names.

* Rename CodeBlockAccordion component.

* Add blob_mime field to Ping type.

* Fix busted import path.

* Update ping type for new position of errors field.

* Repair broken types.

* Fix summary querying

* Type fixes.

* Switch state object from list to KVP.

* Checkpoint.

* Fix screenshot display test.

* Fix executed step test.

* Refresh outdated test snapshots.

* Repair broken types.

* More typing fixes.

* Fix console log and add a test.

Co-authored-by: Andrew Cholakian <[email protected]>
Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
3 people authored Oct 2, 2020
1 parent 43cf97e commit 0ce8025
Show file tree
Hide file tree
Showing 40 changed files with 1,890 additions and 58 deletions.
49 changes: 49 additions & 0 deletions x-pack/plugins/uptime/common/runtime_types/ping/ping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,48 @@ export const PingType = t.intersection([
down: t.number,
up: t.number,
}),
synthetics: t.partial({
index: t.number,
journey: t.type({
id: t.string,
name: t.string,
}),
error: t.partial({
message: t.string,
name: t.string,
stack: t.string,
}),
package_version: t.string,
step: t.type({
index: t.number,
name: t.string,
}),
type: t.string,
// ui-related field
screenshotLoading: t.boolean,
// ui-related field
screenshotExists: t.boolean,
blob: t.string,
blob_mime: t.string,
payload: t.partial({
duration: t.number,
index: t.number,
is_navigation_request: t.boolean,
message: t.string,
method: t.string,
name: t.string,
params: t.partial({
homepage: t.string,
}),
source: t.string,
start: t.number,
status: t.string,
ts: t.number,
type: t.string,
url: t.string,
end: t.number,
}),
}),
tags: t.array(t.string),
tcp: t.partial({
rtt: t.partial({
Expand All @@ -202,6 +244,13 @@ export const PingType = t.intersection([
}),
]);

export const SyntheticsJourneyApiResponseType = t.type({
checkGroup: t.string,
steps: t.array(PingType),
});

export type SyntheticsJourneyApiResponse = t.TypeOf<typeof SyntheticsJourneyApiResponseType>;

export type Ping = t.TypeOf<typeof PingType>;

// Convenience function for tests etc that makes an empty ping
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/uptime/public/apps/uptime_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export interface UptimeAppColors {
range: string;
mean: string;
warning: string;
lightestShade: string;
}

export interface UptimeAppProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ describe('PingListExpandedRow', () => {
docId: 'fdeio12',
timestamp: '19290310',
monitor: {
check_group: 'check_group_id',
duration: {
us: 12345,
},
Expand Down Expand Up @@ -87,4 +88,25 @@ describe('PingListExpandedRow', () => {

expect(docLinkComponent).toHaveLength(1);
});

it('renders a synthetics expanded row for synth monitor', () => {
ping.monitor.type = 'browser';
expect(shallowWithIntl(<PingListExpandedRowComponent ping={ping} />)).toMatchInlineSnapshot(`
<EuiFlexGroup
direction="column"
>
<EuiFlexItem>
<EuiCallOut
iconType="beaker"
title="Experimental feature"
/>
</EuiFlexItem>
<EuiFlexItem>
<BrowserExpandedRow
checkGroup="check_group_id"
/>
</EuiFlexItem>
</EuiFlexGroup>
`);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import React from 'react';
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import { PingListComponent, toggleDetails } from '../ping_list';
import { PingListComponent, rowShouldExpand, toggleDetails } from '../ping_list';
import { Ping, PingsResponse } from '../../../../../common/runtime_types';
import { ExpandedRowMap } from '../../../overview/monitor_list/types';

Expand Down Expand Up @@ -182,6 +182,7 @@ describe('PingList component', () => {
to: 'now',
}}
getPings={jest.fn()}
pruneJourneysCallback={jest.fn()}
lastRefresh={123}
loading={false}
locations={[]}
Expand Down Expand Up @@ -273,5 +274,14 @@ describe('PingList component', () => {
/>
`);
});

describe('rowShouldExpand', () => {
// TODO: expand for all cases
it('returns true for browser monitors', () => {
const ping = pings[0];
ping.monitor.type = 'browser';
expect(rowShouldExpand(ping)).toBe(true);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

// @ts-ignore formatNumber
import { formatNumber } from '@elastic/eui/lib/services/format';
import {
Expand All @@ -19,6 +20,7 @@ import { i18n } from '@kbn/i18n';
import { Ping, HttpResponseBody } from '../../../../common/runtime_types';
import { DocLinkForBody } from './doc_link_body';
import { PingRedirects } from './ping_redirects';
import { BrowserExpandedRow } from '../synthetics/browser_expanded_row';

interface Props {
ping: Ping;
Expand Down Expand Up @@ -53,6 +55,24 @@ const BodyExcerpt = ({ content }: { content: string }) =>
export const PingListExpandedRowComponent = ({ ping }: Props) => {
const listItems = [];

if (ping.monitor.type === 'browser') {
return (
<EuiFlexGroup direction="column">
<EuiFlexItem>
<EuiCallOut
iconType="beaker"
title={i18n.translate('xpack.uptime.synthetics.experimentalCallout.title', {
defaultMessage: 'Experimental feature',
})}
/>
</EuiFlexItem>
<EuiFlexItem>
<BrowserExpandedRow checkGroup={ping.monitor.check_group} />
</EuiFlexItem>
</EuiFlexGroup>
);
}

// Show the error block
if (ping.error) {
listItems.push({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
*/

export { PingListComponent } from './ping_list';
export { PingList } from './ping_list_container';
export { PingList } from './ping_list';
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,63 @@ import {
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import moment from 'moment';
import React, { useState, useEffect } from 'react';
import React, { useCallback, useContext, useState, useEffect } from 'react';
import styled from 'styled-components';
import { useDispatch, useSelector } from 'react-redux';
import { Ping, GetPingsParams, DateRange } from '../../../../common/runtime_types';
import { convertMicrosecondsToMilliseconds as microsToMillis } from '../../../lib/helper';
import { LocationName } from './location_name';
import { Pagination } from '../../overview/monitor_list';
import { PingListExpandedRowComponent } from './expanded_row';
import { PingListProps } from './ping_list_container';
// import { PingListProps } from './ping_list_container';
import { pruneJourneyState } from '../../../state/actions/journey';
import { selectPingList } from '../../../state/selectors';
import { UptimeRefreshContext, UptimeSettingsContext } from '../../../contexts';
import { getPings as getPingsAction } from '../../../state/actions';

export interface PingListProps {
monitorId: string;
}

export const PingList = (props: PingListProps) => {
const {
error,
loading,
pingList: { locations, pings, total },
} = useSelector(selectPingList);

const { lastRefresh } = useContext(UptimeRefreshContext);

const { dateRangeStart: drs, dateRangeEnd: dre } = useContext(UptimeSettingsContext);

const dispatch = useDispatch();
const getPingsCallback = useCallback(
(params: GetPingsParams) => dispatch(getPingsAction(params)),
[dispatch]
);
const pruneJourneysCallback = useCallback(
(checkGroups: string[]) => dispatch(pruneJourneyState(checkGroups)),
[dispatch]
);

return (
<PingListComponent
dateRange={{
from: drs,
to: dre,
}}
error={error}
getPings={getPingsCallback}
pruneJourneysCallback={pruneJourneysCallback}
lastRefresh={lastRefresh}
loading={loading}
locations={locations}
pings={pings}
total={total}
{...props}
/>
);
};

export const AllLocationOption = {
'data-test-subj': 'xpack.uptime.pingList.locationOptions.all',
Expand Down Expand Up @@ -63,6 +112,7 @@ interface Props extends PingListProps {
dateRange: DateRange;
error?: Error;
getPings: (props: GetPingsParams) => void;
pruneJourneysCallback: (checkGroups: string[]) => void;
lastRefresh: number;
loading: boolean;
locations: string[];
Expand Down Expand Up @@ -96,6 +146,13 @@ const statusOptions = [
},
];

export function rowShouldExpand(item: Ping) {
const errorPresent = !!item.error;
const httpBodyPresent = item.http?.response?.body?.bytes ?? 0 > 0;
const isBrowserMonitor = item.monitor.type === 'browser';
return errorPresent || httpBodyPresent || isBrowserMonitor;
}

export const PingListComponent = (props: Props) => {
const [selectedLocation, setSelectedLocation] = useState<string>('');
const [status, setStatus] = useState<string>('');
Expand All @@ -105,6 +162,7 @@ export const PingListComponent = (props: Props) => {
dateRange: { from, to },
error,
getPings,
pruneJourneysCallback,
lastRefresh,
loading,
locations,
Expand All @@ -129,6 +187,27 @@ export const PingListComponent = (props: Props) => {

const [expandedRows, setExpandedRows] = useState<Record<string, JSX.Element>>({});

const expandedIdsToRemove = JSON.stringify(
Object.keys(expandedRows).filter((e) => !pings.some(({ docId }) => docId === e))
);
useEffect(() => {
const parsed = JSON.parse(expandedIdsToRemove);
if (parsed.length) {
parsed.forEach((docId: string) => {
delete expandedRows[docId];
});
setExpandedRows(expandedRows);
}
}, [expandedIdsToRemove, expandedRows]);

const expandedCheckGroups = pings
.filter((p: Ping) => Object.keys(expandedRows).some((f) => p.docId === f))
.map(({ monitor: { check_group: cg } }) => cg);
const expandedCheckGroupsStr = JSON.stringify(expandedCheckGroups);
useEffect(() => {
pruneJourneysCallback(JSON.parse(expandedCheckGroupsStr));
}, [pruneJourneysCallback, expandedCheckGroupsStr]);

const locationOptions = !locations
? [AllLocationOption]
: [AllLocationOption].concat(
Expand Down Expand Up @@ -239,7 +318,7 @@ export const PingListComponent = (props: Props) => {
<EuiButtonIcon
data-test-subj="uptimePingListExpandBtn"
onClick={() => toggleDetails(item, expandedRows, setExpandedRows)}
disabled={!item.error && !(item.http?.response?.body?.bytes ?? 0 > 0)}
disabled={!rowShouldExpand(item)}
aria-label={
expandedRows[item.docId]
? i18n.translate('xpack.uptime.pingList.collapseRow', {
Expand Down

This file was deleted.

Loading

0 comments on commit 0ce8025

Please sign in to comment.