Skip to content

Commit

Permalink
[Uptime] make index status api call unblocking (#97225) (#97630)
Browse files Browse the repository at this point in the history
Co-authored-by: Shahzad <shahzad.muhammad@elastic.co>
  • Loading branch information
kibanamachine and shahzad31 authored Apr 20, 2021
1 parent aeaec0c commit 3c406dc
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 2,130 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
*/

import React from 'react';
import { screen } from '@testing-library/react';
import { EmptyStateComponent } from './empty_state';
import { StatesIndexStatus } from '../../../../common/runtime_types';
import { HttpFetchError, IHttpFetchError } from 'src/core/public';
import { mountWithRouter, shallowWithRouter } from '../../../lib';
import { render } from '../../../lib/helper/rtl_helpers';

describe('EmptyState component', () => {
let statesIndexStatus: StatesIndexStatus;
Expand All @@ -22,23 +23,26 @@ describe('EmptyState component', () => {
});

it('renders child components when count is truthy', () => {
const component = shallowWithRouter(
render(
<EmptyStateComponent statesIndexStatus={statesIndexStatus} loading={false}>
<div>Foo</div>
<div>Bar</div>
<div>Baz</div>
</EmptyStateComponent>
);
expect(component).toMatchSnapshot();

expect(screen.getByText('Foo')).toBeInTheDocument();
expect(screen.getByText('Bar')).toBeInTheDocument();
expect(screen.getByText('Baz')).toBeInTheDocument();
});

it(`doesn't render child components when count is falsy`, () => {
const component = mountWithRouter(
render(
<EmptyStateComponent statesIndexStatus={null} loading={false}>
<div>Shouldn&apos;t be rendered</div>
<div>Should not be rendered</div>
</EmptyStateComponent>
);
expect(component).toMatchSnapshot();
expect(screen.queryByText('Should not be rendered')).toBeNull();
});

it(`renders error message when an error occurs`, () => {
Expand All @@ -47,43 +51,47 @@ describe('EmptyState component', () => {
body: { message: 'There was an error fetching your data.' },
}),
];
const component = mountWithRouter(
render(
<EmptyStateComponent statesIndexStatus={null} errors={errors} loading={false}>
<div>Shouldn&apos;t appear...</div>
<div>Should not appear...</div>
</EmptyStateComponent>
);
expect(component).toMatchSnapshot();
expect(screen.queryByText('Should not appear...')).toBeNull();
});

it('renders loading state if no errors or doc count', () => {
const component = mountWithRouter(
render(
<EmptyStateComponent loading={true} statesIndexStatus={null}>
<div>Should appear even while loading...</div>
</EmptyStateComponent>
);
expect(component).toMatchSnapshot();
expect(screen.queryByText('Should appear even while loading...')).toBeInTheDocument();
});

it('does not render empty state with appropriate base path and no docs', () => {
statesIndexStatus = {
docCount: 0,
indexExists: true,
};
const component = mountWithRouter(
const text = 'If this is in the snapshot the test should fail';
render(
<EmptyStateComponent statesIndexStatus={statesIndexStatus} loading={false}>
<div>If this is in the snapshot the test should fail</div>
<div>{text}</div>
</EmptyStateComponent>
);
expect(component).toMatchSnapshot();
expect(screen.queryByText(text)).toBeNull();
});

it('notifies when index does not exist', () => {
statesIndexStatus.indexExists = false;
const component = mountWithRouter(

const text = 'This text should not render';

render(
<EmptyStateComponent statesIndexStatus={statesIndexStatus} loading={false}>
<div>This text should not render</div>
<div>{text}</div>
</EmptyStateComponent>
);
expect(component).toMatchSnapshot();
expect(screen.queryByText(text)).toBeNull();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -33,36 +33,28 @@ export const EmptyStateComponent = ({
}
const { indexExists, docCount } = statesIndexStatus ?? {};

if (loading && (!indexExists || docCount === 0 || !statesIndexStatus)) {
return <EmptyStateLoading />;
}
const isLoading = loading && (!indexExists || docCount === 0 || !statesIndexStatus);

const noIndicesMessage = (
<FormattedMessage
id="xpack.uptime.emptyState.noIndexTitle"
defaultMessage="No indices found matching pattern {indexName}"
values={{ indexName: <em>{settings?.heartbeatIndices}</em> }}
/>
);

const noUptimeDataMessage = (
<FormattedMessage
id="xpack.uptime.emptyState.noDataMessage"
defaultMessage="No uptime data found in index {indexName}"
values={{ indexName: <em>{settings?.heartbeatIndices}</em> }}
/>
);

if (!indexExists) {
return (
<DataOrIndexMissing
settings={settings}
headingMessage={
<FormattedMessage
id="xpack.uptime.emptyState.noIndexTitle"
defaultMessage="No indices found matching pattern {indexName}"
values={{ indexName: <em>{settings?.heartbeatIndices}</em> }}
/>
}
/>
);
} else if (indexExists && docCount === 0) {
return (
<DataOrIndexMissing
settings={settings}
headingMessage={
<FormattedMessage
id="xpack.uptime.emptyState.noDataMessage"
defaultMessage="No uptime data found in index {indexName}"
values={{ indexName: <em>{settings?.heartbeatIndices}</em> }}
/>
}
/>
);
if (!indexExists && !isLoading) {
return <DataOrIndexMissing settings={settings} headingMessage={noIndicesMessage} />;
} else if (indexExists && docCount === 0 && !isLoading) {
return <DataOrIndexMissing settings={settings} headingMessage={noUptimeDataMessage} />;
}
/**
* We choose to render the children any time the count > 0, even if
Expand All @@ -71,6 +63,11 @@ export const EmptyStateComponent = ({
* jittery UX any time the components refresh. This way we'll keep the stale
* state displayed during the fetching process.
*/
return <Fragment>{children}</Fragment>;
return (
<Fragment>
{isLoading && <EmptyStateLoading />}
<div style={{ visibility: isLoading ? 'hidden' : 'initial' }}>{children}</div>
</Fragment>
);
// }
};
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,18 @@ export const EmptyState: React.FC = ({ children }) => {

const dispatch = useDispatch();

const noDataInfo = !data || data?.docCount === 0 || data?.indexExists === false;

useEffect(() => {
if (!data || data?.docCount === 0 || data?.indexExists === false) {
if (noDataInfo) {
// only call when we haven't fetched it already
dispatch(indexStatusAction.get());
}
// Don't add data , it will create endless loop
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dispatch, lastRefresh]);
}, [dispatch, lastRefresh, noDataInfo]);

useEffect(() => {
// using separate side effect, we want to call index status,
// every statue indices setting changes
dispatch(indexStatusAction.get());
}, [dispatch, heartbeatIndices]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { esKuerySelector, monitorListSelector } from '../../../state/selectors';
import { MonitorListComponent } from './monitor_list';
import { useUrlParams } from '../../../hooks';
import { UptimeRefreshContext } from '../../../contexts';
import { getConnectorsAction, getMonitorAlertsAction } from '../../../state/alerts/alerts';

export interface MonitorListProps {
filters?: string;
Expand Down Expand Up @@ -65,6 +66,14 @@ export const MonitorList: React.FC<MonitorListProps> = (props) => {
query,
]);

useEffect(() => {
dispatch(getMonitorAlertsAction.get());
}, [dispatch]);

useEffect(() => {
dispatch(getConnectorsAction.get());
}, [dispatch]);

return (
<MonitorListComponent
{...props}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ export const isValidKuery = (query: string) => {
};

export const QueryBar = () => {
const { index_pattern: indexPattern } = useIndexPattern();

const { search: urlValue } = useGetUrlParams();

const { query, setQuery } = useQueryBar();

const { index_pattern: indexPattern } = useIndexPattern(query.language ?? SyntaxType.text);

const [inputVal, setInputVal] = useState<string>(query.query);

const isInValid = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@ import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { getIndexPattern } from '../../../state/actions';
import { selectIndexPattern } from '../../../state/selectors';
import { SyntaxType } from './use_query_bar';

export const useIndexPattern = () => {
export const useIndexPattern = (queryLanguage?: string) => {
const dispatch = useDispatch();
const indexPattern = useSelector(selectIndexPattern);

useEffect(() => {
if (!indexPattern.index_pattern) {
// we only use index pattern for kql queries
if (!indexPattern.index_pattern && (!queryLanguage || queryLanguage === SyntaxType.kuery)) {
dispatch(getIndexPattern());
}
}, [indexPattern.index_pattern, dispatch]);
}, [indexPattern.index_pattern, dispatch, queryLanguage]);

return indexPattern;
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ export enum SyntaxType {
const SYNTAX_STORAGE = 'uptime:queryBarSyntax';

export const useQueryBar = () => {
const { index_pattern: indexPattern } = useIndexPattern();

const dispatch = useDispatch();

const { absoluteDateRangeStart, absoluteDateRangeEnd, ...params } = useGetUrlParams();
Expand All @@ -46,6 +44,8 @@ export const useQueryBar = () => {
}
);

const { index_pattern: indexPattern } = useIndexPattern(query.language);

const updateUrlParams = useUrlParams()[1];

const [esFilters, error] = useUpdateKueryString(
Expand Down
4 changes: 3 additions & 1 deletion x-pack/plugins/uptime/public/hooks/use_telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export const useUptimeTelemetry = (page?: UptimePage) => {
dateEnd: dateRangeEnd,
autoRefreshEnabled: !autorefreshIsPaused,
};
apiService.post(API_URLS.LOG_PAGE_VIEW, params);
setTimeout(() => {
apiService.post(API_URLS.LOG_PAGE_VIEW, params);
}, 100);
}, [autorefreshInterval, autorefreshIsPaused, dateRangeEnd, dateRangeStart, page]);
};
14 changes: 1 addition & 13 deletions x-pack/plugins/uptime/public/pages/overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,14 @@
*/

import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import React, { useEffect } from 'react';
import React from 'react';
import styled from 'styled-components';
import { useDispatch } from 'react-redux';

import { useBreadcrumbs } from '../hooks/use_breadcrumbs';
import { useTrackPageview } from '../../../observability/public';
import { MonitorList } from '../components/overview/monitor_list/monitor_list_container';
import { EmptyState, FilterGroup } from '../components/overview';
import { StatusPanel } from '../components/overview/status_panel';
import { getConnectorsAction, getMonitorAlertsAction } from '../state/alerts/alerts';
import { useInitApp } from '../hooks/use_init_app';
import { QueryBar } from '../components/overview/query_bar/query_bar';

const EuiFlexItemStyled = styled(EuiFlexItem)`
Expand All @@ -35,15 +32,6 @@ export const OverviewPageComponent = () => {
useTrackPageview({ app: 'uptime', path: 'overview' });
useTrackPageview({ app: 'uptime', path: 'overview', delay: 15000 });

useInitApp();

const dispatch = useDispatch();

useEffect(() => {
dispatch(getConnectorsAction.get());
dispatch(getMonitorAlertsAction.get());
}, [dispatch]);

useBreadcrumbs([]); // No extra breadcrumbs on overview

return (
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/uptime/public/state/effects/index_pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
* 2.0.
*/

import { takeLatest } from 'redux-saga/effects';
import { takeLeading } from 'redux-saga/effects';
import { getIndexPattern, getIndexPatternSuccess, getIndexPatternFail } from '../actions';
import { fetchIndexPattern } from '../api';
import { fetchEffectFactory } from './fetch_effect';

export function* fetchIndexPatternEffect() {
yield takeLatest(
yield takeLeading(
getIndexPattern,
fetchEffectFactory(fetchIndexPattern, getIndexPatternSuccess, getIndexPatternFail)
);
Expand Down

0 comments on commit 3c406dc

Please sign in to comment.