From 64c250f46b951c5197c8782e1386aa23fb634088 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Wed, 23 Oct 2019 17:12:19 -0700 Subject: [PATCH 1/9] Convert layouts to use React compontents - This PR closes #48808 - Move all files under pages/metrics --- .../inventory_models/container/index.ts | 8 + .../inventory_models/container/layout.v2.tsx | 222 +++++++++++ .../inventory_models/host/detail_page.tsx | 142 +++++++ .../common/inventory_models/host/index.ts | 18 + .../inventory_models/host/layout.v2.tsx | 352 ++++++++++++++++++ .../infra/common/inventory_models/index.ts | 2 +- .../infra/common/inventory_models/layouts.ts | 44 +++ .../common/inventory_models/pod/index.ts | 9 + .../common/inventory_models/pod/layout.v2.tsx | 154 ++++++++ .../shared/layouts/aws.v2.tsx | 237 ++++++++++++ .../shared/layouts/nginx.v2.tsx | 103 +++++ .../shared/metrics/required_metrics.ts | 21 ++ .../infra/common/inventory_models/types.ts | 2 + .../infra/public/components/metrics/index.tsx | 128 ------- .../public/components/metrics/section.tsx | 42 --- .../metrics/sections/gauges_section.tsx | 104 ------ .../components/metrics/sections/index.ts | 13 - .../public/components/metrics/side_nav.tsx | 81 ---- .../metadata/lib/get_filtered_metrics.ts | 25 ++ .../containers/metadata/use_metadata.ts | 6 +- .../redirect_to_host_detail_via_ip.tsx | 2 +- .../pages/link_to/redirect_to_node_detail.tsx | 2 +- .../metrics/components/chart_section_vis.tsx} | 51 +-- .../metrics/components}/error_message.tsx | 0 .../metrics/components/gauges_section_vis.tsx | 101 +++++ .../metrics/components/helpers.ts} | 50 ++- .../metrics/components}/invalid_node.tsx | 6 +- .../metrics/components}/node_details.tsx | 4 +- .../pages/metrics/components/page_body.tsx | 72 ++++ .../pages/metrics/components/page_error.tsx | 45 +++ .../pages/metrics/components/section.tsx | 67 ++++ .../metrics/components}/series_chart.tsx | 0 .../pages/metrics/components/side_nav.tsx | 52 +++ .../pages/metrics/components/sub_section.tsx | 55 +++ .../components}/time_controls.test.tsx | 2 +- .../metrics/components}/time_controls.tsx | 4 +- .../metrics/containers}/metrics.gql_query.ts | 0 .../metrics/containers}/metrics_time.test.tsx | 0 .../metrics/containers}/with_metrics.tsx | 21 +- .../metrics/containers}/with_metrics_time.tsx | 4 +- .../infra/public/pages/metrics/index.tsx | 120 +++--- .../pages/metrics/lib/side_nav_context.ts | 24 ++ .../public/pages/metrics/page_providers.tsx | 2 +- .../infra/public/pages/metrics/types.ts | 62 +++ .../infra/public/utils/formatters/index.ts | 17 +- 45 files changed, 1947 insertions(+), 529 deletions(-) create mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/container/layout.v2.tsx create mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/host/detail_page.tsx create mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/host/layout.v2.tsx create mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts create mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/pod/layout.v2.tsx create mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/aws.v2.tsx create mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/nginx.v2.tsx create mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/required_metrics.ts delete mode 100644 x-pack/legacy/plugins/infra/public/components/metrics/index.tsx delete mode 100644 x-pack/legacy/plugins/infra/public/components/metrics/section.tsx delete mode 100644 x-pack/legacy/plugins/infra/public/components/metrics/sections/gauges_section.tsx delete mode 100644 x-pack/legacy/plugins/infra/public/components/metrics/sections/index.ts delete mode 100644 x-pack/legacy/plugins/infra/public/components/metrics/side_nav.tsx create mode 100644 x-pack/legacy/plugins/infra/public/containers/metadata/lib/get_filtered_metrics.ts rename x-pack/legacy/plugins/infra/public/{components/metrics/sections/chart_section.tsx => pages/metrics/components/chart_section_vis.tsx} (72%) rename x-pack/legacy/plugins/infra/public/{components/metrics/sections => pages/metrics/components}/error_message.tsx (100%) create mode 100644 x-pack/legacy/plugins/infra/public/pages/metrics/components/gauges_section_vis.tsx rename x-pack/legacy/plugins/infra/public/{components/metrics/sections/helpers/index.ts => pages/metrics/components/helpers.ts} (58%) rename x-pack/legacy/plugins/infra/public/{components/metrics => pages/metrics/components}/invalid_node.tsx (92%) rename x-pack/legacy/plugins/infra/public/{components/metrics => pages/metrics/components}/node_details.tsx (97%) create mode 100644 x-pack/legacy/plugins/infra/public/pages/metrics/components/page_body.tsx create mode 100644 x-pack/legacy/plugins/infra/public/pages/metrics/components/page_error.tsx create mode 100644 x-pack/legacy/plugins/infra/public/pages/metrics/components/section.tsx rename x-pack/legacy/plugins/infra/public/{components/metrics/sections => pages/metrics/components}/series_chart.tsx (100%) create mode 100644 x-pack/legacy/plugins/infra/public/pages/metrics/components/side_nav.tsx create mode 100644 x-pack/legacy/plugins/infra/public/pages/metrics/components/sub_section.tsx rename x-pack/legacy/plugins/infra/public/{components/metrics => pages/metrics/components}/time_controls.test.tsx (95%) rename x-pack/legacy/plugins/infra/public/{components/metrics => pages/metrics/components}/time_controls.tsx (92%) rename x-pack/legacy/plugins/infra/public/{containers/metrics => pages/metrics/containers}/metrics.gql_query.ts (100%) rename x-pack/legacy/plugins/infra/public/{containers/metrics => pages/metrics/containers}/metrics_time.test.tsx (100%) rename x-pack/legacy/plugins/infra/public/{containers/metrics => pages/metrics/containers}/with_metrics.tsx (82%) rename x-pack/legacy/plugins/infra/public/{containers/metrics => pages/metrics/containers}/with_metrics_time.tsx (98%) create mode 100644 x-pack/legacy/plugins/infra/public/pages/metrics/lib/side_nav_context.ts create mode 100644 x-pack/legacy/plugins/infra/public/pages/metrics/types.ts diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts index 254ed7b759300..63d13696cf041 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts @@ -13,4 +13,12 @@ export const container: InventoryModel = { requiredModules: ['docker'], layout, metrics, + requiredMetrics: [ + 'containerOverview', + 'containerCpuUsage', + 'containerMemory', + 'containerNetworkTraffic', + 'containerDiskIOBytes', + 'containerDiskIOOps', + ], }; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/container/layout.v2.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/container/layout.v2.tsx new file mode 100644 index 0000000000000..00da70f1d96a5 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/container/layout.v2.tsx @@ -0,0 +1,222 @@ +/* + * 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 { LayoutPropsWithTheme } from '../../../public/pages/metrics/types'; +import { Section } from '../../../public/pages/metrics/components/section'; +import { SubSection } from '../../../public/pages/metrics/components/sub_section'; +import { GaugesSectionVis } from '../../../public/pages/metrics/components/gauges_section_vis'; +import { ChartSectionVis } from '../../../public/pages/metrics/components/chart_section_vis'; +import { withTheme } from '../../../../../common/eui_styled_components'; + +export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( + +
+ + + + + + + + + + + + + + + + + + +
+
+)); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/host/detail_page.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/host/detail_page.tsx new file mode 100644 index 0000000000000..7ff69af87aa3a --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/host/detail_page.tsx @@ -0,0 +1,142 @@ +/* + * 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, { FunctionComponent, useEffect, useMemo } from 'react'; +import { EuiSideNav, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { InfraMetricData } from '../../../public/graphql/types'; +import { Section } from '../../../public/pages/metrics/components/section'; +import { SubSection } from '../../../public/pages/metrics/components/sub_section'; +import { NavItem, SideNavContext } from '../../../public/pages/metrics/lib/side_nav_context'; + +interface VisSectionProps { + metric?: InfraMetricData; +} + +const VisSection: FunctionComponent = ({ metric }) => { + if (metric) { + return ( +
+
VISUALIZATION GOES HERE
+
+ ); + } + return
Gauges without Metric (you should never see this)
; +}; + +interface WithMetricsDataProps { + source: string; + ids: string[]; + children: (props: LayoutProps) => React.ReactElement; +} + +const WithMetricsData = ({ ids, children }: WithMetricsDataProps) => { + if (!children) { + return null; + } + + // eslint-disable-next-line no-console + useEffect(() => console.log('Fetching', ids), [ids]); + + const metrics = useMemo(() => { + return ids.map(m => ({ id: m, series: [] })); + }, [ids]) as InfraMetricData[]; + + return children({ metrics }); +}; + +interface LayoutProps { + metrics: InfraMetricData[]; +} + +interface MetricsLayout { + requiredMetrics: string[]; + Layout: FunctionComponent; +} + +const Aws: MetricsLayout = { + requiredMetrics: ['awsOverview', 'awsCpuUsage'], + Layout: ({ metrics }) => ( +
+ + + + + + +
+ ), +}; +const Nginx: MetricsLayout = { + requiredMetrics: ['nginxOverview'], + Layout: ({ metrics }) => ( +
+ + + +
+ ), +}; + +export const Host: MetricsLayout = { + requiredMetrics: [ + 'hostSystemOverview', + 'hostSystemCPU', + ...Aws.requiredMetrics, + ...Nginx.requiredMetrics, + ], + Layout: ({ metrics }) => ( + +
+ + + + + + +
+ + +
+ ), +}; + +export const DetailPage: FunctionComponent = () => { + const [sideNav, setSideNav] = React.useState([]); + + const addNavItem = React.useCallback( + (item: NavItem) => { + if (!sideNav.some(n => n.id === item.id)) { + setSideNav([item, ...sideNav]); + } + }, + [sideNav] + ); + + return ( +
+ + + + + + + + {({ metrics }) => } + + + + +
+ ); +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts index e29f5878bfcb3..e69535e9d0f7d 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts @@ -7,10 +7,28 @@ import { layout } from './layout'; import { metrics } from './metrics'; import { InventoryModel } from '../types'; +import { + aws as awsRequiredMetrics, + nginx as nginxRequireMetrics, +} from '../shared/metrics/required_metrics'; export const host: InventoryModel = { id: 'host', requiredModules: ['system'], layout, metrics, + requiredMetrics: [ + 'hostSystemOverview', + 'hostCpuUsage', + 'hostLoad', + 'hostMemoryUsage', + 'hostNetworkTraffic', + 'hostK8sOverview', + 'hostK8sCpuCap', + 'hostK8sMemoryCap', + 'hostK8sDiskCap', + 'hostK8sPodCap', + ...awsRequiredMetrics, + ...nginxRequireMetrics, + ], }; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/host/layout.v2.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/host/layout.v2.tsx new file mode 100644 index 0000000000000..b7dcc29b19d3d --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/host/layout.v2.tsx @@ -0,0 +1,352 @@ +/* + * 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 { LayoutPropsWithTheme } from '../../../public/pages/metrics/types'; +import { Section } from '../../../public/pages/metrics/components/section'; +import { SubSection } from '../../../public/pages/metrics/components/sub_section'; +import { GaugesSectionVis } from '../../../public/pages/metrics/components/gauges_section_vis'; +import { ChartSectionVis } from '../../../public/pages/metrics/components/chart_section_vis'; +import { withTheme } from '../../../../../common/eui_styled_components'; +import * as AWS from '../shared/layouts/aws.v2'; +import * as Ngnix from '../shared/layouts/nginx.v2'; + +export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( + +
+ + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + +
+ + +
+)); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/index.ts index ec518cb9cb950..79aad7b2ccf6f 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/index.ts @@ -11,7 +11,7 @@ import { container } from './container'; import { InventoryItemType } from './types'; export { metrics } from './metrics'; -export const inventoryModels = [host, pod, container]; +const inventoryModels = [host, pod, container]; export const findInventoryModel = (type: InventoryItemType) => { const model = inventoryModels.find(m => m.id === type); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts b/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts new file mode 100644 index 0000000000000..f69a30e51c3d6 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts @@ -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. + */ + +/** + * WHY ARE THE LAYOUTS A SEPERATE FILE? + * + * Files with React can not be included on the server without + * crashing due to the requirement of the `window` object. + */ + +import { idx } from '@kbn/elastic-idx'; +import { i18n } from '@kbn/i18n'; + +import { ReactNode, FunctionComponent } from 'react'; +import { Layout as HostLayout } from './host/layout.v2'; +import { Layout as PodLayout } from './pod/layout.v2'; +import { Layout as ContainerLayout } from './container/layout.v2'; +import { InventoryItemType } from './types'; +import { LayoutProps } from '../../public/pages/metrics/types'; + +interface Layouts { + [type: string]: ReactNode; +} + +const Layouts: Layouts = { + host: HostLayout, + pod: PodLayout, + container: ContainerLayout, +}; + +export const findLayout = (type: InventoryItemType) => { + const Layout = idx(Layouts, _ => _[type]); + if (!Layout) { + throw new Error( + i18n.translate('xpack.infra.inventoryModels.findLayout.error', { + defaultMessage: "The layout you've attempted to find does not exist", + }) + ); + } + return Layout as FunctionComponent; +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts index 1cf839b787657..a3d619b08eb05 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts @@ -7,9 +7,18 @@ import { layout } from './layout'; import { metrics } from './metrics'; import { InventoryModel } from '../types'; +import { nginx as nginxRequiredMetrics } from '../shared/metrics/required_metrics'; + export const pod: InventoryModel = { id: 'pod', requiredModules: ['kubernetes'], layout, metrics, + requiredMetrics: [ + 'podOverview', + 'podCpuUsage', + 'podMemoryUsage', + 'podNetworkTraffic', + ...nginxRequiredMetrics, + ], }; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/pod/layout.v2.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/pod/layout.v2.tsx new file mode 100644 index 0000000000000..3afcf9488f216 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/pod/layout.v2.tsx @@ -0,0 +1,154 @@ +/* + * 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 { LayoutPropsWithTheme } from '../../../public/pages/metrics/types'; +import { Section } from '../../../public/pages/metrics/components/section'; +import { SubSection } from '../../../public/pages/metrics/components/sub_section'; +import { GaugesSectionVis } from '../../../public/pages/metrics/components/gauges_section_vis'; +import { ChartSectionVis } from '../../../public/pages/metrics/components/chart_section_vis'; +import { withTheme } from '../../../../../common/eui_styled_components'; +import * as Nginx from '../shared/layouts/nginx.v2'; + +export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( + +
+ + + + + + + + + + + + +
+ +
+)); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/aws.v2.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/aws.v2.tsx new file mode 100644 index 0000000000000..2cabbe4c33ff3 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/aws.v2.tsx @@ -0,0 +1,237 @@ +/* + * 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 { LayoutPropsWithTheme } from '../../../../public/pages/metrics/types'; +import { Section } from '../../../../public/pages/metrics/components/section'; +import { SubSection } from '../../../../public/pages/metrics/components/sub_section'; +import { GaugesSectionVis } from '../../../../public/pages/metrics/components/gauges_section_vis'; +import { ChartSectionVis } from '../../../../public/pages/metrics/components/chart_section_vis'; +import { withTheme } from '../../../../../../common/eui_styled_components'; + +export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( + +
+ + + + + + + + + + + + + + + + + + +
+
+)); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/nginx.v2.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/nginx.v2.tsx new file mode 100644 index 0000000000000..9d31ffa775d21 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/nginx.v2.tsx @@ -0,0 +1,103 @@ +/* + * 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 { LayoutPropsWithTheme } from '../../../../public/pages/metrics/types'; +import { Section } from '../../../../public/pages/metrics/components/section'; +import { SubSection } from '../../../../public/pages/metrics/components/sub_section'; +import { ChartSectionVis } from '../../../../public/pages/metrics/components/chart_section_vis'; +import { withTheme } from '../../../../../../common/eui_styled_components'; + +export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( + +
+ + + + + + + + + + + + +
+
+)); diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/required_metrics.ts b/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/required_metrics.ts new file mode 100644 index 0000000000000..7bd888ab7c589 --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/required_metrics.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +export const nginx = [ + 'nginxHits', + 'nginxRequestRate', + 'nginxActiveConnections', + 'nginxRequestsPerConnection', +]; + +export const aws = [ + 'awsOverview', + 'awsCpuUtilization', + 'awsNetworkBytes', + 'awsNetworkPackets', + 'awsDiskioOps', + 'awsDiskioBytes', +]; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/types.ts b/x-pack/legacy/plugins/infra/common/inventory_models/types.ts index 9c9f11048ee63..b1d0e1dcad5cc 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/types.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/types.ts @@ -32,6 +32,7 @@ export const InventoryFormatterTypeRT = rt.keyof({ number: null, percent: null, }); +export type InventoryFormatterType = rt.TypeOf; export type InventoryItemType = rt.TypeOf; export const InventoryMetricRT = rt.string; @@ -282,4 +283,5 @@ export interface InventoryModel { requiredModules: string[]; layout: InventoryDetailLayoutCreator; metrics: InventoryMetrics; + requiredMetrics: InventoryMetric[]; } diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/index.tsx b/x-pack/legacy/plugins/infra/public/components/metrics/index.tsx deleted file mode 100644 index a80525e3a9cac..0000000000000 --- a/x-pack/legacy/plugins/infra/public/components/metrics/index.tsx +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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 { EuiPageContentBody, EuiTitle } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import React from 'react'; - -import { InfraMetricData } from '../../graphql/types'; -import { NoData } from '../empty_states'; -import { InfraLoadingPanel } from '../loading'; -import { Section } from './section'; -import { MetricsTimeInput } from '../../containers/metrics/with_metrics_time'; -import { - InventoryDetailLayout, - InventoryDetailSection, -} from '../../../common/inventory_models/types'; - -interface Props { - metrics: InfraMetricData[]; - layouts: InventoryDetailLayout[]; - loading: boolean; - refetch: () => void; - nodeId: string; - label: string; - onChangeRangeTime?: (time: MetricsTimeInput) => void; - isLiveStreaming?: boolean; - stopLiveStreaming?: () => void; -} - -interface State { - crosshairValue: number | null; -} - -export const Metrics = class extends React.PureComponent { - public static displayName = 'Metrics'; - public readonly state = { - crosshairValue: null, - }; - - public render() { - if (this.props.loading) { - return ( - - ); - } else if (!this.props.loading && this.props.metrics && this.props.metrics.length === 0) { - return ( - - ); - } - - return {this.props.layouts.map(this.renderLayout)}; - } - - private handleRefetch = () => { - this.props.refetch(); - }; - - private renderLayout = (layout: InventoryDetailLayout) => { - return ( - - - -

- -

-
-
- {layout.sections.map(this.renderSection(layout))} -
- ); - }; - - private renderSection = (layout: InventoryDetailLayout) => (section: InventoryDetailSection) => { - let sectionProps = {}; - if (section.type === 'chart') { - const { onChangeRangeTime, isLiveStreaming, stopLiveStreaming } = this.props; - sectionProps = { - onChangeRangeTime, - isLiveStreaming, - stopLiveStreaming, - crosshairValue: this.state.crosshairValue, - onCrosshairUpdate: this.onCrosshairUpdate, - }; - } - return ( -
- ); - }; - - private onCrosshairUpdate = (crosshairValue: number) => { - this.setState({ - crosshairValue, - }); - }; -}; diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/section.tsx b/x-pack/legacy/plugins/infra/public/components/metrics/section.tsx deleted file mode 100644 index ff416bf4541b2..0000000000000 --- a/x-pack/legacy/plugins/infra/public/components/metrics/section.tsx +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 { InfraMetricData } from '../../graphql/types'; -import { sections } from './sections'; -import { MetricsTimeInput } from '../../containers/metrics/with_metrics_time'; -import { InventoryDetailSection } from '../../../common/inventory_models/types'; - -interface Props { - section: InventoryDetailSection; - metrics: InfraMetricData[]; - onChangeRangeTime?: (time: MetricsTimeInput) => void; - crosshairValue?: number; - onCrosshairUpdate?: (crosshairValue: number) => void; - isLiveStreaming?: boolean; - stopLiveStreaming?: () => void; -} - -export class Section extends React.PureComponent { - public render() { - const metric = this.props.metrics.find(m => m.id === this.props.section.id); - if (!metric) { - return null; - } - let sectionProps = {}; - if (this.props.section.type === 'chart') { - sectionProps = { - onChangeRangeTime: this.props.onChangeRangeTime, - crosshairValue: this.props.crosshairValue, - onCrosshairUpdate: this.props.onCrosshairUpdate, - isLiveStreaming: this.props.isLiveStreaming, - stopLiveStreaming: this.props.stopLiveStreaming, - }; - } - const Component = sections[this.props.section.type]; - return ; - } -} diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/sections/gauges_section.tsx b/x-pack/legacy/plugins/infra/public/components/metrics/sections/gauges_section.tsx deleted file mode 100644 index 6b73ac62872c9..0000000000000 --- a/x-pack/legacy/plugins/infra/public/components/metrics/sections/gauges_section.tsx +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 { - EuiFlexItem, - EuiPageContentBody, - EuiPanel, - EuiProgress, - EuiSpacer, - EuiText, - EuiTitle, -} from '@elastic/eui'; -import { get, last, max } from 'lodash'; -import React, { ReactText } from 'react'; - -import euiStyled from '../../../../../../common/eui_styled_components'; -import { InfraMetricData } from '../../../graphql/types'; -import { InfraFormatterType } from '../../../lib/lib'; -import { createFormatter } from '../../../utils/formatters'; -import { InventoryDetailSection } from '../../../../common/inventory_models/types'; - -interface Props { - section: InventoryDetailSection; - metric: InfraMetricData; -} - -const getFormatter = (section: InventoryDetailSection, seriesId: string) => (val: ReactText) => { - if (val == null) { - return ''; - } - const defaultFormatter = get(section, ['visConfig', 'formatter'], InfraFormatterType.number); - const defaultFormatterTemplate = get(section, ['visConfig', 'formatterTemplate'], '{{value}}'); - const formatter = get( - section, - ['visConfig', 'seriesOverrides', seriesId, 'formatter'], - defaultFormatter - ); - const formatterTemplate = get( - section, - ['visConfig', 'seriesOverrides', seriesId, 'formatterTemplate'], - defaultFormatterTemplate - ); - return createFormatter(formatter, formatterTemplate)(val); -}; - -export class GaugesSection extends React.PureComponent { - public render() { - const { metric, section } = this.props; - return ( - - - - {metric.series.map(series => { - const lastDataPoint = last(series.data); - if (!lastDataPoint) { - return null; - } - const formatter = getFormatter(section, series.id); - const value = formatter(lastDataPoint.value || 0); - const name = get( - section, - ['visConfig', 'seriesOverrides', series.id, 'name'], - series.id - ); - const dataMax = max(series.data.map(d => d.value || 0)); - const gaugeMax = get( - section, - ['visConfig', 'seriesOverrides', series.id, 'gaugeMax'], - dataMax - ); - return ( - - - - {name} - - -

{value}

-
- -
-
- ); - })} -
- -
- ); - } -} - -const GroupBox = euiStyled.div` - display: flex; - flex-flow: row wrap; - justify-content: space-evenly; -`; diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/sections/index.ts b/x-pack/legacy/plugins/infra/public/components/metrics/sections/index.ts deleted file mode 100644 index 39844868ecbea..0000000000000 --- a/x-pack/legacy/plugins/infra/public/components/metrics/sections/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 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 { GaugesSection } from './gauges_section'; -import { ChartSection } from './chart_section'; - -export const sections = { - chart: ChartSection, - gauges: GaugesSection, -}; diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/side_nav.tsx b/x-pack/legacy/plugins/infra/public/components/metrics/side_nav.tsx deleted file mode 100644 index f20adadce6042..0000000000000 --- a/x-pack/legacy/plugins/infra/public/components/metrics/side_nav.tsx +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 { EuiHideFor, EuiPageSideBar, EuiShowFor, EuiSideNav } from '@elastic/eui'; - -import React from 'react'; - -import euiStyled from '../../../../../common/eui_styled_components'; -import { - InventoryDetailLayout, - InventoryDetailSection, -} from '../../../common/inventory_models/types'; - -interface Props { - layouts: InventoryDetailLayout[]; - loading: boolean; - nodeName: string; - handleClick: (section: InventoryDetailSection) => () => void; -} - -export const MetricsSideNav = class extends React.PureComponent { - public static displayName = 'MetricsSideNav'; - - public readonly state = { - isOpenOnMobile: false, - }; - - public render() { - let content; - let mobileContent; - if (!this.props.loading) { - const entries = this.props.layouts.map(item => { - return { - name: item.label, - id: item.id, - items: item.sections.map(section => ({ - id: section.id, - name: section.label, - onClick: this.props.handleClick(section), - })), - }; - }); - content = ; - mobileContent = ( - - ); - } - return ( - - - {content} - - {mobileContent} - - ); - } - - private toggleOpenOnMobile = () => { - this.setState({ - isOpenOnMobile: !this.state.isOpenOnMobile, - }); - }; -}; - -const SideNavContainer = euiStyled.div` - position: fixed; - z-index: 1; - height: 88vh; - padding-left: 16px; - margin-left: -16px; - overflow-y: auto; - overflow-x: hidden; -`; diff --git a/x-pack/legacy/plugins/infra/public/containers/metadata/lib/get_filtered_metrics.ts b/x-pack/legacy/plugins/infra/public/containers/metadata/lib/get_filtered_metrics.ts new file mode 100644 index 0000000000000..b485c90700145 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/containers/metadata/lib/get_filtered_metrics.ts @@ -0,0 +1,25 @@ +/* + * 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 { InfraMetadataFeature } from '../../../../common/http_api/metadata_api'; +import { InventoryMetric } from '../../../../common/inventory_models/types'; +import { metrics } from '../../../../common/inventory_models/metrics'; + +export const getFilteredMetrics = ( + requiredMetrics: InventoryMetric[], + metadata: Array +) => { + const metricMetadata = metadata + .filter(data => data && data.source === 'metrics') + .map(data => data && data.name); + return requiredMetrics.filter(metric => { + const metricModelCreator = metrics.tsvb[metric]; + // We just need to get a dummy version of the model so we can filter + // using the `requires` attribute. + const metricModel = metricModelCreator('@timestamp', 'test', '>=1m'); + return metricMetadata.some(m => m && metricModel.requires.includes(m)); + }); +}; diff --git a/x-pack/legacy/plugins/infra/public/containers/metadata/use_metadata.ts b/x-pack/legacy/plugins/infra/public/containers/metadata/use_metadata.ts index 540e32a27b319..9db0ef5089a4a 100644 --- a/x-pack/legacy/plugins/infra/public/containers/metadata/use_metadata.ts +++ b/x-pack/legacy/plugins/infra/public/containers/metadata/use_metadata.ts @@ -13,12 +13,14 @@ import { InfraMetadata, InfraMetadataRT } from '../../../common/http_api/metadat import { getFilteredLayouts } from './lib/get_filtered_layouts'; import { useHTTPRequest } from '../../hooks/use_http_request'; import { throwErrors, createPlainError } from '../../../common/runtime_types'; -import { InventoryDetailLayout } from '../../../common/inventory_models/types'; +import { InventoryDetailLayout, InventoryMetric } from '../../../common/inventory_models/types'; +import { getFilteredMetrics } from './lib/get_filtered_metrics'; export function useMetadata( nodeId: string, nodeType: InfraNodeType, layouts: InventoryDetailLayout[], + requiredMetrics: InventoryMetric[], sourceId: string ) { const decodeResponse = (response: any) => { @@ -48,6 +50,8 @@ export function useMetadata( return { name: (response && response.name) || '', filteredLayouts: (response && getFilteredLayouts(layouts, response.features)) || [], + filteredRequiredMetrics: + (response && getFilteredMetrics(requiredMetrics, response.features)) || [], error: (error && error.message) || null, loading, metadata: response, diff --git a/x-pack/legacy/plugins/infra/public/pages/link_to/redirect_to_host_detail_via_ip.tsx b/x-pack/legacy/plugins/infra/public/pages/link_to/redirect_to_host_detail_via_ip.tsx index d06abb2aa1060..c1b0814f550a3 100644 --- a/x-pack/legacy/plugins/infra/public/pages/link_to/redirect_to_host_detail_via_ip.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/link_to/redirect_to_host_detail_via_ip.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { Redirect, RouteComponentProps } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; -import { replaceMetricTimeInQueryString } from '../../containers/metrics/with_metrics_time'; +import { replaceMetricTimeInQueryString } from '../metrics/containers/with_metrics_time'; import { useHostIpToName } from './use_host_ip_to_name'; import { getFromFromLocation, getToFromLocation } from './query_params'; import { LoadingPage } from '../../components/loading_page'; diff --git a/x-pack/legacy/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx b/x-pack/legacy/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx index ad51307641780..a2cebbb96a4f0 100644 --- a/x-pack/legacy/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { Redirect, RouteComponentProps } from 'react-router-dom'; -import { replaceMetricTimeInQueryString } from '../../containers/metrics/with_metrics_time'; +import { replaceMetricTimeInQueryString } from '../metrics/containers/with_metrics_time'; import { InfraNodeType } from '../../graphql/types'; import { getFromFromLocation, getToFromLocation } from './query_params'; diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/sections/chart_section.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/chart_section_vis.tsx similarity index 72% rename from x-pack/legacy/plugins/infra/public/components/metrics/sections/chart_section.tsx rename to x-pack/legacy/plugins/infra/public/pages/metrics/components/chart_section_vis.tsx index cf148eefe8e8f..425b5a43f793f 100644 --- a/x-pack/legacy/plugins/infra/public/components/metrics/sections/chart_section.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/chart_section_vis.tsx @@ -6,8 +6,6 @@ import React, { useCallback } from 'react'; import moment from 'moment'; import { i18n } from '@kbn/i18n'; - -import { get } from 'lodash'; import { Axis, Chart, @@ -17,10 +15,8 @@ import { Settings, TooltipValue, } from '@elastic/charts'; -import { EuiPageContentBody, EuiTitle } from '@elastic/eui'; -import { InfraMetricData } from '../../../graphql/types'; -import { getChartTheme } from '../../metrics_explorer/helpers/get_chart_theme'; -import { InfraFormatterType } from '../../../lib/lib'; +import { EuiPageContentBody } from '@elastic/eui'; +import { getChartTheme } from '../../../components/metrics_explorer/helpers/get_chart_theme'; import { SeriesChart } from './series_chart'; import { getFormatter, @@ -32,28 +28,24 @@ import { } from './helpers'; import { ErrorMessage } from './error_message'; import { useKibanaUiSetting } from '../../../utils/use_kibana_ui_setting'; -import { MetricsTimeInput } from '../../../containers/metrics/with_metrics_time'; -import { InventoryDetailSection } from '../../../../common/inventory_models/types'; - -interface Props { - section: InventoryDetailSection; - metric: InfraMetricData; - onChangeRangeTime?: (time: MetricsTimeInput) => void; - isLiveStreaming?: boolean; - stopLiveStreaming?: () => void; -} +import { VisSectionProps } from '../types'; -export const ChartSection = ({ +export const ChartSectionVis = ({ + id, onChangeRangeTime, - section, metric, stopLiveStreaming, isLiveStreaming, -}: Props) => { - const { visConfig } = section; + formatter, + formatterTemplate, + stacked, + seriesOverrides, + type, +}: VisSectionProps) => { + if (!metric || !id) { + return null; + } const [dateFormat] = useKibanaUiSetting('dateFormat'); - const formatter = get(visConfig, 'formatter', InfraFormatterType.number); - const formatterTemplate = get(visConfig, 'formatterTemplate', '{{value}}'); const valueFormatter = useCallback(getFormatter(formatter, formatterTemplate), [ formatter, formatterTemplate, @@ -109,9 +101,6 @@ export const ChartSection = ({ return ( - -

{section.label}

-
( ))} (val: ReactText) => { + if (val == null) { + return ''; + } + const formatter = get(seriesOverrides, [seriesId, 'formatter'], defaultFormatter); + const formatterTemplate = get( + seriesOverrides, + [seriesId, 'formatterTemplate'], + defaultFormatterTemplate + ); + return createFormatter(formatter, formatterTemplate)(val); +}; + +export const GaugesSectionVis = ({ + id, + metric, + seriesOverrides, + formatter, + formatterTemplate, +}: VisSectionProps) => { + if (!metric || !id) { + return null; + } + return ( + + + + {metric.series.map(series => { + const lastDataPoint = last(series.data); + if (!lastDataPoint) { + return null; + } + const formatterFn = getFormatter( + formatter, + formatterTemplate, + seriesOverrides, + series.id + ); + const value = formatterFn(lastDataPoint.value || 0); + const name = getChartName(seriesOverrides, series.id, series.id); + const dataMax = max(series.data.map(d => d.value || 0)); + const gaugeMax = get(seriesOverrides, [series.id, 'gaugeMax'], dataMax); + return ( + + + + {name} + + +

{value}

+
+ +
+
+ ); + })} +
+ +
+ ); +}; + +const GroupBox = euiStyled.div` + display: flex; + flex-flow: row wrap; + justify-content: space-evenly; +`; diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/sections/helpers/index.ts b/x-pack/legacy/plugins/infra/public/pages/metrics/components/helpers.ts similarity index 58% rename from x-pack/legacy/plugins/infra/public/components/metrics/sections/helpers/index.ts rename to x-pack/legacy/plugins/infra/public/pages/metrics/components/helpers.ts index bfc1385c0431a..0da73bcd7a531 100644 --- a/x-pack/legacy/plugins/infra/public/components/metrics/sections/helpers/index.ts +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/helpers.ts @@ -7,19 +7,22 @@ import { ReactText } from 'react'; import Color from 'color'; import { get, first, last, min, max } from 'lodash'; -import { InfraFormatterType } from '../../../../lib/lib'; -import { createFormatter } from '../../../../utils/formatters'; -import { InfraDataSeries, InfraMetricData } from '../../../../graphql/types'; +import { createFormatter } from '../../../utils/formatters'; +import { InfraDataSeries, InfraMetricData } from '../../../graphql/types'; import { - InventoryDetailSection, InventoryVisTypeRT, -} from '../../../../../common/inventory_models/types'; + InventoryFormatterType, + InventoryVisType, +} from '../../../../common/inventory_models/types'; +import { SeriesOverrides } from '../types'; /** * Returns a formatter */ -export const getFormatter = (formatter: InfraFormatterType, template: string) => (val: ReactText) => - val != null ? createFormatter(formatter, template)(val) : ''; +export const getFormatter = ( + formatter: InventoryFormatterType = 'number', + template: string = '{{value}}' +) => (val: ReactText) => (val != null ? createFormatter(formatter, template)(val) : ''); /** * Does a series have more then two points? @@ -53,16 +56,25 @@ export const getMaxMinTimestamp = (metric: InfraMetricData): [number, number] => * Returns the chart name from the visConfig based on the series id, otherwise it * just returns the seriesId */ -export const getChartName = (section: InventoryDetailSection, seriesId: string, label: string) => { - return get(section, ['visConfig', 'seriesOverrides', seriesId, 'name'], label); +export const getChartName = ( + seriesOverrides: SeriesOverrides | undefined, + seriesId: string, + label: string +) => { + if (!seriesOverrides) { + return label; + } + return get(seriesOverrides, [seriesId, 'name'], label); }; /** * Returns the chart color from the visConfig based on the series id, otherwise it * just returns null if the color doesn't exists in the overrides. */ -export const getChartColor = (section: InventoryDetailSection, seriesId: string) => { - const rawColor: string | null = get(section, ['visConfig', 'seriesOverrides', seriesId, 'color']); +export const getChartColor = (seriesOverrides: SeriesOverrides | undefined, seriesId: string) => { + const rawColor: string | null = seriesOverrides + ? get(seriesOverrides, [seriesId, 'color']) + : null; if (!rawColor) { return null; } @@ -73,14 +85,20 @@ export const getChartColor = (section: InventoryDetailSection, seriesId: string) /** * Gets the chart type based on the section and seriesId */ -export const getChartType = (section: InventoryDetailSection, seriesId: string) => { - const value = get(section, ['visConfig', 'type']); - const overrideValue = get(section, ['visConfig', 'seriesOverrides', seriesId, 'type']); +export const getChartType = ( + seriesOverrides: SeriesOverrides | undefined, + type: InventoryVisType | undefined, + seriesId: string +) => { + if (!seriesOverrides || !type) { + return 'line'; + } + const overrideValue = get(seriesOverrides, [seriesId, 'type']); if (InventoryVisTypeRT.is(overrideValue)) { return overrideValue; } - if (InventoryVisTypeRT.is(value)) { - return value; + if (InventoryVisTypeRT.is(type)) { + return type; } return 'line'; }; diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/invalid_node.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/invalid_node.tsx similarity index 92% rename from x-pack/legacy/plugins/infra/public/components/metrics/invalid_node.tsx rename to x-pack/legacy/plugins/infra/public/pages/metrics/components/invalid_node.tsx index 673bca91904c7..f9e56791746f5 100644 --- a/x-pack/legacy/plugins/infra/public/components/metrics/invalid_node.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/invalid_node.tsx @@ -8,12 +8,12 @@ import { EuiButton, EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem } from '@elastic/e import { FormattedMessage } from '@kbn/i18n/react'; import React from 'react'; -import euiStyled from '../../../../../common/eui_styled_components'; -import { WithKibanaChrome } from '../../containers/with_kibana_chrome'; +import euiStyled from '../../../../../../common/eui_styled_components'; +import { WithKibanaChrome } from '../../../containers/with_kibana_chrome'; import { ViewSourceConfigurationButton, ViewSourceConfigurationButtonHrefBase, -} from '../../components/source_configuration'; +} from '../../../components/source_configuration'; interface InvalidNodeErrorProps { nodeName: string; diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/node_details.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/node_details.tsx similarity index 97% rename from x-pack/legacy/plugins/infra/public/components/metrics/node_details.tsx rename to x-pack/legacy/plugins/infra/public/pages/metrics/components/node_details.tsx index 41331ed73afce..5329ea992c493 100644 --- a/x-pack/legacy/plugins/infra/public/components/metrics/node_details.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/node_details.tsx @@ -8,8 +8,8 @@ import React, { useState, useCallback, useMemo } from 'react'; import { EuiButtonIcon, EuiFlexGrid, EuiFlexItem, EuiTitle, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { get } from 'lodash'; -import { InfraMetadata } from '../../../common/http_api'; -import euiStyled from '../../../../../common/eui_styled_components'; +import { InfraMetadata } from '../../../../common/http_api'; +import euiStyled from '../../../../../../common/eui_styled_components'; interface Props { metadata?: InfraMetadata | null; diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/components/page_body.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/page_body.tsx new file mode 100644 index 0000000000000..81c96c0ffe68d --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/page_body.tsx @@ -0,0 +1,72 @@ +/* + * 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 { findLayout } from '../../../../common/inventory_models/layouts'; +import { InventoryItemType } from '../../../../common/inventory_models/types'; +import { InfraMetricData } from '../../../graphql/types'; +import { MetricsTimeInput } from '../containers/with_metrics_time'; +import { InfraLoadingPanel } from '../../../components/loading'; +import { NoData } from '../../../components/empty_states'; + +interface Props { + loading: boolean; + refetch: () => void; + type: InventoryItemType; + metrics: InfraMetricData[]; + onChangeRangeTime?: (time: MetricsTimeInput) => void; + isLiveStreaming?: boolean; + stopLiveStreaming?: () => void; +} + +export const PageBody = ({ + loading, + refetch, + type, + metrics, + onChangeRangeTime, + isLiveStreaming, + stopLiveStreaming, +}: Props) => { + if (loading) { + return ( + + ); + } else if (!loading && metrics && metrics.length === 0) { + return ( + + ); + } + + const Layout = findLayout(type); + return ( + + ); +}; diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/components/page_error.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/page_error.tsx new file mode 100644 index 0000000000000..69ba80b85e3b2 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/page_error.tsx @@ -0,0 +1,45 @@ +/* + * 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 { GraphQLFormattedError } from 'graphql'; +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { ApolloError } from 'apollo-client'; +import { InvalidNodeError } from './invalid_node'; +import { InfraMetricsErrorCodes } from '../../../../common/errors'; +import { DocumentTitle } from '../../../components/document_title'; +import { ErrorPageBody } from '../../error'; + +interface Props { + name: string; + error: ApolloError; +} + +export const PageError = ({ error, name }: Props) => { + const invalidNodeError = error.graphQLErrors.some( + (err: GraphQLFormattedError) => err.code === InfraMetricsErrorCodes.invalid_node + ); + + return ( + <> + + i18n.translate('xpack.infra.metricDetailPage.documentTitleError', { + defaultMessage: '{previousTitle} | Uh oh', + values: { + previousTitle, + }, + }) + } + /> + {invalidNodeError ? ( + + ) : ( + + )} + + ); +}; diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/components/section.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/section.tsx new file mode 100644 index 0000000000000..9a87557713616 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/section.tsx @@ -0,0 +1,67 @@ +/* + * 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, { FunctionComponent, useCallback } from 'react'; +import { EuiTitle } from '@elastic/eui'; +import { SideNavContext, SubNavItem } from '../lib/side_nav_context'; +import { LayoutProps } from '../types'; + +type SectionProps = LayoutProps & { + navLabel: string; + sectionLabel: string; +}; + +export const Section: FunctionComponent = ({ + children, + metrics, + navLabel, + sectionLabel, + onChangeRangeTime, + isLiveStreaming, + stopLiveStreaming, +}) => { + const { addNavItem } = React.useContext(SideNavContext); + const subNavItems: SubNavItem[] = []; + + const childrenWithProps = React.Children.map(children, child => { + if (React.isValidElement(child)) { + const metric = (metrics && metrics.find(m => m.id === child.props.id)) || null; + if (metric) { + subNavItems.push({ + id: child.props.id, + name: child.props.label, + onClick: useCallback(() => { + const el = document.getElementById(child.props.id); + if (el) { + el.scrollIntoView(); + } + }, []), + }); + } + return React.cloneElement(child, { + metrics, + onChangeRangeTime, + isLiveStreaming, + stopLiveStreaming, + }); + } + return null; + }); + + if (metrics && subNavItems.length) { + addNavItem({ id: navLabel, name: navLabel, items: subNavItems }); + return ( +
+ +

{sectionLabel}

+
+ {childrenWithProps} +
+ ); + } + + return null; +}; diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/sections/series_chart.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/series_chart.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/components/metrics/sections/series_chart.tsx rename to x-pack/legacy/plugins/infra/public/pages/metrics/components/series_chart.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/components/side_nav.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/side_nav.tsx new file mode 100644 index 0000000000000..8e922818222b4 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/side_nav.tsx @@ -0,0 +1,52 @@ +/* + * 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 { EuiHideFor, EuiPageSideBar, EuiShowFor, EuiSideNav } from '@elastic/eui'; +import React, { useState, useCallback } from 'react'; +import euiStyled from '../../../../../../common/eui_styled_components'; +import { NavItem } from '../lib/side_nav_context'; + +interface Props { + loading: boolean; + name: string; + items: NavItem[]; +} + +export const MetricsSideNav = ({ loading, name, items }: Props) => { + const [isOpenOnMobile, setMobileState] = useState(false); + + const toggle = useCallback(() => { + setMobileState(!isOpenOnMobile); + }, [isOpenOnMobile]); + + const content = loading ? null : ; + const mobileContent = loading ? null : ( + + ); + return ( + + + {content} + + {mobileContent} + + ); +}; + +const SideNavContainer = euiStyled.div` + position: fixed; + z-index: 1; + height: 88vh; + padding-left: 16px; + margin-left: -16px; + overflow-y: auto; + overflow-x: hidden; +`; diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/components/sub_section.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/sub_section.tsx new file mode 100644 index 0000000000000..80253db52d61c --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/sub_section.tsx @@ -0,0 +1,55 @@ +/* + * 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, { FunctionComponent } from 'react'; +import { EuiTitle } from '@elastic/eui'; +import { InventoryMetric } from '../../../../common/inventory_models/types'; +import { LayoutProps } from '../types'; + +type SubSectionProps = LayoutProps & { + id: InventoryMetric; + label?: string; +}; + +export const SubSection: FunctionComponent = ({ + id, + label, + children, + metrics, + onChangeRangeTime, + isLiveStreaming, + stopLiveStreaming, +}) => { + if (!children || !metrics) { + return null; + } + const metric = metrics.find(m => m.id === id); + if (!metric) { + return null; + } + const childrenWithProps = React.Children.map(children, child => { + if (React.isValidElement(child)) { + return React.cloneElement(child, { + metric, + id, + onChangeRangeTime, + isLiveStreaming, + stopLiveStreaming, + }); + } + return null; + }); + return ( +
+ {label ? ( + +

{label}

+
+ ) : null} + {childrenWithProps} +
+ ); +}; diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/time_controls.test.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.test.tsx similarity index 95% rename from x-pack/legacy/plugins/infra/public/components/metrics/time_controls.test.tsx rename to x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.test.tsx index 61872f52615a0..624a2bb4a6f0f 100644 --- a/x-pack/legacy/plugins/infra/public/components/metrics/time_controls.test.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { MetricsTimeControls } from './time_controls'; import { mount } from 'enzyme'; -import { MetricsTimeInput } from '../../containers/metrics/with_metrics_time'; +import { MetricsTimeInput } from '../containers/with_metrics_time'; describe('MetricsTimeControls', () => { it('should set a valid from and to value for Today', () => { diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/time_controls.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.tsx similarity index 92% rename from x-pack/legacy/plugins/infra/public/components/metrics/time_controls.tsx rename to x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.tsx index 7d236cf0a3ea7..d181aa37f59aa 100644 --- a/x-pack/legacy/plugins/infra/public/components/metrics/time_controls.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/time_controls.tsx @@ -6,8 +6,8 @@ import { EuiSuperDatePicker, OnRefreshChangeProps, OnTimeChangeProps } from '@elastic/eui'; import React from 'react'; -import euiStyled from '../../../../../common/eui_styled_components'; -import { MetricsTimeInput } from '../../containers/metrics/with_metrics_time'; +import euiStyled from '../../../../../../common/eui_styled_components'; +import { MetricsTimeInput } from '../containers/with_metrics_time'; interface MetricsTimeControlsProps { currentTimeRange: MetricsTimeInput; diff --git a/x-pack/legacy/plugins/infra/public/containers/metrics/metrics.gql_query.ts b/x-pack/legacy/plugins/infra/public/pages/metrics/containers/metrics.gql_query.ts similarity index 100% rename from x-pack/legacy/plugins/infra/public/containers/metrics/metrics.gql_query.ts rename to x-pack/legacy/plugins/infra/public/pages/metrics/containers/metrics.gql_query.ts diff --git a/x-pack/legacy/plugins/infra/public/containers/metrics/metrics_time.test.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/containers/metrics_time.test.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/containers/metrics/metrics_time.test.tsx rename to x-pack/legacy/plugins/infra/public/pages/metrics/containers/metrics_time.test.tsx diff --git a/x-pack/legacy/plugins/infra/public/containers/metrics/with_metrics.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/containers/with_metrics.tsx similarity index 82% rename from x-pack/legacy/plugins/infra/public/containers/metrics/with_metrics.tsx rename to x-pack/legacy/plugins/infra/public/pages/metrics/containers/with_metrics.tsx index 95f130878fc52..6f7e411628d27 100644 --- a/x-pack/legacy/plugins/infra/public/containers/metrics/with_metrics.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/containers/with_metrics.tsx @@ -13,9 +13,9 @@ import { InfraNodeType, MetricsQuery, InfraTimerangeInput, -} from '../../graphql/types'; +} from '../../../graphql/types'; import { metricsQuery } from './metrics.gql_query'; -import { InventoryDetailLayout, InventoryMetric } from '../../../common/inventory_models/types'; +import { InventoryMetric, InventoryMetricRT } from '../../../../common/inventory_models/types'; interface WithMetricsArgs { metrics: InfraMetricData[]; @@ -26,7 +26,7 @@ interface WithMetricsArgs { interface WithMetricsProps { children: (args: WithMetricsArgs) => React.ReactNode; - layouts: InventoryDetailLayout[]; + requiredMetrics: InventoryMetric[]; nodeType: InfraNodeType; nodeId: string; cloudId: string; @@ -35,26 +35,19 @@ interface WithMetricsProps { } const isInfraMetrics = (subject: any[]): subject is InfraMetric[] => { - return subject.every(s => !!InfraMetric[s]); + return subject.every(s => InventoryMetricRT.is(s)); }; export const WithMetrics = ({ children, - layouts, + requiredMetrics, sourceId, timerange, nodeType, nodeId, cloudId, }: WithMetricsProps) => { - const metrics = layouts.reduce( - (acc, item) => { - return acc.concat(item.sections.map(s => s.id)); - }, - [] as InventoryMetric[] - ); - - if (!isInfraMetrics(metrics)) { + if (!isInfraMetrics(requiredMetrics)) { throw new Error( i18n.translate('xpack.infra.invalidInventoryMetricsError', { defaultMessage: 'One of the InfraMetric is invalid', @@ -69,7 +62,7 @@ export const WithMetrics = ({ notifyOnNetworkStatusChange variables={{ sourceId, - metrics, + metrics: requiredMetrics, nodeType, nodeId, cloudId, diff --git a/x-pack/legacy/plugins/infra/public/containers/metrics/with_metrics_time.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/containers/with_metrics_time.tsx similarity index 98% rename from x-pack/legacy/plugins/infra/public/containers/metrics/with_metrics_time.tsx rename to x-pack/legacy/plugins/infra/public/pages/metrics/containers/with_metrics_time.tsx index 1afc3a04acd65..6a89e75679468 100644 --- a/x-pack/legacy/plugins/infra/public/containers/metrics/with_metrics_time.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/containers/with_metrics_time.tsx @@ -11,8 +11,8 @@ import moment from 'moment'; import dateMath from '@elastic/datemath'; import * as rt from 'io-ts'; import { isRight } from 'fp-ts/lib/Either'; -import { replaceStateKeyInQueryString, UrlStateContainer } from '../../utils/url_state'; -import { InfraTimerangeInput } from '../../graphql/types'; +import { replaceStateKeyInQueryString, UrlStateContainer } from '../../../utils/url_state'; +import { InfraTimerangeInput } from '../../../graphql/types'; export interface MetricsTimeInput { from: string; diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx index 1996d51b4f26b..92865b954bcbb 100644 --- a/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx @@ -14,34 +14,28 @@ import { EuiTitle, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { GraphQLFormattedError } from 'graphql'; -import React, { useCallback, useContext } from 'react'; +import React, { useContext, useState } from 'react'; import { UICapabilities } from 'ui/capabilities'; import { injectUICapabilities } from 'ui/capabilities/react'; import euiStyled, { EuiTheme, withTheme } from '../../../../../common/eui_styled_components'; -import { InfraMetricsErrorCodes } from '../../../common/errors'; import { AutoSizer } from '../../components/auto_sizer'; import { DocumentTitle } from '../../components/document_title'; import { Header } from '../../components/header'; -import { Metrics } from '../../components/metrics'; -import { InvalidNodeError } from '../../components/metrics/invalid_node'; -import { MetricsSideNav } from '../../components/metrics/side_nav'; -import { MetricsTimeControls } from '../../components/metrics/time_controls'; +import { MetricsSideNav } from './components/side_nav'; +import { MetricsTimeControls } from './components/time_controls'; import { ColumnarPage, PageContent } from '../../components/page'; -import { WithMetrics } from '../../containers/metrics/with_metrics'; -import { - WithMetricsTime, - WithMetricsTimeUrlState, -} from '../../containers/metrics/with_metrics_time'; +import { WithMetrics } from './containers/with_metrics'; +import { WithMetricsTime, WithMetricsTimeUrlState } from './containers/with_metrics_time'; import { InfraNodeType } from '../../graphql/types'; -import { ErrorPageBody } from '../error'; import { withMetricPageProviders } from './page_providers'; import { useMetadata } from '../../containers/metadata/use_metadata'; import { Source } from '../../containers/source'; import { InfraLoadingPanel } from '../../components/loading'; -import { NodeDetails } from '../../components/metrics/node_details'; +import { NodeDetails } from './components/node_details'; import { findInventoryModel } from '../../../common/inventory_models'; -import { InventoryDetailSection } from '../../../common/inventory_models/types'; +import { PageError } from './components/page_error'; +import { NavItem, SideNavContext } from './lib/side_nav_context'; +import { PageBody } from './components/page_body'; const DetailPageContent = euiStyled(PageContent)` overflow: auto; @@ -72,12 +66,25 @@ export const MetricDetail = withMetricPageProviders( const layoutCreator = inventoryModel.layout; const { sourceId } = useContext(Source.Context); const layouts = layoutCreator(theme); - const { name, filteredLayouts, loading: metadataLoading, cloudId, metadata } = useMetadata( - nodeId, - nodeType, - layouts, - sourceId + const { + name, + filteredRequiredMetrics, + loading: metadataLoading, + cloudId, + metadata, + } = useMetadata(nodeId, nodeType, layouts, inventoryModel.requiredMetrics, sourceId); + + const [sideNav, setSideNav] = useState([]); + + const addNavItem = React.useCallback( + (item: NavItem) => { + if (!sideNav.some(n => n.id === item.id)) { + setSideNav([item, ...sideNav]); + } + }, + [sideNav] ); + const breadcrumbs = [ { href: '#/', @@ -88,18 +95,7 @@ export const MetricDetail = withMetricPageProviders( { text: name }, ]; - const handleClick = useCallback( - (section: InventoryDetailSection) => () => { - const id = section.linkToId || section.id; - const el = document.getElementById(id); - if (el) { - el.scrollIntoView(); - } - }, - [] - ); - - if (metadataLoading && !filteredLayouts.length) { + if (metadataLoading && !filteredRequiredMetrics.length) { return ( {({ metrics, error, loading, refetch }) => { if (error) { - const invalidNodeError = error.graphQLErrors.some( - (err: GraphQLFormattedError) => - err.code === InfraMetricsErrorCodes.invalid_node - ); - - return ( - <> - - i18n.translate('xpack.infra.metricDetailPage.documentTitleError', { - defaultMessage: '{previousTitle} | Uh oh', - values: { - previousTitle, - }, - }) - } - /> - {invalidNodeError ? ( - - ) : ( - - )} - - ); + return ; } return ( - + {({ measureRef, bounds: { width = 0 } }) => { const w = width ? `${width}px` : `100%`; @@ -209,19 +177,19 @@ export const MetricDetail = withMetricPageProviders( - 0 && isAutoReloading ? false : loading - } - refetch={refetch} - onChangeRangeTime={setTimeRange} - isLiveStreaming={isAutoReloading} - stopLiveStreaming={() => setAutoReload(false)} - /> + + 0 && isAutoReloading ? false : loading + } + refetch={refetch} + type={nodeType} + metrics={metrics} + onChangeRangeTime={setTimeRange} + isLiveStreaming={isAutoReloading} + stopLiveStreaming={() => setAutoReload(false)} + /> + diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/lib/side_nav_context.ts b/x-pack/legacy/plugins/infra/public/pages/metrics/lib/side_nav_context.ts new file mode 100644 index 0000000000000..3afd91ef59e93 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/lib/side_nav_context.ts @@ -0,0 +1,24 @@ +/* + * 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'; + +export interface SubNavItem { + id: string; + name: string; + onClick: () => void; +} + +export interface NavItem { + id: string | number; + name: string; + items: SubNavItem[]; +} + +export const SideNavContext = React.createContext({ + items: [] as NavItem[], + addNavItem: (item: NavItem) => {}, +}); diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/page_providers.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/page_providers.tsx index 5e43e79ab7c89..0abbd597dd65c 100644 --- a/x-pack/legacy/plugins/infra/public/pages/metrics/page_providers.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/page_providers.tsx @@ -6,7 +6,7 @@ import React from 'react'; -import { MetricsTimeContainer } from '../../containers/metrics/with_metrics_time'; +import { MetricsTimeContainer } from './containers/with_metrics_time'; import { Source } from '../../containers/source'; export const withMetricPageProviders = (Component: React.ComponentType) => ( diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/types.ts b/x-pack/legacy/plugins/infra/public/pages/metrics/types.ts new file mode 100644 index 0000000000000..e752164796150 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/types.ts @@ -0,0 +1,62 @@ +/* + * 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 rt from 'io-ts'; +import { EuiTheme } from '../../../../../common/eui_styled_components'; +import { InfraMetricData } from '../../graphql/types'; +import { InventoryFormatterTypeRT } from '../../../common/inventory_models/types'; +import { MetricsTimeInput } from './containers/with_metrics_time'; + +export interface LayoutProps { + metrics?: InfraMetricData[]; + onChangeRangeTime?: (time: MetricsTimeInput) => void; + isLiveStreaming?: boolean; + stopLiveStreaming?: () => void; +} + +export type LayoutPropsWithTheme = LayoutProps & { theme: EuiTheme }; + +const ChartTypesRT = rt.keyof({ + area: null, + bar: null, + line: null, +}); + +export const SeriesOverridesObjectRT = rt.intersection([ + rt.type({ + color: rt.string, + }), + rt.partial({ + name: rt.string, + formatter: InventoryFormatterTypeRT, + formatterTemplate: rt.string, + gaugeMax: rt.number, + type: ChartTypesRT, + }), +]); + +export const SeriesOverridesRT = rt.record( + rt.string, + rt.union([rt.undefined, SeriesOverridesObjectRT]) +); + +export type SeriesOverrides = rt.TypeOf; + +export const VisSectionPropsRT = rt.partial({ + type: ChartTypesRT, + stacked: rt.boolean, + formatter: InventoryFormatterTypeRT, + formatterTemplate: rt.string, + seriesOverrides: SeriesOverridesRT, +}); + +export type VisSectionProps = rt.TypeOf & { + id?: string; + metric?: InfraMetricData; + onChangeRangeTime?: (time: MetricsTimeInput) => void; + isLiveStreaming?: boolean; + stopLiveStreaming?: () => void; +}; diff --git a/x-pack/legacy/plugins/infra/public/utils/formatters/index.ts b/x-pack/legacy/plugins/infra/public/utils/formatters/index.ts index 4006e672d8b74..efb20e71a9ce4 100644 --- a/x-pack/legacy/plugins/infra/public/utils/formatters/index.ts +++ b/x-pack/legacy/plugins/infra/public/utils/formatters/index.ts @@ -5,26 +5,25 @@ */ import Mustache from 'mustache'; -import { InfraFormatterType, InfraWaffleMapDataFormat } from '../../lib/lib'; +import { InfraWaffleMapDataFormat } from '../../lib/lib'; import { createBytesFormatter } from './bytes'; import { formatNumber } from './number'; import { formatPercent } from './percent'; +import { InventoryFormatterType } from '../../../common/inventory_models/types'; export const FORMATTERS = { - [InfraFormatterType.number]: formatNumber, + number: formatNumber, // Because the implimentation for formatting large numbers is the same as formatting // bytes we are re-using the same code, we just format the number using the abbreviated number format. - [InfraFormatterType.abbreviatedNumber]: createBytesFormatter( - InfraWaffleMapDataFormat.abbreviatedNumber - ), + abbreviatedNumber: createBytesFormatter(InfraWaffleMapDataFormat.abbreviatedNumber), // bytes in bytes formatted string out - [InfraFormatterType.bytes]: createBytesFormatter(InfraWaffleMapDataFormat.bytesDecimal), + bytes: createBytesFormatter(InfraWaffleMapDataFormat.bytesDecimal), // bytes in bits formatted string out - [InfraFormatterType.bits]: createBytesFormatter(InfraWaffleMapDataFormat.bitsDecimal), - [InfraFormatterType.percent]: formatPercent, + bits: createBytesFormatter(InfraWaffleMapDataFormat.bitsDecimal), + percent: formatPercent, }; -export const createFormatter = (format: InfraFormatterType, template: string = '{{value}}') => ( +export const createFormatter = (format: InventoryFormatterType, template: string = '{{value}}') => ( val: string | number ) => { if (val == null) { From 3fcd27a13f1c90900fdab01ee071cf4814446e2f Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Mon, 28 Oct 2019 16:24:35 -0700 Subject: [PATCH 2/9] Renaming layout files; Fixing some types; Removing unused types --- .../inventory_models/container/index.ts | 2 - .../inventory_models/container/layout.ts | 226 ----------- .../container/{layout.v2.tsx => layout.tsx} | 0 .../common/inventory_models/host/index.ts | 2 - .../common/inventory_models/host/layout.ts | 364 ------------------ .../host/{layout.v2.tsx => layout.tsx} | 4 +- .../infra/common/inventory_models/layouts.ts | 6 +- .../common/inventory_models/pod/index.ts | 2 - .../common/inventory_models/pod/layout.ts | 153 -------- .../pod/{layout.v2.tsx => layout.tsx} | 2 +- .../inventory_models/shared/layouts/aws.ts | 240 ------------ .../shared/layouts/{aws.v2.tsx => aws.tsx} | 0 .../inventory_models/shared/layouts/nginx.ts | 102 ----- .../layouts/{nginx.v2.tsx => nginx.tsx} | 0 .../shared/metrics/required_metrics.ts | 6 +- .../infra/common/inventory_models/types.ts | 95 ++--- .../metadata/lib/get_filtered_layouts.ts | 38 -- .../containers/metadata/use_metadata.ts | 5 +- .../infra/public/pages/metrics/index.tsx | 4 +- 19 files changed, 52 insertions(+), 1199 deletions(-) delete mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/container/layout.ts rename x-pack/legacy/plugins/infra/common/inventory_models/container/{layout.v2.tsx => layout.tsx} (100%) delete mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/host/layout.ts rename x-pack/legacy/plugins/infra/common/inventory_models/host/{layout.v2.tsx => layout.tsx} (99%) delete mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/pod/layout.ts rename x-pack/legacy/plugins/infra/common/inventory_models/pod/{layout.v2.tsx => layout.tsx} (98%) delete mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/aws.ts rename x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/{aws.v2.tsx => aws.tsx} (100%) delete mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/nginx.ts rename x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/{nginx.v2.tsx => nginx.tsx} (100%) delete mode 100644 x-pack/legacy/plugins/infra/public/containers/metadata/lib/get_filtered_layouts.ts diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts index 63d13696cf041..54fe938528d19 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/container/index.ts @@ -4,14 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { layout } from './layout'; import { metrics } from './metrics'; import { InventoryModel } from '../types'; export const container: InventoryModel = { id: 'container', requiredModules: ['docker'], - layout, metrics, requiredMetrics: [ 'containerOverview', diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/container/layout.ts b/x-pack/legacy/plugins/infra/common/inventory_models/container/layout.ts deleted file mode 100644 index 821e180cda016..0000000000000 --- a/x-pack/legacy/plugins/infra/common/inventory_models/container/layout.ts +++ /dev/null @@ -1,226 +0,0 @@ -/* - * 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 { i18n } from '@kbn/i18n'; -import { InventoryDetailLayoutCreator } from '../types'; -import { nginxLayoutCreator } from '../shared/layouts/nginx'; - -export const layout: InventoryDetailLayoutCreator = theme => [ - { - id: 'containerOverview', - label: i18n.translate('xpack.infra.metricDetailPage.containerMetricsLayout.layoutLabel', { - defaultMessage: 'Container', - }), - sections: [ - { - id: 'containerOverview', - label: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.overviewSection.sectionLabel', - { - defaultMessage: 'Overview', - } - ), - requires: ['docker.cpu', 'docker.memory', 'docker.network'], - type: 'gauges', - visConfig: { - seriesOverrides: { - cpu: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.overviewSection.cpuUsageSeriesLabel', - { - defaultMessage: 'CPU Usage', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'percent', - gaugeMax: 1, - }, - memory: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.overviewSection.memoryUsageSeriesLabel', - { - defaultMessage: 'Memory Usage', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'percent', - gaugeMax: 1, - }, - rx: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.overviewSection.inboundRXSeriesLabel', - { - defaultMessage: 'Inbound (RX)', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'bits', - formatterTemplate: '{{value}}/s', - }, - tx: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.overviewSection.outboundTXSeriesLabel', - { - defaultMessage: 'Outbound (TX)', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'bits', - formatterTemplate: '{{value}}/s', - }, - }, - }, - }, - { - id: 'containerCpuUsage', - label: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.cpuUsageSection.sectionLabel', - { - defaultMessage: 'CPU Usage', - } - ), - requires: ['docker.cpu'], - type: 'chart', - visConfig: { - stacked: true, - type: 'area', - formatter: 'percent', - seriesOverrides: { - cpu: { color: theme.eui.euiColorVis1 }, - }, - }, - }, - { - id: 'containerMemory', - label: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.memoryUsageSection.sectionLabel', - { - defaultMessage: 'Memory Usage', - } - ), - requires: ['docker.memory'], - type: 'chart', - visConfig: { - stacked: true, - type: 'area', - formatter: 'percent', - seriesOverrides: { - memory: { color: theme.eui.euiColorVis1 }, - }, - }, - }, - { - id: 'containerNetworkTraffic', - label: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.networkTrafficSection.sectionLabel', - { - defaultMessage: 'Network Traffic', - } - ), - requires: ['docker.network'], - type: 'chart', - visConfig: { - formatter: 'bits', - formatterTemplate: '{{value}}/s', - type: 'area', - seriesOverrides: { - rx: { - color: theme.eui.euiColorVis1, - name: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.networkTrafficSection.networkRxRateSeriesLabel', - { - defaultMessage: 'in', - } - ), - }, - tx: { - color: theme.eui.euiColorVis2, - name: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.networkTrafficSection.networkTxRateSeriesLabel', - { - defaultMessage: 'out', - } - ), - }, - }, - }, - }, - { - id: 'containerDiskIOOps', - label: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.diskIoOpsSection.sectionLabel', - { - defaultMessage: 'Disk IO (Ops)', - } - ), - requires: ['docker.diskio'], - type: 'chart', - visConfig: { - formatter: 'number', - formatterTemplate: '{{value}}/s', - type: 'area', - seriesOverrides: { - read: { - color: theme.eui.euiColorVis1, - name: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.diskIoOpsSection.readRateSeriesLabel', - { - defaultMessage: 'reads', - } - ), - }, - write: { - color: theme.eui.euiColorVis2, - name: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.diskIoOpsSection.writeRateSeriesLabel', - { - defaultMessage: 'writes', - } - ), - }, - }, - }, - }, - { - id: 'containerDiskIOBytes', - label: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.diskIoBytesSection.sectionLabel', - { - defaultMessage: 'Disk IO (Bytes)', - } - ), - requires: ['docker.diskio'], - type: 'chart', - visConfig: { - formatter: 'bytes', - formatterTemplate: '{{value}}/s', - type: 'area', - seriesOverrides: { - read: { - color: theme.eui.euiColorVis1, - name: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.diskIoBytesSection.readRateSeriesLabel', - { - defaultMessage: 'reads', - } - ), - }, - write: { - color: theme.eui.euiColorVis2, - name: i18n.translate( - 'xpack.infra.metricDetailPage.containerMetricsLayout.diskIoBytesSection.writeRateSeriesLabel', - { - defaultMessage: 'writes', - } - ), - }, - }, - }, - }, - ], - }, - ...nginxLayoutCreator(theme), -]; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/container/layout.v2.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/container/layout.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/common/inventory_models/container/layout.v2.tsx rename to x-pack/legacy/plugins/infra/common/inventory_models/container/layout.tsx diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts index e69535e9d0f7d..08056e650a32e 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/host/index.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { layout } from './layout'; import { metrics } from './metrics'; import { InventoryModel } from '../types'; import { @@ -15,7 +14,6 @@ import { export const host: InventoryModel = { id: 'host', requiredModules: ['system'], - layout, metrics, requiredMetrics: [ 'hostSystemOverview', diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/host/layout.ts b/x-pack/legacy/plugins/infra/common/inventory_models/host/layout.ts deleted file mode 100644 index 2ac12387e26a4..0000000000000 --- a/x-pack/legacy/plugins/infra/common/inventory_models/host/layout.ts +++ /dev/null @@ -1,364 +0,0 @@ -/* - * 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 { i18n } from '@kbn/i18n'; -import { InventoryDetailLayoutCreator } from '../types'; - -import { nginxLayoutCreator } from '../shared/layouts/nginx'; -import { awsLayoutCreator } from '../shared/layouts/aws'; - -export const layout: InventoryDetailLayoutCreator = theme => [ - { - id: 'hostOverview', - label: i18n.translate('xpack.infra.metricDetailPage.hostMetricsLayout.layoutLabel', { - defaultMessage: 'Host', - }), - sections: [ - { - id: 'hostSystemOverview', - linkToId: 'hostOverview', - label: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.overviewSection.sectionLabel', - { - defaultMessage: 'Overview', - } - ), - requires: ['system.cpu', 'system.load', 'system.memory', 'system.network'], - type: 'gauges', - visConfig: { - seriesOverrides: { - cpu: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.overviewSection.cpuUsageSeriesLabel', - { - defaultMessage: 'CPU Usage', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'percent', - gaugeMax: 1, - }, - load: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.overviewSection.loadSeriesLabel', - { - defaultMessage: 'Load (5m)', - } - ), - color: theme.eui.euiColorFullShade, - }, - memory: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.overviewSection.memoryCapacitySeriesLabel', - { - defaultMessage: 'Memory Usage', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'percent', - gaugeMax: 1, - }, - rx: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.overviewSection.inboundRXSeriesLabel', - { - defaultMessage: 'Inbound (RX)', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'bits', - formatterTemplate: '{{value}}/s', - }, - tx: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.overviewSection.outboundTXSeriesLabel', - { - defaultMessage: 'Outbound (TX)', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'bits', - formatterTemplate: '{{value}}/s', - }, - }, - }, - }, - { - id: 'hostCpuUsage', - label: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.cpuUsageSection.sectionLabel', - { - defaultMessage: 'CPU Usage', - } - ), - requires: ['system.cpu'], - type: 'chart', - visConfig: { - stacked: true, - type: 'area', - formatter: 'percent', - seriesOverrides: { - user: { color: theme.eui.euiColorVis0 }, - system: { color: theme.eui.euiColorVis2 }, - steal: { color: theme.eui.euiColorVis9 }, - irq: { color: theme.eui.euiColorVis4 }, - softirq: { color: theme.eui.euiColorVis6 }, - iowait: { color: theme.eui.euiColorVis7 }, - nice: { color: theme.eui.euiColorVis5 }, - }, - }, - }, - { - id: 'hostLoad', - label: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.loadSection.sectionLabel', - { - defaultMessage: 'Load', - } - ), - requires: ['system.load'], - type: 'chart', - visConfig: { - seriesOverrides: { - load_1m: { - color: theme.eui.euiColorVis0, - name: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.loadSection.oneMinuteSeriesLabel', - { - defaultMessage: '1m', - } - ), - }, - load_5m: { - color: theme.eui.euiColorVis1, - name: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.loadSection.fiveMinuteSeriesLabel', - { - defaultMessage: '5m', - } - ), - }, - load_15m: { - color: theme.eui.euiColorVis3, - name: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.loadSection.fifteenMinuteSeriesLabel', - { - defaultMessage: '15m', - } - ), - }, - }, - }, - }, - { - id: 'hostMemoryUsage', - label: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.memoryUsageSection.sectionLabel', - { - defaultMessage: 'Memory Usage', - } - ), - requires: ['system.memory'], - type: 'chart', - visConfig: { - stacked: true, - formatter: 'bytes', - type: 'area', - seriesOverrides: { - used: { color: theme.eui.euiColorVis2 }, - free: { color: theme.eui.euiColorVis0 }, - cache: { color: theme.eui.euiColorVis1 }, - }, - }, - }, - { - id: 'hostNetworkTraffic', - label: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.networkTrafficSection.sectionLabel', - { - defaultMessage: 'Network Traffic', - } - ), - requires: ['system.network'], - type: 'chart', - visConfig: { - formatter: 'bits', - formatterTemplate: '{{value}}/s', - type: 'area', - seriesOverrides: { - rx: { - color: theme.eui.euiColorVis1, - name: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.networkTrafficSection.networkRxRateSeriesLabel', - { - defaultMessage: 'in', - } - ), - }, - tx: { - color: theme.eui.euiColorVis2, - name: i18n.translate( - 'xpack.infra.metricDetailPage.hostMetricsLayout.networkTrafficSection.networkTxRateSeriesLabel', - { - defaultMessage: 'out', - } - ), - }, - }, - }, - }, - ], - }, - { - id: 'k8sOverview', - label: 'Kubernetes', - sections: [ - { - id: 'hostK8sOverview', - linkToId: 'k8sOverview', - label: i18n.translate( - 'xpack.infra.metricDetailPage.kubernetesMetricsLayout.overviewSection.sectionLabel', - { - defaultMessage: 'Overview', - } - ), - requires: ['kubernetes.node'], - type: 'gauges', - visConfig: { - seriesOverrides: { - cpucap: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.kubernetesMetricsLayout.overviewSection.cpuUsageSeriesLabel', - { - defaultMessage: 'CPU Capacity', - } - ), - color: 'secondary', - formatter: 'percent', - gaugeMax: 1, - }, - load: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.kubernetesMetricsLayout.overviewSection.loadSeriesLabel', - { - defaultMessage: 'Load (5m)', - } - ), - color: 'secondary', - }, - memorycap: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.kubernetesMetricsLayout.overviewSection.memoryUsageSeriesLabel', - { - defaultMessage: 'Memory Capacity', - } - ), - color: 'secondary', - formatter: 'percent', - gaugeMax: 1, - }, - podcap: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.kubernetesMetricsLayout.overviewSection.podCapacitySeriesLabel', - { - defaultMessage: 'Pod Capacity', - } - ), - color: 'secondary', - formatter: 'percent', - gaugeMax: 1, - }, - diskcap: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.kubernetesMetricsLayout.overviewSection.diskCapacitySeriesLabel', - { - defaultMessage: 'Disk Capacity', - } - ), - color: 'secondary', - formatter: 'percent', - gaugeMax: 1, - }, - }, - }, - }, - { - id: 'hostK8sCpuCap', - label: i18n.translate( - 'xpack.infra.metricDetailPage.kubernetesMetricsLayout.nodeCpuCapacitySection.sectionLabel', - { - defaultMessage: 'Node CPU Capacity', - } - ), - requires: ['kubernetes.node'], - type: 'chart', - visConfig: { - formatter: 'abbreviatedNumber', - seriesOverrides: { - capacity: { color: theme.eui.euiColorVis2 }, - used: { color: theme.eui.euiColorVis1, type: 'area' }, - }, - }, - }, - { - id: 'hostK8sMemoryCap', - label: i18n.translate( - 'xpack.infra.metricDetailPage.kubernetesMetricsLayout.nodeMemoryCapacitySection.sectionLabel', - { - defaultMessage: 'Node Memory Capacity', - } - ), - requires: ['kubernetes.node'], - type: 'chart', - visConfig: { - formatter: 'bytes', - seriesOverrides: { - capacity: { color: theme.eui.euiColorVis2 }, - used: { color: theme.eui.euiColorVis1, type: 'area' }, - }, - }, - }, - { - id: 'hostK8sDiskCap', - label: i18n.translate( - 'xpack.infra.metricDetailPage.kubernetesMetricsLayout.nodeDiskCapacitySection.sectionLabel', - { - defaultMessage: 'Node Disk Capacity', - } - ), - requires: ['kubernetes.node'], - type: 'chart', - visConfig: { - formatter: 'bytes', - seriesOverrides: { - capacity: { color: theme.eui.euiColorVis2 }, - used: { color: theme.eui.euiColorVis1, type: 'area' }, - }, - }, - }, - { - id: 'hostK8sPodCap', - label: i18n.translate( - 'xpack.infra.metricDetailPage.kubernetesMetricsLayout.nodePodCapacitySection.sectionLabel', - { - defaultMessage: 'Node Pod Capacity', - } - ), - requires: ['kubernetes.node'], - type: 'chart', - visConfig: { - formatter: 'number', - seriesOverrides: { - capacity: { color: theme.eui.euiColorVis2 }, - used: { color: theme.eui.euiColorVis1, type: 'area' }, - }, - }, - }, - ], - }, - ...nginxLayoutCreator(theme), - ...awsLayoutCreator(theme), -]; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/host/layout.v2.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/host/layout.tsx similarity index 99% rename from x-pack/legacy/plugins/infra/common/inventory_models/host/layout.v2.tsx rename to x-pack/legacy/plugins/infra/common/inventory_models/host/layout.tsx index b7dcc29b19d3d..b22fd9d6f61dd 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/host/layout.v2.tsx +++ b/x-pack/legacy/plugins/infra/common/inventory_models/host/layout.tsx @@ -11,8 +11,8 @@ import { SubSection } from '../../../public/pages/metrics/components/sub_section import { GaugesSectionVis } from '../../../public/pages/metrics/components/gauges_section_vis'; import { ChartSectionVis } from '../../../public/pages/metrics/components/chart_section_vis'; import { withTheme } from '../../../../../common/eui_styled_components'; -import * as AWS from '../shared/layouts/aws.v2'; -import * as Ngnix from '../shared/layouts/nginx.v2'; +import * as AWS from '../shared/layouts/aws'; +import * as Ngnix from '../shared/layouts/nginx'; export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts b/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts index f69a30e51c3d6..fa80659e1f4b0 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts @@ -15,9 +15,9 @@ import { idx } from '@kbn/elastic-idx'; import { i18n } from '@kbn/i18n'; import { ReactNode, FunctionComponent } from 'react'; -import { Layout as HostLayout } from './host/layout.v2'; -import { Layout as PodLayout } from './pod/layout.v2'; -import { Layout as ContainerLayout } from './container/layout.v2'; +import { Layout as HostLayout } from './host/layout'; +import { Layout as PodLayout } from './pod/layout'; +import { Layout as ContainerLayout } from './container/layout'; import { InventoryItemType } from './types'; import { LayoutProps } from '../../public/pages/metrics/types'; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts index a3d619b08eb05..66ace03abac00 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/pod/index.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { layout } from './layout'; import { metrics } from './metrics'; import { InventoryModel } from '../types'; import { nginx as nginxRequiredMetrics } from '../shared/metrics/required_metrics'; @@ -12,7 +11,6 @@ import { nginx as nginxRequiredMetrics } from '../shared/metrics/required_metric export const pod: InventoryModel = { id: 'pod', requiredModules: ['kubernetes'], - layout, metrics, requiredMetrics: [ 'podOverview', diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/pod/layout.ts b/x-pack/legacy/plugins/infra/common/inventory_models/pod/layout.ts deleted file mode 100644 index ffb78894d63f6..0000000000000 --- a/x-pack/legacy/plugins/infra/common/inventory_models/pod/layout.ts +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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 { i18n } from '@kbn/i18n'; -import { InventoryDetailLayoutCreator } from '../types'; -import { nginxLayoutCreator } from '../shared/layouts/nginx'; - -export const layout: InventoryDetailLayoutCreator = theme => [ - { - id: 'podOverview', - label: i18n.translate('xpack.infra.metricDetailPage.podMetricsLayout.layoutLabel', { - defaultMessage: 'Pod', - }), - sections: [ - { - id: 'podOverview', - label: i18n.translate( - 'xpack.infra.metricDetailPage.podMetricsLayout.overviewSection.sectionLabel', - { - defaultMessage: 'Overview', - } - ), - requires: ['kubernetes.pod'], - type: 'gauges', - visConfig: { - seriesOverrides: { - cpu: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.podMetricsLayout.overviewSection.cpuUsageSeriesLabel', - { - defaultMessage: 'CPU Usage', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'percent', - gaugeMax: 1, - }, - memory: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.podMetricsLayout.overviewSection.memoryUsageSeriesLabel', - { - defaultMessage: 'Memory Usage', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'percent', - gaugeMax: 1, - }, - rx: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.podMetricsLayout.overviewSection.inboundRXSeriesLabel', - { - defaultMessage: 'Inbound (RX)', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'bits', - formatterTemplate: '{{value}}/s', - }, - tx: { - name: i18n.translate( - 'xpack.infra.metricDetailPage.podMetricsLayout.overviewSection.outboundTXSeriesLabel', - { - defaultMessage: 'Outbound (TX)', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'bits', - formatterTemplate: '{{value}}/s', - }, - }, - }, - }, - { - id: 'podCpuUsage', - label: i18n.translate( - 'xpack.infra.metricDetailPage.podMetricsLayout.cpuUsageSection.sectionLabel', - { - defaultMessage: 'CPU Usage', - } - ), - requires: ['kubernetes.pod'], - type: 'chart', - visConfig: { - formatter: 'percent', - seriesOverrides: { - cpu: { color: theme.eui.euiColorVis1, type: 'area' }, - }, - }, - }, - { - id: 'podMemoryUsage', - label: i18n.translate( - 'xpack.infra.metricDetailPage.podMetricsLayout.memoryUsageSection.sectionLabel', - { - defaultMessage: 'Memory Usage', - } - ), - requires: ['kubernetes.pod'], - type: 'chart', - visConfig: { - formatter: 'percent', - seriesOverrides: { - memory: { - color: theme.eui.euiColorVis1, - type: 'area', - }, - }, - }, - }, - { - id: 'podNetworkTraffic', - label: i18n.translate( - 'xpack.infra.metricDetailPage.podMetricsLayout.networkTrafficSection.sectionLabel', - { - defaultMessage: 'Network Traffic', - } - ), - requires: ['kubernetes.pod'], - type: 'chart', - visConfig: { - formatter: 'bits', - formatterTemplate: '{{value}}/s', - type: 'area', - seriesOverrides: { - rx: { - color: theme.eui.euiColorVis1, - name: i18n.translate( - 'xpack.infra.metricDetailPage.podMetricsLayout.networkTrafficSection.networkRxRateSeriesLabel', - { - defaultMessage: 'in', - } - ), - }, - tx: { - color: theme.eui.euiColorVis2, - name: i18n.translate( - 'xpack.infra.metricDetailPage.podMetricsLayout.networkTrafficSection.networkTxRateSeriesLabel', - { - defaultMessage: 'out', - } - ), - }, - }, - }, - }, - ], - }, - ...nginxLayoutCreator(theme), -]; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/pod/layout.v2.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/pod/layout.tsx similarity index 98% rename from x-pack/legacy/plugins/infra/common/inventory_models/pod/layout.v2.tsx rename to x-pack/legacy/plugins/infra/common/inventory_models/pod/layout.tsx index 3afcf9488f216..401e25c4defb8 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/pod/layout.v2.tsx +++ b/x-pack/legacy/plugins/infra/common/inventory_models/pod/layout.tsx @@ -11,7 +11,7 @@ import { SubSection } from '../../../public/pages/metrics/components/sub_section import { GaugesSectionVis } from '../../../public/pages/metrics/components/gauges_section_vis'; import { ChartSectionVis } from '../../../public/pages/metrics/components/chart_section_vis'; import { withTheme } from '../../../../../common/eui_styled_components'; -import * as Nginx from '../shared/layouts/nginx.v2'; +import * as Nginx from '../shared/layouts/nginx'; export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/aws.ts b/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/aws.ts deleted file mode 100644 index 7c7c009df6f27..0000000000000 --- a/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/aws.ts +++ /dev/null @@ -1,240 +0,0 @@ -/* - * 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 { i18n } from '@kbn/i18n'; -import { InventoryDetailLayoutCreator } from '../../types'; - -export const awsLayoutCreator: InventoryDetailLayoutCreator = theme => [ - { - id: 'awsOverview', - label: 'AWS', - sections: [ - { - id: 'awsOverview', - linkToId: 'awsOverview', - label: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.overviewSection.sectionLabel', - { - defaultMessage: 'Overview', - } - ), - requires: ['aws.ec2'], - type: 'gauges', - visConfig: { - seriesOverrides: { - 'cpu-util': { - name: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.overviewSection.cpuUtilizationSeriesLabel', - { - defaultMessage: 'CPU Utilization', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'percent', - gaugeMax: 1, - }, - 'status-check-failed': { - name: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.overviewSection.statusCheckFailedLabel', - { - defaultMessage: 'Status check failed', - } - ), - color: theme.eui.euiColorFullShade, - }, - 'packets-in': { - name: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.overviewSection.networkPacketsInLabel', - { - defaultMessage: 'Packets (in)', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'number', - }, - 'packets-out': { - name: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.overviewSection.networkPacketsOutLabel', - { - defaultMessage: 'Packets (out)', - } - ), - color: theme.eui.euiColorFullShade, - formatter: 'number', - }, - }, - }, - }, - { - id: 'awsCpuUtilization', - label: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.cpuUtilSection.sectionLabel', - { - defaultMessage: 'CPU Utilization', - } - ), - requires: ['aws.ec2'], - type: 'chart', - visConfig: { - type: 'area', - formatter: 'number', - seriesOverrides: { - 'cpu-util': { - color: theme.eui.euiColorVis1, - name: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.cpuUtilSection.percentSeriesLabel', - { - defaultMessage: 'percent', - } - ), - }, - }, - }, - }, - { - id: 'awsNetworkBytes', - label: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.networkBytesSection.sectionLabel', - { - defaultMessage: 'Network Traffic', - } - ), - requires: ['aws.ec2'], - type: 'chart', - visConfig: { - type: 'area', - formatter: 'bits', - formatterTemplate: '{{value}}/s', - seriesOverrides: { - tx: { - color: theme.eui.euiColorVis1, - name: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.networkBytesSection.txSeriesLabel', - { - defaultMessage: 'out', - } - ), - }, - rx: { - color: theme.eui.euiColorVis2, - name: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.networkBytesSection.rxSeriesLabel', - { - defaultMessage: 'in', - } - ), - }, - }, - }, - }, - { - id: 'awsNetworkPackets', - label: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.networkPacketsSection.sectionLabel', - { - defaultMessage: 'Network Packets (Average)', - } - ), - requires: ['aws.ec2'], - type: 'chart', - visConfig: { - type: 'area', - formatter: 'number', - seriesOverrides: { - 'packets-out': { - color: theme.eui.euiColorVis1, - name: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.networkPacketsSection.packetsOutSeriesLabel', - { - defaultMessage: 'out', - } - ), - }, - 'packets-in': { - color: theme.eui.euiColorVis2, - name: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.networkPacketsSection.packetsInSeriesLabel', - { - defaultMessage: 'in', - } - ), - }, - }, - }, - }, - { - id: 'awsDiskioOps', - label: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.diskioOperationsSection.sectionLabel', - { - defaultMessage: 'Disk I/O Operations', - } - ), - requires: ['aws.ec2'], - type: 'chart', - visConfig: { - type: 'area', - formatter: 'number', - seriesOverrides: { - writes: { - color: theme.eui.euiColorVis1, - name: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.diskioOperationsSection.writesSeriesLabel', - { - defaultMessage: 'writes', - } - ), - }, - reads: { - color: theme.eui.euiColorVis2, - name: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.diskioOperationsSection.readsSeriesLabel', - { - defaultMessage: 'reads', - } - ), - }, - }, - }, - }, - { - id: 'awsDiskioBytes', - label: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.diskioBytesSection.sectionLabel', - { - defaultMessage: 'Disk I/O Bytes', - } - ), - requires: ['aws.ec2'], - type: 'chart', - visConfig: { - type: 'area', - formatter: 'number', - seriesOverrides: { - writes: { - color: theme.eui.euiColorVis1, - name: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.diskioBytesSection.writesSeriesLabel', - { - defaultMessage: 'writes', - } - ), - }, - reads: { - color: theme.eui.euiColorVis2, - name: i18n.translate( - 'xpack.infra.metricDetailPage.awsMetricsLayout.diskioBytesSection.readsSeriesLabel', - { - defaultMessage: 'reads', - } - ), - }, - }, - }, - }, - ], - }, -]; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/aws.v2.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/aws.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/aws.v2.tsx rename to x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/aws.tsx diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/nginx.ts b/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/nginx.ts deleted file mode 100644 index 2d895c3b83a0b..0000000000000 --- a/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/nginx.ts +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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 { i18n } from '@kbn/i18n'; -import { InventoryDetailLayoutCreator } from '../../types'; - -export const nginxLayoutCreator: InventoryDetailLayoutCreator = theme => [ - { - id: 'nginxOverview', - label: 'Nginx', - sections: [ - { - id: 'nginxHits', - label: i18n.translate( - 'xpack.infra.metricDetailPage.nginxMetricsLayout.hitsSection.sectionLabel', - { - defaultMessage: 'Hits', - } - ), - requires: ['nginx.access'], - type: 'chart', - visConfig: { - formatter: 'abbreviatedNumber', - stacked: true, - seriesOverrides: { - '200s': { color: theme.eui.euiColorVis1, type: 'bar' }, - '300s': { color: theme.eui.euiColorVis5, type: 'bar' }, - '400s': { color: theme.eui.euiColorVis2, type: 'bar' }, - '500s': { color: theme.eui.euiColorVis9, type: 'bar' }, - }, - }, - }, - { - id: 'nginxRequestRate', - label: i18n.translate( - 'xpack.infra.metricDetailPage.nginxMetricsLayout.requestRateSection.sectionLabel', - { - defaultMessage: 'Request Rate', - } - ), - requires: ['nginx.stubstatus'], - type: 'chart', - visConfig: { - formatter: 'abbreviatedNumber', - formatterTemplate: '{{value}}/s', - seriesOverrides: { - rate: { color: theme.eui.euiColorVis1, type: 'area' }, - }, - }, - }, - { - id: 'nginxActiveConnections', - label: i18n.translate( - 'xpack.infra.metricDetailPage.nginxMetricsLayout.activeConnectionsSection.sectionLabel', - { - defaultMessage: 'Active Connections', - } - ), - requires: ['nginx.stubstatus'], - type: 'chart', - visConfig: { - formatter: 'abbreviatedNumber', - seriesOverrides: { - connections: { - color: theme.eui.euiColorVis1, - type: 'bar', - }, - }, - }, - }, - { - id: 'nginxRequestsPerConnection', - label: i18n.translate( - 'xpack.infra.metricDetailPage.nginxMetricsLayout.requestsPerConnectionsSection.sectionLabel', - { - defaultMessage: 'Requests per Connections', - } - ), - requires: ['nginx.stubstatus'], - type: 'chart', - visConfig: { - formatter: 'abbreviatedNumber', - seriesOverrides: { - reqPerConns: { - color: theme.eui.euiColorVis1, - type: 'bar', - name: i18n.translate( - 'xpack.infra.metricDetailPage.nginxMetricsLayout.requestsPerConnectionsSection.reqsPerConnSeriesLabel', - { - defaultMessage: 'reqs per conn', - } - ), - }, - }, - }, - }, - ], - }, -]; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/nginx.v2.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/nginx.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/nginx.v2.tsx rename to x-pack/legacy/plugins/infra/common/inventory_models/shared/layouts/nginx.tsx diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/required_metrics.ts b/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/required_metrics.ts index 7bd888ab7c589..0b2623c448646 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/required_metrics.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/required_metrics.ts @@ -4,14 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -export const nginx = [ +import { InventoryMetric } from '../../types'; + +export const nginx: InventoryMetric[] = [ 'nginxHits', 'nginxRequestRate', 'nginxActiveConnections', 'nginxRequestsPerConnection', ]; -export const aws = [ +export const aws: InventoryMetric[] = [ 'awsOverview', 'awsCpuUtilization', 'awsNetworkBytes', diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/types.ts b/x-pack/legacy/plugins/infra/common/inventory_models/types.ts index b1d0e1dcad5cc..e3b6768ed919f 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/types.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/types.ts @@ -5,7 +5,6 @@ */ import * as rt from 'io-ts'; -import { EuiTheme } from '../../../../common/eui_styled_components'; export const ItemTypeRT = rt.keyof({ host: null, @@ -35,60 +34,47 @@ export const InventoryFormatterTypeRT = rt.keyof({ export type InventoryFormatterType = rt.TypeOf; export type InventoryItemType = rt.TypeOf; -export const InventoryMetricRT = rt.string; -export type InventoryMetric = rt.TypeOf; - -export const SeriesOverridesRT = rt.intersection([ - rt.type({ - color: rt.string, - }), - rt.partial({ - type: InventoryVisTypeRT, - name: rt.string, - formatter: InventoryFormatterTypeRT, - formatterTemplate: rt.string, - gaugeMax: rt.number, - }), -]); - -export const VisConfigRT = rt.partial({ - stacked: rt.boolean, - type: InventoryVisTypeRT, - formatter: InventoryFormatterTypeRT, - formatterTemplate: rt.string, - seriesOverrides: rt.record(rt.string, rt.union([rt.undefined, SeriesOverridesRT])), -}); - -export const InventorySectionTypeRT = rt.keyof({ - chart: null, - gauges: null, +export const InventoryMetricRT = rt.keyof({ + hostSystemOverview: null, + hostCpuUsage: null, + hostFilesystem: null, + hostK8sOverview: null, + hostK8sCpuCap: null, + hostK8sDiskCap: null, + hostK8sMemoryCap: null, + hostK8sPodCap: null, + hostLoad: null, + hostMemoryUsage: null, + hostNetworkTraffic: null, + hostDockerOverview: null, + hostDockerInfo: null, + hostDockerTop5ByCpu: null, + hostDockerTop5ByMemory: null, + podOverview: null, + podCpuUsage: null, + podMemoryUsage: null, + podLogUsage: null, + podNetworkTraffic: null, + containerOverview: null, + containerCpuKernel: null, + containerCpuUsage: null, + containerDiskIOOps: null, + containerDiskIOBytes: null, + containerMemory: null, + containerNetworkTraffic: null, + nginxHits: null, + nginxRequestRate: null, + nginxActiveConnections: null, + nginxRequestsPerConnection: null, + awsOverview: null, + awsCpuUtilization: null, + awsNetworkBytes: null, + awsNetworkPackets: null, + awsDiskioBytes: null, + awsDiskioOps: null, + custom: null, }); - -export type InventorySectionType = rt.TypeOf; - -export const SectionRT = rt.intersection([ - rt.type({ - id: InventoryMetricRT, - label: rt.string, - requires: rt.array(rt.string), - visConfig: VisConfigRT, - type: InventorySectionTypeRT, - }), - rt.partial({ - linkToId: rt.string, - }), -]); - -export const InventoryDetailLayoutRT = rt.type({ - id: rt.string, - label: rt.string, - sections: rt.array(SectionRT), -}); - -export type InventoryDetailSection = rt.TypeOf; -export type InventoryDetailLayout = rt.TypeOf; - -export type InventoryDetailLayoutCreator = (theme: EuiTheme) => InventoryDetailLayout[]; +export type InventoryMetric = rt.TypeOf; export const TSVBMetricTypeRT = rt.keyof({ avg: null, @@ -281,7 +267,6 @@ export interface InventoryMetrics { export interface InventoryModel { id: string; requiredModules: string[]; - layout: InventoryDetailLayoutCreator; metrics: InventoryMetrics; requiredMetrics: InventoryMetric[]; } diff --git a/x-pack/legacy/plugins/infra/public/containers/metadata/lib/get_filtered_layouts.ts b/x-pack/legacy/plugins/infra/public/containers/metadata/lib/get_filtered_layouts.ts deleted file mode 100644 index 6c7a9d6dcad38..0000000000000 --- a/x-pack/legacy/plugins/infra/public/containers/metadata/lib/get_filtered_layouts.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 { InfraMetadataFeature } from '../../../../common/http_api/metadata_api'; -import { InventoryDetailLayout } from '../../../../common/inventory_models/types'; - -export const getFilteredLayouts = ( - layouts: InventoryDetailLayout[], - metadata: Array | undefined -): InventoryDetailLayout[] => { - if (!metadata) { - return layouts; - } - - const metricMetadata: Array = metadata - .filter(data => data && data.source === 'metrics') - .map(data => data && data.name); - - // After filtering out sections that can't be displayed, a layout may end up empty and can be removed. - const filteredLayouts = layouts - .map(layout => getFilteredLayout(layout, metricMetadata)) - .filter(layout => layout.sections.length > 0); - return filteredLayouts; -}; - -export const getFilteredLayout = ( - layout: InventoryDetailLayout, - metricMetadata: Array -): InventoryDetailLayout => { - // A section is only displayed if at least one of its requirements is met - // All others are filtered out. - const filteredSections = layout.sections.filter( - section => _.intersection(section.requires, metricMetadata).length > 0 - ); - return { ...layout, sections: filteredSections }; -}; diff --git a/x-pack/legacy/plugins/infra/public/containers/metadata/use_metadata.ts b/x-pack/legacy/plugins/infra/public/containers/metadata/use_metadata.ts index 9db0ef5089a4a..ec84318197ff2 100644 --- a/x-pack/legacy/plugins/infra/public/containers/metadata/use_metadata.ts +++ b/x-pack/legacy/plugins/infra/public/containers/metadata/use_metadata.ts @@ -10,16 +10,14 @@ import { identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; import { InfraNodeType } from '../../graphql/types'; import { InfraMetadata, InfraMetadataRT } from '../../../common/http_api/metadata_api'; -import { getFilteredLayouts } from './lib/get_filtered_layouts'; import { useHTTPRequest } from '../../hooks/use_http_request'; import { throwErrors, createPlainError } from '../../../common/runtime_types'; -import { InventoryDetailLayout, InventoryMetric } from '../../../common/inventory_models/types'; +import { InventoryMetric } from '../../../common/inventory_models/types'; import { getFilteredMetrics } from './lib/get_filtered_metrics'; export function useMetadata( nodeId: string, nodeType: InfraNodeType, - layouts: InventoryDetailLayout[], requiredMetrics: InventoryMetric[], sourceId: string ) { @@ -49,7 +47,6 @@ export function useMetadata( return { name: (response && response.name) || '', - filteredLayouts: (response && getFilteredLayouts(layouts, response.features)) || [], filteredRequiredMetrics: (response && getFilteredMetrics(requiredMetrics, response.features)) || [], error: (error && error.message) || null, diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx index 92865b954bcbb..643d943273a81 100644 --- a/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx @@ -63,16 +63,14 @@ export const MetricDetail = withMetricPageProviders( const nodeId = match.params.node; const nodeType = match.params.type as InfraNodeType; const inventoryModel = findInventoryModel(nodeType); - const layoutCreator = inventoryModel.layout; const { sourceId } = useContext(Source.Context); - const layouts = layoutCreator(theme); const { name, filteredRequiredMetrics, loading: metadataLoading, cloudId, metadata, - } = useMetadata(nodeId, nodeType, layouts, inventoryModel.requiredMetrics, sourceId); + } = useMetadata(nodeId, nodeType, inventoryModel.requiredMetrics, sourceId); const [sideNav, setSideNav] = useState([]); From 50cd9e5a3ed97458dd5d27dc10c38cd24c51ca70 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 29 Oct 2019 13:14:24 -0700 Subject: [PATCH 3/9] Fixing naming issue --- .../plugins/infra/common/inventory_models/host/layout.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/host/layout.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/host/layout.tsx index b22fd9d6f61dd..fee79d8364c42 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/host/layout.tsx +++ b/x-pack/legacy/plugins/infra/common/inventory_models/host/layout.tsx @@ -11,7 +11,7 @@ import { SubSection } from '../../../public/pages/metrics/components/sub_section import { GaugesSectionVis } from '../../../public/pages/metrics/components/gauges_section_vis'; import { ChartSectionVis } from '../../../public/pages/metrics/components/chart_section_vis'; import { withTheme } from '../../../../../common/eui_styled_components'; -import * as AWS from '../shared/layouts/aws'; +import * as Aws from '../shared/layouts/aws'; import * as Ngnix from '../shared/layouts/nginx'; export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( @@ -346,7 +346,7 @@ export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( />
- + )); From 59113ae96b92e76ee8e10df19497f19bb20f675e Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 29 Oct 2019 13:57:51 -0700 Subject: [PATCH 4/9] Fixing path --- x-pack/test/api_integration/apis/infra/metrics.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/api_integration/apis/infra/metrics.ts b/x-pack/test/api_integration/apis/infra/metrics.ts index d40359edc5ff2..00c57bcc45e32 100644 --- a/x-pack/test/api_integration/apis/infra/metrics.ts +++ b/x-pack/test/api_integration/apis/infra/metrics.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { first, last } from 'lodash'; -import { metricsQuery } from '../../../../legacy/plugins/infra/public/containers/metrics/metrics.gql_query'; +import { metricsQuery } from '../../../../legacy/plugins/infra/public/pages/metrics/containers/metrics.gql_query'; import { MetricsQuery } from '../../../../legacy/plugins/infra/public/graphql/types'; import { FtrProviderContext } from '../../ftr_provider_context'; From 9a6a892be1e6db2b40cda01c9c416bc1b097d306 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 29 Oct 2019 16:02:15 -0700 Subject: [PATCH 5/9] Fixing i18n stuff --- x-pack/plugins/translations/translations/ja-JP.json | 1 - x-pack/plugins/translations/translations/zh-CN.json | 1 - 2 files changed, 2 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 39db6ff3791df..f1a21aad9e787 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4943,7 +4943,6 @@ "xpack.infra.metrics.emptyViewTitle": "表示するデータがありません。", "xpack.infra.metrics.invalidNodeErrorDescription": "構成をよく確認してください", "xpack.infra.metrics.invalidNodeErrorTitle": "{nodeName} がメトリックデータを収集していないようです", - "xpack.infra.metrics.layoutLabelOverviewTitle": "{layoutLabel} 概要", "xpack.infra.metrics.loadingNodeDataText": "データを読み込み中", "xpack.infra.metrics.refetchButtonLabel": "新規データを確認", "xpack.infra.metricsExplorer.actionsLabel.aria": "{grouping} のアクション", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 10ffb2b7d731d..c0de053d24604 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4944,7 +4944,6 @@ "xpack.infra.metrics.emptyViewTitle": "没有可显示的数据。", "xpack.infra.metrics.invalidNodeErrorDescription": "反复检查您的配置", "xpack.infra.metrics.invalidNodeErrorTitle": "似乎 {nodeName} 未在收集任何指标数据", - "xpack.infra.metrics.layoutLabelOverviewTitle": "{layoutLabel} 概览", "xpack.infra.metrics.loadingNodeDataText": "正在加载数据", "xpack.infra.metrics.refetchButtonLabel": "检查新数据", "xpack.infra.metricsExplorer.actionsLabel.aria": "适用于 {grouping} 的操作", From 82f3f16f55caa57a478397a77c4f159c64907a3a Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Wed, 30 Oct 2019 13:08:09 -0700 Subject: [PATCH 6/9] [Metrics UI] Move toolbars under inventory models --- .../container/metrics/index.ts | 1 + .../container/toolbar_items.tsx} | 13 ++++--- .../inventory_models/host/metrics/index.ts | 1 + .../inventory_models/host/toolbar_items.tsx} | 13 ++++--- .../infra/common/inventory_models/layouts.ts | 4 +-- .../inventory_models/pod/metrics/index.ts | 1 + .../inventory_models/pod/toolbar_items.tsx} | 13 ++++--- .../inventory_models/shared/metrics/index.ts | 5 +++ .../infra/common/inventory_models/toolbars.ts | 36 +++++++++++++++++++ .../infra/common/inventory_models/types.ts | 16 ++++++++- .../components/inventory/toolbars/toolbar.tsx | 22 ++++-------- .../waffle/waffle_inventory_switcher.tsx | 6 +++- 12 files changed, 96 insertions(+), 35 deletions(-) rename x-pack/legacy/plugins/infra/{public/components/inventory/toolbars/container_toolbar_items.tsx => common/inventory_models/container/toolbar_items.tsx} (76%) rename x-pack/legacy/plugins/infra/{public/components/inventory/toolbars/host_toolbar_items.tsx => common/inventory_models/host/toolbar_items.tsx} (77%) rename x-pack/legacy/plugins/infra/{public/components/inventory/toolbars/pod_toolbar_items.tsx => common/inventory_models/pod/toolbar_items.tsx} (75%) create mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/toolbars.ts diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/container/metrics/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/container/metrics/index.ts index 9cbbb2dca7ffa..9e0153c5d6ea6 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/container/metrics/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/container/metrics/index.ts @@ -29,4 +29,5 @@ export const metrics: InventoryMetrics = { containerMemory, }, snapshot: { cpu, memory, rx, tx }, + defaultSnapshot: 'cpu', }; diff --git a/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/container_toolbar_items.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/container/toolbar_items.tsx similarity index 76% rename from x-pack/legacy/plugins/infra/public/components/inventory/toolbars/container_toolbar_items.tsx rename to x-pack/legacy/plugins/infra/common/inventory_models/container/toolbar_items.tsx index 2c24c7aa1a830..ddb3c0491f164 100644 --- a/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/container_toolbar_items.tsx +++ b/x-pack/legacy/plugins/infra/common/inventory_models/container/toolbar_items.tsx @@ -6,11 +6,14 @@ import React, { useMemo } from 'react'; import { EuiFlexItem } from '@elastic/eui'; -import { ToolbarProps } from './toolbar'; -import { WaffleMetricControls } from '../../waffle/waffle_metric_controls'; -import { WaffleGroupByControls } from '../../waffle/waffle_group_by_controls'; -import { InfraSnapshotMetricType } from '../../../graphql/types'; -import { toMetricOpt, toGroupByOpt } from './toolbar_wrapper'; +import { ToolbarProps } from '../../../public/components/inventory/toolbars/toolbar'; +import { WaffleMetricControls } from '../../../public/components/waffle/waffle_metric_controls'; +import { WaffleGroupByControls } from '../../../public/components/waffle/waffle_group_by_controls'; +import { InfraSnapshotMetricType } from '../../../public/graphql/types'; +import { + toMetricOpt, + toGroupByOpt, +} from '../../../public/components/inventory/toolbars/toolbar_wrapper'; export const ContainerToolbarItems = (props: ToolbarProps) => { const options = useMemo( diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/host/metrics/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/host/metrics/index.ts index d1fd3a307ae36..f4c0150309dd8 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/host/metrics/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/host/metrics/index.ts @@ -51,4 +51,5 @@ export const metrics: InventoryMetrics = { hostDockerTop5ByCpu, }, snapshot: { count, cpu, load, logRate, memory, rx, tx }, + defaultSnapshot: 'cpu', }; diff --git a/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/host_toolbar_items.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/host/toolbar_items.tsx similarity index 77% rename from x-pack/legacy/plugins/infra/public/components/inventory/toolbars/host_toolbar_items.tsx rename to x-pack/legacy/plugins/infra/common/inventory_models/host/toolbar_items.tsx index 81dadcc7f6c8b..8e1bb0dfb4816 100644 --- a/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/host_toolbar_items.tsx +++ b/x-pack/legacy/plugins/infra/common/inventory_models/host/toolbar_items.tsx @@ -6,11 +6,14 @@ import React, { useMemo } from 'react'; import { EuiFlexItem } from '@elastic/eui'; -import { ToolbarProps } from './toolbar'; -import { WaffleMetricControls } from '../../waffle/waffle_metric_controls'; -import { WaffleGroupByControls } from '../../waffle/waffle_group_by_controls'; -import { InfraSnapshotMetricType } from '../../../graphql/types'; -import { toGroupByOpt, toMetricOpt } from './toolbar_wrapper'; +import { ToolbarProps } from '../../../public/components/inventory/toolbars/toolbar'; +import { WaffleMetricControls } from '../../../public/components/waffle/waffle_metric_controls'; +import { WaffleGroupByControls } from '../../../public/components/waffle/waffle_group_by_controls'; +import { InfraSnapshotMetricType } from '../../../public/graphql/types'; +import { + toGroupByOpt, + toMetricOpt, +} from '../../../public/components/inventory/toolbars/toolbar_wrapper'; export const HostToolbarItems = (props: ToolbarProps) => { const metricOptions = useMemo( diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts b/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts index fa80659e1f4b0..9fce720f5b14b 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/layouts.ts @@ -25,14 +25,14 @@ interface Layouts { [type: string]: ReactNode; } -const Layouts: Layouts = { +const layouts: Layouts = { host: HostLayout, pod: PodLayout, container: ContainerLayout, }; export const findLayout = (type: InventoryItemType) => { - const Layout = idx(Layouts, _ => _[type]); + const Layout = idx(layouts, _ => _[type]); if (!Layout) { throw new Error( i18n.translate('xpack.infra.inventoryModels.findLayout.error', { diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/pod/metrics/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/pod/metrics/index.ts index 03aa6d4e039b1..2aa7ac6b496af 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/pod/metrics/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/pod/metrics/index.ts @@ -25,4 +25,5 @@ export const metrics: InventoryMetrics = { podMemoryUsage, }, snapshot: { cpu, memory, rx, tx }, + defaultSnapshot: 'cpu', }; diff --git a/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/pod_toolbar_items.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/pod/toolbar_items.tsx similarity index 75% rename from x-pack/legacy/plugins/infra/public/components/inventory/toolbars/pod_toolbar_items.tsx rename to x-pack/legacy/plugins/infra/common/inventory_models/pod/toolbar_items.tsx index b3eec84dcfcd6..cc0676fc60ae4 100644 --- a/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/pod_toolbar_items.tsx +++ b/x-pack/legacy/plugins/infra/common/inventory_models/pod/toolbar_items.tsx @@ -6,11 +6,14 @@ import React, { useMemo } from 'react'; import { EuiFlexItem } from '@elastic/eui'; -import { ToolbarProps } from './toolbar'; -import { WaffleMetricControls } from '../../waffle/waffle_metric_controls'; -import { WaffleGroupByControls } from '../../waffle/waffle_group_by_controls'; -import { InfraSnapshotMetricType } from '../../../graphql/types'; -import { toGroupByOpt, toMetricOpt } from './toolbar_wrapper'; +import { ToolbarProps } from '../../../public/components/inventory/toolbars/toolbar'; +import { WaffleMetricControls } from '../../../public/components/waffle/waffle_metric_controls'; +import { WaffleGroupByControls } from '../../../public/components/waffle/waffle_group_by_controls'; +import { InfraSnapshotMetricType } from '../../../public/graphql/types'; +import { + toGroupByOpt, + toMetricOpt, +} from '../../../public/components/inventory/toolbars/toolbar_wrapper'; export const PodToolbarItems = (props: ToolbarProps) => { const options = useMemo( diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/index.ts b/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/index.ts index a17ca0e2b09e5..6416aa08e8585 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/index.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/shared/metrics/index.ts @@ -16,6 +16,7 @@ import { awsNetworkBytes } from './tsvb/aws_network_bytes'; import { awsNetworkPackets } from './tsvb/aws_network_packets'; import { awsOverview } from './tsvb/aws_overview'; import { InventoryMetrics } from '../../types'; +import { count } from './snapshot/count'; export const metrics: InventoryMetrics = { tsvb: { @@ -30,4 +31,8 @@ export const metrics: InventoryMetrics = { awsNetworkPackets, awsOverview, }, + snapshot: { + count, + }, + defaultSnapshot: 'count', }; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/toolbars.ts b/x-pack/legacy/plugins/infra/common/inventory_models/toolbars.ts new file mode 100644 index 0000000000000..661b9c7a8841e --- /dev/null +++ b/x-pack/legacy/plugins/infra/common/inventory_models/toolbars.ts @@ -0,0 +1,36 @@ +/* + * 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 { idx } from '@kbn/elastic-idx/target'; +import { ReactNode, FunctionComponent } from 'react'; +import { i18n } from '@kbn/i18n'; +import { InventoryItemType } from './types'; +import { HostToolbarItems } from './host/toolbar_items'; +import { ContainerToolbarItems } from './container/toolbar_items'; +import { PodToolbarItems } from './pod/toolbar_items'; +import { ToolbarProps } from '../../public/components/inventory/toolbars/toolbar'; + +interface Toolbars { + [type: string]: ReactNode; +} + +const toolbars: Toolbars = { + host: HostToolbarItems, + container: ContainerToolbarItems, + pod: PodToolbarItems, +}; + +export const findToolbar = (type: InventoryItemType) => { + const Toolbar = idx(toolbars, _ => _[type]); + if (!Toolbar) { + throw new Error( + i18n.translate('xpack.infra.inventoryModels.findToolbar.error', { + defaultMessage: "The toolbar you've attempted to find does not exist.", + }) + ); + } + return Toolbar as FunctionComponent; +}; diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/types.ts b/x-pack/legacy/plugins/infra/common/inventory_models/types.ts index e3b6768ed919f..71774fd7025ed 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/types.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/types.ts @@ -5,6 +5,7 @@ */ import * as rt from 'io-ts'; +import { InfraSnapshotMetricType } from '../graphql/types'; export const ItemTypeRT = rt.keyof({ host: null, @@ -259,9 +260,22 @@ export const SnapshotModelRT = rt.record( ); export type SnapshotModel = rt.TypeOf; +export const SnapshotMetricTypeRT = rt.keyof({ + count: null, + cpu: null, + load: null, + memory: null, + tx: null, + rx: null, + logRate: null, +}); + +export type SnapshotMetricType = rt.TypeOf; + export interface InventoryMetrics { tsvb: { [name: string]: TSVBMetricModelCreator }; - snapshot?: { [name: string]: SnapshotModel }; + snapshot: { [name: string]: SnapshotModel }; + defaultSnapshot: SnapshotMetricType; } export interface InventoryModel { diff --git a/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/toolbar.tsx b/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/toolbar.tsx index f68944b012cca..167a328135bf7 100644 --- a/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/toolbar.tsx +++ b/x-pack/legacy/plugins/infra/public/components/inventory/toolbars/toolbar.tsx @@ -4,18 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { FunctionComponent } from 'react'; import { StaticIndexPattern } from 'ui/index_patterns'; import { Action } from 'typescript-fsa'; import { EuiFlexItem } from '@elastic/eui'; +import { findToolbar } from '../../../../common/inventory_models/toolbars'; import { InfraNodeType, InfraSnapshotMetricInput, InfraSnapshotGroupbyInput, } from '../../../graphql/types'; -import { HostToolbarItems } from './host_toolbar_items'; -import { PodToolbarItems } from './pod_toolbar_items'; -import { ContainerToolbarItems } from './container_toolbar_items'; import { ToolbarWrapper } from './toolbar_wrapper'; import { waffleOptionsSelectors } from '../../../store'; @@ -35,7 +33,7 @@ export interface ToolbarProps { nodeType: ReturnType; } -const wrapToolbarItems = (ToolbarItems: (props: ToolbarProps) => JSX.Element) => { +const wrapToolbarItems = (ToolbarItems: FunctionComponent) => { return ( {props => ( @@ -60,15 +58,7 @@ const wrapToolbarItems = (ToolbarItems: (props: ToolbarProps) => JSX.Element) => ); }; -export const Toolbar = (props: { nodeType: InfraNodeType }) => { - switch (props.nodeType) { - case InfraNodeType.host: - return wrapToolbarItems(HostToolbarItems); - case InfraNodeType.pod: - return wrapToolbarItems(PodToolbarItems); - case InfraNodeType.container: - return wrapToolbarItems(ContainerToolbarItems); - default: - return null; - } +export const Toolbar = ({ nodeType }: { nodeType: InfraNodeType }) => { + const ToolbarItems = findToolbar(nodeType); + return wrapToolbarItems(ToolbarItems); }; diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/waffle_inventory_switcher.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/waffle_inventory_switcher.tsx index ddb89811ac023..38e87038b7c4f 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/waffle_inventory_switcher.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/waffle_inventory_switcher.tsx @@ -15,6 +15,7 @@ import { InfraNodeType, InfraSnapshotGroupbyInput, } from '../../graphql/types'; +import { findInventoryModel } from '../../../common/inventory_models'; interface Props { nodeType: InfraNodeType; @@ -32,7 +33,10 @@ export const WaffleInventorySwitcher = (props: Props) => { closePopover(); props.changeNodeType(nodeType); props.changeGroupBy([]); - props.changeMetric({ type: InfraSnapshotMetricType.cpu }); + const inventoryModel = findInventoryModel(nodeType); + props.changeMetric({ + type: inventoryModel.metrics.defaultSnapshot as InfraSnapshotMetricType, + }); }, [props.changeGroupBy, props.changeNodeType, props.changeMetric] ); From f725d8a20b9989335551cc2ecd6cb7516653f689 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Thu, 31 Oct 2019 13:15:30 -0700 Subject: [PATCH 7/9] Fixing imports; wrapping code in useMemo to optimize --- .../pages/metrics/components/section.tsx | 64 +++++++++++-------- .../pages/metrics/components/sub_section.tsx | 30 +++++---- 2 files changed, 55 insertions(+), 39 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/components/section.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/section.tsx index 9a87557713616..27b2a517f1904 100644 --- a/x-pack/legacy/plugins/infra/public/pages/metrics/components/section.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/section.tsx @@ -4,7 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { FunctionComponent, useCallback } from 'react'; +import React, { + useContext, + Children, + isValidElement, + cloneElement, + FunctionComponent, + useCallback, + useMemo, +} from 'react'; import { EuiTitle } from '@elastic/eui'; import { SideNavContext, SubNavItem } from '../lib/side_nav_context'; import { LayoutProps } from '../types'; @@ -23,33 +31,37 @@ export const Section: FunctionComponent = ({ isLiveStreaming, stopLiveStreaming, }) => { - const { addNavItem } = React.useContext(SideNavContext); + const { addNavItem } = useContext(SideNavContext); const subNavItems: SubNavItem[] = []; - const childrenWithProps = React.Children.map(children, child => { - if (React.isValidElement(child)) { - const metric = (metrics && metrics.find(m => m.id === child.props.id)) || null; - if (metric) { - subNavItems.push({ - id: child.props.id, - name: child.props.label, - onClick: useCallback(() => { - const el = document.getElementById(child.props.id); - if (el) { - el.scrollIntoView(); - } - }, []), - }); - } - return React.cloneElement(child, { - metrics, - onChangeRangeTime, - isLiveStreaming, - stopLiveStreaming, - }); - } - return null; - }); + const childrenWithProps = useMemo( + () => + Children.map(children, child => { + if (isValidElement(child)) { + const metric = (metrics && metrics.find(m => m.id === child.props.id)) || null; + if (metric) { + subNavItems.push({ + id: child.props.id, + name: child.props.label, + onClick: () => { + const el = document.getElementById(child.props.id); + if (el) { + el.scrollIntoView(); + } + }, + }); + } + return cloneElement(child, { + metrics, + onChangeRangeTime, + isLiveStreaming, + stopLiveStreaming, + }); + } + return null; + }), + [children, metrics, onChangeRangeTime, isLiveStreaming, stopLiveStreaming] + ); if (metrics && subNavItems.length) { addNavItem({ id: navLabel, name: navLabel, items: subNavItems }); diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/components/sub_section.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/sub_section.tsx index 80253db52d61c..f3db3b1670199 100644 --- a/x-pack/legacy/plugins/infra/public/pages/metrics/components/sub_section.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/sub_section.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { FunctionComponent } from 'react'; +import React, { isValidElement, cloneElement, FunctionComponent, Children, useMemo } from 'react'; import { EuiTitle } from '@elastic/eui'; import { InventoryMetric } from '../../../../common/inventory_models/types'; import { LayoutProps } from '../types'; @@ -30,18 +30,22 @@ export const SubSection: FunctionComponent = ({ if (!metric) { return null; } - const childrenWithProps = React.Children.map(children, child => { - if (React.isValidElement(child)) { - return React.cloneElement(child, { - metric, - id, - onChangeRangeTime, - isLiveStreaming, - stopLiveStreaming, - }); - } - return null; - }); + const childrenWithProps = useMemo( + () => + Children.map(children, child => { + if (isValidElement(child)) { + return cloneElement(child, { + metric, + id, + onChangeRangeTime, + isLiveStreaming, + stopLiveStreaming, + }); + } + return null; + }), + [children, metric, id, onChangeRangeTime, isLiveStreaming, stopLiveStreaming] + ); return (
{label ? ( From d2d4e680163ca545cf9955754ade18d8adaeedcd Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Thu, 31 Oct 2019 14:27:23 -0700 Subject: [PATCH 8/9] removing unused imports --- x-pack/legacy/plugins/infra/common/inventory_models/types.ts | 1 - .../plugins/infra/public/pages/metrics/components/section.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/types.ts b/x-pack/legacy/plugins/infra/common/inventory_models/types.ts index 71774fd7025ed..93eaf214ad23e 100644 --- a/x-pack/legacy/plugins/infra/common/inventory_models/types.ts +++ b/x-pack/legacy/plugins/infra/common/inventory_models/types.ts @@ -5,7 +5,6 @@ */ import * as rt from 'io-ts'; -import { InfraSnapshotMetricType } from '../graphql/types'; export const ItemTypeRT = rt.keyof({ host: null, diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/components/section.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/components/section.tsx index 27b2a517f1904..32d2e2eff8ab9 100644 --- a/x-pack/legacy/plugins/infra/public/pages/metrics/components/section.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/components/section.tsx @@ -10,7 +10,6 @@ import React, { isValidElement, cloneElement, FunctionComponent, - useCallback, useMemo, } from 'react'; import { EuiTitle } from '@elastic/eui'; From d5416876b63a12aa837225dfcf8513494b94c6b3 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Wed, 13 Nov 2019 11:58:58 -0700 Subject: [PATCH 9/9] Removing prototype page --- .../inventory_models/host/detail_page.tsx | 142 ------------------ 1 file changed, 142 deletions(-) delete mode 100644 x-pack/legacy/plugins/infra/common/inventory_models/host/detail_page.tsx diff --git a/x-pack/legacy/plugins/infra/common/inventory_models/host/detail_page.tsx b/x-pack/legacy/plugins/infra/common/inventory_models/host/detail_page.tsx deleted file mode 100644 index 7ff69af87aa3a..0000000000000 --- a/x-pack/legacy/plugins/infra/common/inventory_models/host/detail_page.tsx +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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, { FunctionComponent, useEffect, useMemo } from 'react'; -import { EuiSideNav, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { InfraMetricData } from '../../../public/graphql/types'; -import { Section } from '../../../public/pages/metrics/components/section'; -import { SubSection } from '../../../public/pages/metrics/components/sub_section'; -import { NavItem, SideNavContext } from '../../../public/pages/metrics/lib/side_nav_context'; - -interface VisSectionProps { - metric?: InfraMetricData; -} - -const VisSection: FunctionComponent = ({ metric }) => { - if (metric) { - return ( -
-
VISUALIZATION GOES HERE
-
- ); - } - return
Gauges without Metric (you should never see this)
; -}; - -interface WithMetricsDataProps { - source: string; - ids: string[]; - children: (props: LayoutProps) => React.ReactElement; -} - -const WithMetricsData = ({ ids, children }: WithMetricsDataProps) => { - if (!children) { - return null; - } - - // eslint-disable-next-line no-console - useEffect(() => console.log('Fetching', ids), [ids]); - - const metrics = useMemo(() => { - return ids.map(m => ({ id: m, series: [] })); - }, [ids]) as InfraMetricData[]; - - return children({ metrics }); -}; - -interface LayoutProps { - metrics: InfraMetricData[]; -} - -interface MetricsLayout { - requiredMetrics: string[]; - Layout: FunctionComponent; -} - -const Aws: MetricsLayout = { - requiredMetrics: ['awsOverview', 'awsCpuUsage'], - Layout: ({ metrics }) => ( -
- - - - - - -
- ), -}; -const Nginx: MetricsLayout = { - requiredMetrics: ['nginxOverview'], - Layout: ({ metrics }) => ( -
- - - -
- ), -}; - -export const Host: MetricsLayout = { - requiredMetrics: [ - 'hostSystemOverview', - 'hostSystemCPU', - ...Aws.requiredMetrics, - ...Nginx.requiredMetrics, - ], - Layout: ({ metrics }) => ( - -
- - - - - - -
- - -
- ), -}; - -export const DetailPage: FunctionComponent = () => { - const [sideNav, setSideNav] = React.useState([]); - - const addNavItem = React.useCallback( - (item: NavItem) => { - if (!sideNav.some(n => n.id === item.id)) { - setSideNav([item, ...sideNav]); - } - }, - [sideNav] - ); - - return ( -
- - - - - - - - {({ metrics }) => } - - - - -
- ); -};