Skip to content

Commit

Permalink
[Synthetics] Improve dedupe client performance (#103979) (#107344)
Browse files Browse the repository at this point in the history
* Add new runtime types for parsing on client/server.

* Add more runtime types.

* Remove dead code.

* Mark parameter as unused.

* Improve typing for failed journey request function.

* Add new API functions, improve typing in a few others.

* Modify API calls to work with new screenshot_ref data.

* Fix untested refactor error.

* Add required fields to runtime type.

* Update typing in failed steps component.

* Adapt client to work with old screenshots as well as new screenshot_ref.

* Refactor composite code to reusable hook.

* Implement screenshot blocks endpoint.

* TEMP COMMIT.

* Add new runtime types for parsing on client/server.

* Add more runtime types.

* Remove dead code.

* Mark parameter as unused.

* Improve typing for failed journey request function.

* Add new API functions, improve typing in a few others.

* Modify API calls to work with new screenshot_ref data.

* Fix untested refactor error.

* Add required fields to runtime type.

* Update typing in failed steps component.

* Adapt client to work with old screenshots as well as new screenshot_ref.

* Refactor composite code to reusable hook.

* Implement screenshot blocks endpoint.

* Define runtime types for full-size screenshots.

* Delete dedicated screenshot and ref queries.

* Optimize screenshot endpoint by combining queries.

* Handle parsing error.

* Clean up screenshot/ref typings.

* Remove dead types. DRY a type out.

* Simplify types.

* Improve typing in step screenshot components.

* Prefer PNG to JPG for canvas composite op.

* Simplify and clean up some code.

* Remove reliance on `Ping` type, clean up types.

* Add a comment.

* Add a comment.

* Fix typing for `FailedStep` component.

* Standardize loading spinner sizes.

* Add comments to composite code.

* Remove unnecessary optional chaining.

* Reformat error string.

* Remove unneeded key from request return object.

* Add a comment to a return object explaining very large cache value.

* Make type annotation more accurate.

* Resolve some type and test errors.

* Clean up remaining type errors.

* Move type definitions to simplify imports.

* Simplify `PingTimestamp` interface.

* Refactor failing unit test to use RTL and actually test things.

* Add tests for new helper functions.

* Add a comment.

* Test `PingTimestamp` for screenshot ref data.

* Test `StepImageCaption` for ref data.

* Improve typing for step list column definitions.

* Harden a test.

* Extract code to avoid repeated declarations.

* Create centralized mock for `useCompositeImage`.

* Add test for ref to `StepScreenshotDisplay`.

* Add tests for `getJourneyDetails`.

* Extract search results wrapper to helper lib.

* Add tests for `getJourneyFailedSteps`.

* Add support for aggs to result helper wrapper.

* Write tests for `getJourneyScreenshot` and simplify type checking.

* Write tests for `getJourneyScreenshotBlocks`.

* Add new runtime types for parsing on client/server.

* Add more runtime types.

* Remove dead code.

* Mark parameter as unused.

* Improve typing for failed journey request function.

* Add new API functions, improve typing in a few others.

* Modify API calls to work with new screenshot_ref data.

* Fix untested refactor error.

* Add required fields to runtime type.

* Update typing in failed steps component.

* Adapt client to work with old screenshots as well as new screenshot_ref.

* Refactor composite code to reusable hook.

* Implement screenshot blocks endpoint.

* Define runtime types for full-size screenshots.

* Delete dedicated screenshot and ref queries.

* Optimize screenshot endpoint by combining queries.

* Handle parsing error.

* Clean up screenshot/ref typings.

* Remove dead types. DRY a type out.

* Simplify types.

* Improve typing in step screenshot components.

* Prefer PNG to JPG for canvas composite op.

* Simplify and clean up some code.

* Remove reliance on `Ping` type, clean up types.

* Add a comment.

* Add a comment.

* Fix typing for `FailedStep` component.

* Standardize loading spinner sizes.

* Add comments to composite code.

* Remove unnecessary optional chaining.

* Reformat error string.

* Remove unneeded key from request return object.

* Add a comment to a return object explaining very large cache value.

* Make type annotation more accurate.

* Resolve some type and test errors.

* Clean up remaining type errors.

* Move type definitions to simplify imports.

* Simplify `PingTimestamp` interface.

* Refactor failing unit test to use RTL and actually test things.

* Add tests for new helper functions.

* Add a comment.

* Test `PingTimestamp` for screenshot ref data.

* Test `StepImageCaption` for ref data.

* Improve typing for step list column definitions.

* Harden a test.

* Extract code to avoid repeated declarations.

* Create centralized mock for `useCompositeImage`.

* Add test for ref to `StepScreenshotDisplay`.

* Add tests for `getJourneyDetails`.

* Extract search results wrapper to helper lib.

* Add tests for `getJourneyFailedSteps`.

* Add support for aggs to result helper wrapper.

* Write tests for `getJourneyScreenshot` and simplify type checking.

* Write tests for `getJourneyScreenshotBlocks`.

* Simplify prop types for `FailedStep`.

* Remove unused type.

* Fix regression in step navigating for new style screenshots.

* Add type check function.

* Simplify and refactor merge issues.

* Add pruning effects for block cache.

* Handle pruning in redux store, write tests.

* Revert an unwanted change.

* Fix broken unit tests.

* Add throttle to reduce request volume.

* Resolve type issues.

* Add tests and fix a bug for journey screenshot route.

* Fix new test to provide expected values to tested route.

* Simplify blocks route.

* Add tests to blocks route.

* Remove unneeded function.

* Combine redundant selectors into single one.

* Add tests for composite image hook.

* Add a test for compose image.

* Fix bug found during code review.

* Remove double-bang assertions.

* Extract reducer logic to separate functions to improve readability.

* Remove `_source` clause from query.

* Fix issue where journey detail thumbnails would not update on page change.

* Fix #107308.

* Remove unneeded error skipping.

Co-authored-by: Kibana Machine <[email protected]>

Co-authored-by: Justin Kambic <[email protected]>
  • Loading branch information
kibanamachine and justinkambic authored Jul 31, 2021
1 parent 4bae1ff commit 983f484
Show file tree
Hide file tree
Showing 32 changed files with 1,431 additions and 149 deletions.
16 changes: 0 additions & 16 deletions x-pack/plugins/uptime/common/runtime_types/ping/synthetics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,22 +80,6 @@ describe('synthetics runtime types', () => {
maxSteps: 1,
ref: {
screenshotRef: refResult,
blocks: [
{
id: 'hash1',
synthetics: {
blob: 'image data',
blob_mime: 'image/jpeg',
},
},
{
id: 'hash2',
synthetics: {
blob: 'image data',
blob_mime: 'image/jpeg',
},
},
],
},
};
});
Expand Down
8 changes: 5 additions & 3 deletions x-pack/plugins/uptime/common/runtime_types/ping/synthetics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,9 @@ export const FullScreenshotType = t.type({
synthetics: t.intersection([
t.partial({
blob: t.string,
blob_mime: t.string,
}),
t.type({
blob: t.string,
blob_mime: t.string,
step: t.type({
name: t.string,
}),
Expand Down Expand Up @@ -158,6 +157,10 @@ export const ScreenshotBlockDocType = t.type({

export type ScreenshotBlockDoc = t.TypeOf<typeof ScreenshotBlockDocType>;

export function isScreenshotBlockDoc(data: unknown): data is ScreenshotBlockDoc {
return isRight(ScreenshotBlockDocType.decode(data));
}

/**
* Contains the fields requried by the Synthetics UI when utilizing screenshot refs.
*/
Expand All @@ -166,7 +169,6 @@ export const ScreenshotRefImageDataType = t.type({
maxSteps: t.number,
ref: t.type({
screenshotRef: RefResultType,
blocks: t.array(ScreenshotBlockDocType),
}),
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const PingTimestamp = ({ label, checkGroup, initialStepNo = 1 }: Props) =
const { data, status } = useFetcher(() => {
if (intersection && intersection.intersectionRatio === 1 && !stepImages[stepNumber - 1])
return getJourneyScreenshot(imgPath);
}, [intersection?.intersectionRatio, stepNumber]);
}, [intersection?.intersectionRatio, stepNumber, imgPath]);

const [screenshotRef, setScreenshotRef] = useState<ScreenshotRefImageData | undefined>(undefined);
useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const RecomposedScreenshotImage: React.FC<
}
> = ({ captionContent, imageCaption, imageData, imgRef, setImageData }) => {
// initially an undefined URL value is passed to the image display, and a loading spinner is rendered.
// `useCompositeImage` will call `setUrl` when the image is composited, and the updated `url` will display.
// `useCompositeImage` will call `setImageData` when the image is composited, and the updated `imageData` will display.
useCompositeImage(imgRef, setImageData, imageData);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export const StepDetailContainer: React.FC<Props> = ({ checkGroup, stepIndex })
{(!journey || journey.loading) && (
<EuiFlexGroup justifyContent="center">
<EuiFlexItem grow={false}>
<EuiLoadingSpinner size="xl" />
<EuiLoadingSpinner />
</EuiFlexItem>
</EuiFlexGroup>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ export const StepScreenshots = ({ step }: Props) => {
</Label>
<StepScreenshotDisplay
checkGroup={step.monitor.check_group}
isScreenshotRef={!!step.synthetics?.isScreenshotRef}
isScreenshotBlob={!!step.synthetics?.isFullScreenshot}
isScreenshotRef={Boolean(step.synthetics?.isScreenshotRef)}
isFullScreenshot={Boolean(step.synthetics?.isFullScreenshot)}
stepIndex={step.synthetics?.step?.index}
stepName={step.synthetics?.step?.name}
lazyLoad={false}
Expand All @@ -74,8 +74,8 @@ export const StepScreenshots = ({ step }: Props) => {
<ScreenshotLink lastSuccessfulStep={lastSuccessfulStep} />
<StepScreenshotDisplay
checkGroup={lastSuccessfulStep.monitor.check_group}
isScreenshotRef={!!lastSuccessfulStep.synthetics?.isScreenshotRef}
isScreenshotBlob={!!lastSuccessfulStep.synthetics?.isFullScreenshot}
isScreenshotRef={Boolean(lastSuccessfulStep.synthetics?.isScreenshotRef)}
isFullScreenshot={Boolean(lastSuccessfulStep.synthetics?.isFullScreenshot)}
stepIndex={lastSuccessfulStep.synthetics?.step?.index}
stepName={lastSuccessfulStep.synthetics?.step?.name}
lazyLoad={false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { fireEvent, screen } from '@testing-library/dom';
import { renderHook, act as hooksAct } from '@testing-library/react-hooks';
import { createMemoryHistory } from 'history';
import { EuiButtonIcon } from '@elastic/eui';
import { useExpandedRow } from './use_expanded_row';
import { getExpandedStepCallback, useExpandedRow } from './use_expanded_row';
import { render } from '../../../lib/helper/rtl_helpers';
import { JourneyStep } from '../../../../common/runtime_types';
import { SYNTHETIC_CHECK_STEPS_ROUTE } from '../../../../common/constants';
Expand Down Expand Up @@ -198,4 +198,12 @@ describe('useExpandedROw', () => {
// expect only one accordion to be expanded
expect(Object.keys(result.current.expandedRows)).toEqual(['0']);
});

describe('getExpandedStepCallback', () => {
it('matches step index to key', () => {
const callback = getExpandedStepCallback(2);
expect(callback(defaultSteps[0])).toBe(false);
expect(callback(defaultSteps[1])).toBe(true);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ interface HookProps {

type ExpandRowType = Record<string, JSX.Element>;

export function getExpandedStepCallback(key: number) {
return (step: JourneyStep) => step.synthetics?.step?.index === key;
}

export const useExpandedRow = ({ loading, steps, allSteps }: HookProps) => {
const [expandedRows, setExpandedRows] = useState<ExpandRowType>({});
// eui table uses index from 0, synthetics uses 1
Expand All @@ -37,21 +41,18 @@ export const useExpandedRow = ({ loading, steps, allSteps }: HookProps) => {

useEffect(() => {
const expandedRowsN: ExpandRowType = {};
for (const expandedRowKeyStr in expandedRows) {
if (expandedRows.hasOwnProperty(expandedRowKeyStr)) {
const expandedRowKey = Number(expandedRowKeyStr);
const step = steps.find((stepF) => stepF.synthetics?.step?.index !== expandedRowKey);
for (const expandedRowKey of Object.keys(expandedRows).map((key) => Number(key))) {
const step = steps.find(getExpandedStepCallback(expandedRowKey + 1));

if (step) {
expandedRowsN[expandedRowKey] = (
<ExecutedStep
step={step}
browserConsole={getBrowserConsole(expandedRowKey)}
index={step.synthetics?.step?.index!}
loading={loading}
/>
);
}
if (step) {
expandedRowsN[expandedRowKey] = (
<ExecutedStep
step={step}
browserConsole={getBrowserConsole(expandedRowKey)}
index={step.synthetics?.step?.index!}
loading={loading}
/>
);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const ExecutedStep: FC<ExecutedStepProps> = ({
return (
<ExpandedRow>
{loading ? (
<EuiLoadingSpinner size="l" />
<EuiLoadingSpinner />
) : (
<>
<EuiSpacer size="s" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe('StepScreenshotDisplayProps', () => {
const { getByAltText } = render(
<StepScreenshotDisplay
checkGroup="check_group"
isScreenshotBlob={true}
isFullScreenshot={true}
isScreenshotRef={false}
stepIndex={1}
stepName="STEP_NAME"
Expand All @@ -44,7 +44,7 @@ describe('StepScreenshotDisplayProps', () => {
const { getByAltText } = render(
<StepScreenshotDisplay
checkGroup="check_group"
isScreenshotBlob={true}
isFullScreenshot={true}
isScreenshotRef={false}
stepIndex={1}
/>
Expand All @@ -57,7 +57,7 @@ describe('StepScreenshotDisplayProps', () => {
const { getByTestId } = render(
<StepScreenshotDisplay
checkGroup="check_group"
isScreenshotBlob={false}
isFullScreenshot={false}
isScreenshotRef={false}
stepIndex={1}
stepName="STEP_NAME"
Expand All @@ -76,7 +76,7 @@ describe('StepScreenshotDisplayProps', () => {
const { getByAltText } = render(
<StepScreenshotDisplay
checkGroup="check_group"
isScreenshotBlob={false}
isFullScreenshot={false}
isScreenshotRef={true}
stepIndex={1}
stepName="STEP_NAME"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { getJourneyScreenshot } from '../../state/api/journey';
import { useCompositeImage } from '../../hooks';

interface StepScreenshotDisplayProps {
isScreenshotBlob: boolean;
isFullScreenshot: boolean;
isScreenshotRef: boolean;
checkGroup?: string;
stepIndex?: number;
Expand Down Expand Up @@ -96,7 +96,7 @@ const ComposedStepImage = ({

export const StepScreenshotDisplay: FC<StepScreenshotDisplayProps> = ({
checkGroup,
isScreenshotBlob: isScreenshotBlob,
isFullScreenshot: isScreenshotBlob,
isScreenshotRef,
stepIndex,
stepName,
Expand Down Expand Up @@ -134,7 +134,7 @@ export const StepScreenshotDisplay: FC<StepScreenshotDisplayProps> = ({
if (isScreenshotRef) {
return getJourneyScreenshot(imgSrc);
}
}, [basePath, checkGroup, stepIndex, isScreenshotRef]);
}, [basePath, checkGroup, imgSrc, stepIndex, isScreenshotRef]);

const refDimensions = useMemo(() => {
if (isAScreenshotRef(screenshotRef)) {
Expand Down
Loading

0 comments on commit 983f484

Please sign in to comment.