Skip to content

Commit

Permalink
[Infrastructure UI] Plot metric charts data based on current page ite…
Browse files Browse the repository at this point in the history
…ms (#155249)

closes [#152186](#152186)

## Summary

This PR makes the metric charts show data for the hosts on the current
page. With this change, the charts will **only** load after the table
has finished loading its data - or after Snapshot API has responded

It also changes the current behavior of the table pagination and
sorting. Instead of relying on the `EuiInMemoryTable` the pagination and
sorting are done manually, and the EuiInMemoryTable has been replaced by
the `EuiBasicTable`.

The loading indicator has also been replaced.

Paginating and sorting:


https://user-images.githubusercontent.com/2767137/233161166-2bd719e1-7259-4ecc-96a7-50493bc6c0a3.mov

Open in lens 


https://user-images.githubusercontent.com/2767137/233161134-621afd76-44b5-42ab-b58c-7f51ef944ac2.mov


### How to test
- Go to Hosts view
- Paginate and sort the table data
- Select a page size and check if the select has been stored in the
localStorage (`hostsView:pageSizeSelection` key)

---------

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
crespocarlos and kibanamachine authored Apr 24, 2023
1 parent 069324a commit 54457b0
Show file tree
Hide file tree
Showing 20 changed files with 716 additions and 410 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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 React from 'react';
import { EuiFlexGroup, EuiProgress, EuiFlexItem, EuiLoadingChart, useEuiTheme } from '@elastic/eui';
import { css } from '@emotion/react';
import { euiStyled } from '@kbn/kibana-react-plugin/common';

export const ChartLoader = ({
children,
loading,
style,
loadedOnce = false,
hasTitle = false,
}: {
style?: React.CSSProperties;
children: React.ReactNode;
loadedOnce: boolean;
loading: boolean;
hasTitle?: boolean;
}) => {
const { euiTheme } = useEuiTheme();
return (
<LoaderContainer>
{loading && (
<EuiProgress
size="xs"
color="accent"
position="absolute"
css={css`
top: ${loadedOnce && hasTitle ? euiTheme.size.l : 0};
`}
style={{ zIndex: Number(euiTheme.levels.header) - 1 }}
/>
)}
{loading && !loadedOnce ? (
<EuiFlexGroup style={style} justifyContent="center" alignItems="center">
<EuiFlexItem grow={false}>
<EuiLoadingChart mono size="l" />
</EuiFlexItem>
</EuiFlexGroup>
) : (
children
)}
</LoaderContainer>
);
};

const LoaderContainer = euiStyled.div`
position: relative;
border-radius: ${({ theme }) => theme.eui.euiSizeS};
overflow: hidden;
height: 100%;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,16 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useRef } from 'react';

import { Action } from '@kbn/ui-actions-plugin/public';
import { ViewMode } from '@kbn/embeddable-plugin/public';
import { BrushTriggerEvent } from '@kbn/charts-plugin/public';
import { EuiFlexGroup } from '@elastic/eui';
import { EuiFlexItem } from '@elastic/eui';
import { EuiLoadingChart } from '@elastic/eui';
import { Filter, Query, TimeRange } from '@kbn/es-query';
import { useKibanaContextForPlugin } from '../../../../../hooks/use_kibana';
import { useIntersectedOnce } from '../../../../../hooks/use_intersection_once';
import { LensAttributes } from '../../../../../common/visualizations';
import { ChartLoader } from './chart_loader';

export interface Props {
id: string;
Expand All @@ -26,7 +24,10 @@ export interface Props {
extraActions: Action[];
lastReloadRequestTime?: number;
style?: React.CSSProperties;
loading?: boolean;
hasTitle?: boolean;
onBrushEnd?: (data: BrushTriggerEvent['data']) => void;
onLoad?: () => void;
}

export const LensWrapper = ({
Expand All @@ -39,12 +40,19 @@ export const LensWrapper = ({
style,
onBrushEnd,
lastReloadRequestTime,
loading = false,
hasTitle = false,
}: Props) => {
const intersectionRef = React.useRef(null);
const intersectionRef = useRef(null);
const [loadedOnce, setLoadedOnce] = useState(false);

const [state, setState] = useState({
lastReloadRequestTime,
query,
filters,
dateRange,
});

const [currentLastReloadRequestTime, setCurrentLastReloadRequestTime] = useState<
number | undefined
>(lastReloadRequestTime);
const {
services: { lens },
} = useKibanaContextForPlugin();
Expand All @@ -56,38 +64,49 @@ export const LensWrapper = ({

useEffect(() => {
if ((intersection?.intersectionRatio ?? 0) === 1) {
setCurrentLastReloadRequestTime(lastReloadRequestTime);
setState({
lastReloadRequestTime,
query,
dateRange,
filters,
});
}
}, [intersection?.intersectionRatio, lastReloadRequestTime]);
}, [dateRange, filters, intersection?.intersectionRatio, lastReloadRequestTime, query]);

const isReady = attributes && intersectedOnce;

return (
<div ref={intersectionRef}>
{!isReady ? (
<EuiFlexGroup style={style} justifyContent="center" alignItems="center">
<EuiFlexItem grow={false}>
<EuiLoadingChart size="l" mono />
</EuiFlexItem>
</EuiFlexGroup>
) : (
<EmbeddableComponent
id={id}
style={style}
attributes={attributes}
viewMode={ViewMode.VIEW}
timeRange={dateRange}
query={query}
filters={filters}
extraActions={extraActions}
lastReloadRequestTime={currentLastReloadRequestTime}
executionContext={{
type: 'infrastructure_observability_hosts_view',
name: id,
}}
onBrushEnd={onBrushEnd}
/>
)}
<ChartLoader
loading={loading || !isReady}
loadedOnce={loadedOnce}
style={style}
hasTitle={hasTitle}
>
{isReady && (
<EmbeddableComponent
id={id}
style={style}
attributes={attributes}
viewMode={ViewMode.VIEW}
timeRange={state.dateRange}
query={state.query}
filters={state.filters}
extraActions={extraActions}
lastReloadRequestTime={state.lastReloadRequestTime}
executionContext={{
type: 'infrastructure_observability_hosts_view',
name: id,
}}
onBrushEnd={onBrushEnd}
onLoad={() => {
if (!loadedOnce) {
setLoadedOnce(true);
}
}}
/>
)}
</ChartLoader>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,11 @@ import {
} from '@elastic/charts';
import { EuiPanel } from '@elastic/eui';
import styled from 'styled-components';
import { EuiLoadingChart } from '@elastic/eui';
import { EuiFlexGroup } from '@elastic/eui';
import { EuiFlexItem } from '@elastic/eui';
import { EuiToolTip } from '@elastic/eui';
import { EuiProgress } from '@elastic/eui';
import { css } from '@emotion/react';
import { useEuiTheme } from '@elastic/eui';
import type { SnapshotNode, SnapshotNodeMetric } from '../../../../../../common/http_api';
import { createInventoryMetricFormatter } from '../../../inventory_view/lib/create_inventory_metric_formatter';
import type { SnapshotMetricType } from '../../../../../../common/inventory_models/types';
import { ChartLoader } from './chart_loader';

type MetricType = keyof Pick<SnapshotNodeMetric, 'avg' | 'max' | 'value'>;

Expand Down Expand Up @@ -65,7 +60,6 @@ export const MetricChartWrapper = ({
type,
...props
}: Props) => {
const { euiTheme } = useEuiTheme();
const loadedOnce = useRef(false);
const metrics = useMemo(() => (nodes ?? [])[0]?.metrics ?? [], [nodes]);
const metricsTimeseries = useMemo(
Expand Down Expand Up @@ -109,39 +103,18 @@ export const MetricChartWrapper = ({

return (
<EuiPanel hasShadow={false} paddingSize="none" {...props}>
<div
css={css`
position: relative;
border-radius: ${euiTheme.size.s};
overflow: hidden;
`}
>
{loading && (
<EuiProgress size="xs" color="accent" position="absolute" style={{ zIndex: 1 }} />
)}
{loading && !loadedOnce.current ? (
<EuiFlexGroup
style={{ minHeight: MIN_HEIGHT }}
justifyContent="center"
alignItems="center"
>
<EuiFlexItem grow={false}>
<EuiLoadingChart size="l" mono />
</EuiFlexItem>
</EuiFlexGroup>
) : (
<EuiToolTip
className="eui-fullWidth"
delay="regular"
content={toolTip}
anchorClassName="eui-fullWidth"
>
<KPIChartStyled size={{ height: MIN_HEIGHT }}>
<Metric id={id} data={[[metricsData]]} />
</KPIChartStyled>
</EuiToolTip>
)}
</div>
<ChartLoader loading={loading} loadedOnce={loadedOnce.current} style={{ height: MIN_HEIGHT }}>
<EuiToolTip
className="eui-fullWidth"
delay="regular"
content={toolTip}
anchorClassName="eui-fullWidth"
>
<KPIChartStyled size={{ height: MIN_HEIGHT }}>
<Metric id={id} data={[[metricsData]]} />
</KPIChartStyled>
</EuiToolTip>
</ChartLoader>
</EuiPanel>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,42 +32,12 @@ const metadataProps: TabProps = {
name: 'host-1',
cloudProvider: 'gcp',
},
rx: {
name: 'rx',
value: 0,
max: 0,
avg: 0,
},
tx: {
name: 'tx',
value: 0,
max: 0,
avg: 0,
},
memory: {
name: 'memory',
value: 0.5445920331099282,
max: 0.5445920331099282,
avg: 0.5445920331099282,
},
cpu: {
name: 'cpu',
value: 0.2000718443867342,
max: 0.2000718443867342,
avg: 0.2000718443867342,
},
diskLatency: {
name: 'diskLatency',
value: null,
max: 0,
avg: 0,
},
memoryTotal: {
name: 'memoryTotal',
value: 16777216,
max: 16777216,
avg: 16777216,
},
rx: 0,
tx: 0,
memory: 0.5445920331099282,
cpu: 0.2000718443867342,
diskLatency: 0,
memoryTotal: 16777216,
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ import { InfraLoadingPanel } from '../../../../components/loading';
import { useMetricsDataViewContext } from '../hooks/use_data_view';
import { UnifiedSearchBar } from './unified_search_bar';
import { HostsTable } from './hosts_table';
import { HostsViewProvider } from '../hooks/use_hosts_view';
import { KPIGrid } from './kpis/kpi_grid';
import { Tabs } from './tabs/tabs';
import { AlertsQueryProvider } from '../hooks/use_alerts_query';
import { KPIGrid } from './kpis/kpi_grid';
import { HostsViewProvider } from '../hooks/use_hosts_view';
import { HostsTableProvider } from '../hooks/use_hosts_table';

export const HostContainer = () => {
const { dataView, loading, hasError } = useMetricsDataViewContext();
Expand All @@ -38,19 +39,21 @@ export const HostContainer = () => {
<UnifiedSearchBar />
<EuiSpacer />
<HostsViewProvider>
<EuiFlexGroup direction="column">
<EuiFlexItem grow={false}>
<KPIGrid />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<HostsTable />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<AlertsQueryProvider>
<Tabs />
</AlertsQueryProvider>
</EuiFlexItem>
</EuiFlexGroup>
<HostsTableProvider>
<EuiFlexGroup direction="column">
<EuiFlexItem grow={false}>
<KPIGrid />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<HostsTable />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<AlertsQueryProvider>
<Tabs />
</AlertsQueryProvider>
</EuiFlexItem>
</EuiFlexGroup>
</HostsTableProvider>
</HostsViewProvider>
</>
);
Expand Down
Loading

0 comments on commit 54457b0

Please sign in to comment.