From 5d7a7fc907b1bdd84f1a99f92e39719d30c8ed59 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Thu, 4 Oct 2018 08:53:33 -0700 Subject: [PATCH 1/7] [Infra UI] Add log rate to metrics on Waffle Map This PR adds the log rate metric to the waffle map --- .../infra/common/graphql/introspection.json | 3 +- x-pack/plugins/infra/common/graphql/types.ts | 1 + .../infra/public/components/waffle/index.tsx | 1 + .../waffle/waffle_metric_controls.tsx | 1 + .../infra/public/utils/formatters/data.ts | 4 +-- .../infra/server/graphql/nodes/schema.gql.ts | 1 + .../lib/adapters/nodes/adapter_types.ts | 13 ++++++- .../nodes/lib/create_partition_bodies.ts | 6 +++- .../metric_aggregation_creators/index.ts | 2 ++ .../metric_aggregation_creators/log_rate.ts | 34 +++++++++++++++++++ 10 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 x-pack/plugins/infra/server/lib/adapters/nodes/metric_aggregation_creators/log_rate.ts diff --git a/x-pack/plugins/infra/common/graphql/introspection.json b/x-pack/plugins/infra/common/graphql/introspection.json index 8539efe293343..83fb2de8478cd 100644 --- a/x-pack/plugins/infra/common/graphql/introspection.json +++ b/x-pack/plugins/infra/common/graphql/introspection.json @@ -1586,7 +1586,8 @@ { "name": "load", "description": "", "isDeprecated": false, "deprecationReason": null }, { "name": "memory", "description": "", "isDeprecated": false, "deprecationReason": null }, { "name": "tx", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "rx", "description": "", "isDeprecated": false, "deprecationReason": null } + { "name": "rx", "description": "", "isDeprecated": false, "deprecationReason": null }, + { "name": "logRate", "description": "", "isDeprecated": false, "deprecationReason": null } ], "possibleTypes": null }, diff --git a/x-pack/plugins/infra/common/graphql/types.ts b/x-pack/plugins/infra/common/graphql/types.ts index c91e49bbd7c31..afb945c1ac60d 100644 --- a/x-pack/plugins/infra/common/graphql/types.ts +++ b/x-pack/plugins/infra/common/graphql/types.ts @@ -565,6 +565,7 @@ export enum InfraMetricType { memory = 'memory', tx = 'tx', rx = 'rx', + logRate = 'logRate', } export enum InfraNodeType { diff --git a/x-pack/plugins/infra/public/components/waffle/index.tsx b/x-pack/plugins/infra/public/components/waffle/index.tsx index 526380db88183..d0af1fd03f29f 100644 --- a/x-pack/plugins/infra/public/components/waffle/index.tsx +++ b/x-pack/plugins/infra/public/components/waffle/index.tsx @@ -59,6 +59,7 @@ const METRIC_FORMATTERS: MetricFormatters = { }, [InfraMetricType.rx]: { formatter: InfraFormatterType.bits, template: '{{value}}/s' }, [InfraMetricType.tx]: { formatter: InfraFormatterType.bits, template: '{{value}}/s' }, + [InfraMetricType.logRate]: { formatter: InfraFormatterType.abvNumber, template: '{{value}}/s' }, }; const extractValuesFromMap = (groups: InfraWaffleMapGroup[], values: number[] = []): number[] => { diff --git a/x-pack/plugins/infra/public/components/waffle/waffle_metric_controls.tsx b/x-pack/plugins/infra/public/components/waffle/waffle_metric_controls.tsx index e0df71ae9b2b6..6f6a8fc9ce99b 100644 --- a/x-pack/plugins/infra/public/components/waffle/waffle_metric_controls.tsx +++ b/x-pack/plugins/infra/public/components/waffle/waffle_metric_controls.tsx @@ -39,6 +39,7 @@ const OPTIONS = { { text: 'Load', value: InfraMetricType.load }, { text: 'Inbound Traffic', value: InfraMetricType.rx }, { text: 'Outbound Traffic', value: InfraMetricType.tx }, + { text: 'Log Rate', value: InfraMetricType.logRate }, ], }; diff --git a/x-pack/plugins/infra/public/utils/formatters/data.ts b/x-pack/plugins/infra/public/utils/formatters/data.ts index 4066d29ab9ab0..07b404c84f983 100644 --- a/x-pack/plugins/infra/public/utils/formatters/data.ts +++ b/x-pack/plugins/infra/public/utils/formatters/data.ts @@ -67,7 +67,7 @@ export const createDataFormatter = (format: InfraWaffleMapDataFormat) => (val: n const base = BASES[format]; const power = Math.min(Math.floor(Math.log(Math.abs(val)) / Math.log(base)), labels.length - 1); if (power < 0) { - return `${formatNumber(val)} ${labels[0]}`; + return `${formatNumber(val)}${labels[0]}`; } - return `${formatNumber(val / Math.pow(base, power))} ${labels[power]}`; + return `${formatNumber(val / Math.pow(base, power))}${labels[power]}`; }; diff --git a/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts b/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts index 3b2efacc5a3cc..7c9427bf7522d 100644 --- a/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts +++ b/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts @@ -45,6 +45,7 @@ export const nodesSchema: any = gql` memory tx rx + logRate } input InfraMetricInput { diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts index 2c50f07a5fa89..e1384e4a96ad7 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts @@ -207,6 +207,12 @@ export interface InfraDerivativeAgg { }; } +export interface InfraCumulativeSumAgg { + cumulative_sum: { + buckets_path: string; + }; +} + export interface InfraBucketScriptAgg { bucket_script: { buckets_path: { [key: string]: string }; @@ -218,7 +224,12 @@ export interface InfraBucketScriptAgg { }; } -export type InfraAgg = InfraBucketScriptAgg | InfraDerivativeAgg | InfraAvgAgg | InfraMaxAgg; +export type InfraAgg = + | InfraBucketScriptAgg + | InfraDerivativeAgg + | InfraAvgAgg + | InfraMaxAgg + | InfraCumulativeSumAgg; export interface InfraNodeMetricAgg { [key: string]: InfraAgg; } diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_partition_bodies.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_partition_bodies.ts index 68d949e57b210..10d3e14aa7b8d 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_partition_bodies.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_partition_bodies.ts @@ -6,6 +6,7 @@ import { times } from 'lodash'; +import { InfraMetricType } from '../../../../../common/graphql/types'; import { InfraESMSearchBody, InfraNodeRequestOptions, @@ -24,6 +25,9 @@ export function createPartitionBodies( const { sourceConfiguration }: InfraNodeRequestOptions = nodeOptions; const bodies: InfraESMSearchBody[] = []; const numberOfPartitions: number = Math.ceil(totalNodes / NODE_REQUEST_PARTITION_SIZE); + const indices = nodeOptions.metrics.every(m => m.type === InfraMetricType.logRate) + ? [sourceConfiguration.logAlias] + : [sourceConfiguration.logAlias, sourceConfiguration.metricAlias]; times( numberOfPartitions, (partitionId: number): void => { @@ -35,7 +39,7 @@ export function createPartitionBodies( partitionId, }; bodies.push({ - index: [sourceConfiguration.logAlias, sourceConfiguration.metricAlias], + index: indices, }); bodies.push(createNodeRequestBody(processorOptions)); } diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/metric_aggregation_creators/index.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/metric_aggregation_creators/index.ts index 769b65ae602a9..da520d1d64941 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/metric_aggregation_creators/index.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/metric_aggregation_creators/index.ts @@ -8,6 +8,7 @@ import { InfraMetricType } from '../../../../../common/graphql/types'; import { count } from './count'; import { cpu } from './cpu'; import { load } from './load'; +import { logRate } from './log_rate'; import { memory } from './memory'; import { rx } from './rx'; import { tx } from './tx'; @@ -19,4 +20,5 @@ export const metricAggregationCreators = { [InfraMetricType.rx]: rx, [InfraMetricType.tx]: tx, [InfraMetricType.load]: load, + [InfraMetricType.logRate]: logRate, }; diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/metric_aggregation_creators/log_rate.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/metric_aggregation_creators/log_rate.ts new file mode 100644 index 0000000000000..d447997e47734 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/metric_aggregation_creators/log_rate.ts @@ -0,0 +1,34 @@ +/* + * 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 { InfraNodeMetricFn, InfraNodeType } from '../adapter_types'; + +export const logRate: InfraNodeMetricFn = (nodeType: InfraNodeType) => { + return { + count: { + bucket_script: { + buckets_path: { count: '_count' }, + script: { + source: 'count * 1', + lang: 'expression', + }, + gap_policy: 'skip', + }, + }, + cumsum: { + cumulative_sum: { + buckets_path: 'count', + }, + }, + logRate: { + derivative: { + buckets_path: 'cumsum', + gap_policy: 'skip', + unit: '1s', + }, + }, + }; +}; From 9d68254805ba377ea65ab010294f25a91efc1f91 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Thu, 4 Oct 2018 10:29:49 -0700 Subject: [PATCH 2/7] Changing abvNumber to abbreviatedNumber --- x-pack/plugins/infra/public/components/waffle/index.tsx | 5 ++++- x-pack/plugins/infra/public/lib/lib.ts | 2 +- x-pack/plugins/infra/public/pages/metrics/layouts/host.ts | 2 +- x-pack/plugins/infra/public/utils/formatters/index.ts | 4 +++- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/infra/public/components/waffle/index.tsx b/x-pack/plugins/infra/public/components/waffle/index.tsx index d0af1fd03f29f..1f576511951e4 100644 --- a/x-pack/plugins/infra/public/components/waffle/index.tsx +++ b/x-pack/plugins/infra/public/components/waffle/index.tsx @@ -59,7 +59,10 @@ const METRIC_FORMATTERS: MetricFormatters = { }, [InfraMetricType.rx]: { formatter: InfraFormatterType.bits, template: '{{value}}/s' }, [InfraMetricType.tx]: { formatter: InfraFormatterType.bits, template: '{{value}}/s' }, - [InfraMetricType.logRate]: { formatter: InfraFormatterType.abvNumber, template: '{{value}}/s' }, + [InfraMetricType.logRate]: { + formatter: InfraFormatterType.abbreviatedNumber, + template: '{{value}}/s', + }, }; const extractValuesFromMap = (groups: InfraWaffleMapGroup[], values: number[] = []): number[] => { diff --git a/x-pack/plugins/infra/public/lib/lib.ts b/x-pack/plugins/infra/public/lib/lib.ts index c587281f54c86..2e38392564176 100644 --- a/x-pack/plugins/infra/public/lib/lib.ts +++ b/x-pack/plugins/infra/public/lib/lib.ts @@ -186,7 +186,7 @@ export interface InfraWaffleMapBounds { export type InfraFormatter = (value: string | number) => string; export enum InfraFormatterType { number = 'number', - abvNumber = 'abvNumber', + abbreviatedNumber = 'abbreviatedNumber', bytes = 'bytes', bits = 'bits', percent = 'percent', diff --git a/x-pack/plugins/infra/public/pages/metrics/layouts/host.ts b/x-pack/plugins/infra/public/pages/metrics/layouts/host.ts index 6535b27444fd7..cea153bad8193 100644 --- a/x-pack/plugins/infra/public/pages/metrics/layouts/host.ts +++ b/x-pack/plugins/infra/public/pages/metrics/layouts/host.ts @@ -168,7 +168,7 @@ export const hostLayoutCreator: InfraMetricLayoutCreator = theme => [ requires: ['kubernetes.node'], type: InfraMetricLayoutSectionType.chart, visConfig: { - formatter: InfraFormatterType.abvNumber, + formatter: InfraFormatterType.abbreviatedNumber, seriesOverrides: { capacity: { color: theme.eui.euiColorVis2 }, used: { color: theme.eui.euiColorVis1, type: InfraMetricLayoutVisualizationType.area }, diff --git a/x-pack/plugins/infra/public/utils/formatters/index.ts b/x-pack/plugins/infra/public/utils/formatters/index.ts index 7cd163182d889..864890a43f957 100644 --- a/x-pack/plugins/infra/public/utils/formatters/index.ts +++ b/x-pack/plugins/infra/public/utils/formatters/index.ts @@ -12,7 +12,9 @@ import { formatPercent } from './percent'; export const FORMATTERS = { [InfraFormatterType.number]: formatNumber, - [InfraFormatterType.abvNumber]: createDataFormatter(InfraWaffleMapDataFormat.abbreviatedNumber), + [InfraFormatterType.abbreviatedNumber]: createDataFormatter( + InfraWaffleMapDataFormat.abbreviatedNumber + ), [InfraFormatterType.bytes]: createDataFormatter(InfraWaffleMapDataFormat.bytesDecimal), [InfraFormatterType.bits]: createDataFormatter(InfraWaffleMapDataFormat.bitsDecimal), [InfraFormatterType.percent]: formatPercent, From 67e2b7e938abb8e3adf25955f9ca483a8fb00664 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Fri, 5 Oct 2018 09:48:00 -0700 Subject: [PATCH 3/7] adding support for normalized_value --- .../infra/server/lib/adapters/nodes/adapter_types.ts | 2 +- .../infra/server/lib/adapters/nodes/lib/create_node_item.ts | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts index e1384e4a96ad7..600283f98e6b0 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts @@ -160,7 +160,7 @@ export interface InfraBucketWithAggs { } export interface InfraBucketWithValues { - [name: string]: { value: number }; + [name: string]: { value: number; normalized_value?: number }; } export type InfraBucket = InfraBucketWithAggs & InfraBucketWithKey & InfraBucketWithValues; diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_node_item.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_node_item.ts index 1bd4311c5fc1c..04a5cf2191e34 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_node_item.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_node_item.ts @@ -45,7 +45,11 @@ function createNodeMetrics( } return metrics.filter(metric => lastBucket[metric.type]).map(metric => { const metricObj = lastBucket[metric.type]; - return { name: metric.type, value: (metricObj && metricObj.value) || 0 }; + const value = (metricObj && (metricObj.normalized_value || metricObj.value)) || 0; + return { + name: metric.type, + value, + }; }); } From 16d2c107bfaea3734184d68be06845e6403e741a Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Fri, 5 Oct 2018 10:54:10 -0700 Subject: [PATCH 4/7] Fixing normalized_value issue in inbound/outbound traffic --- .../lib/adapters/nodes/metric_aggregation_creators/rate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/metric_aggregation_creators/rate.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/metric_aggregation_creators/rate.ts index bbcc387f3c072..9a315a9145992 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/metric_aggregation_creators/rate.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/metric_aggregation_creators/rate.ts @@ -28,7 +28,7 @@ export const rate = (id: string, fields: Fields): InfraNodeMetricFn => ( }, [id]: { bucket_script: { - buckets_path: { value: `${id}_deriv` }, + buckets_path: { value: `${id}_deriv[normalized_value]` }, script: { source: 'params.value > 0.0 ? params.value : 0.0', lang: 'painless', From 7439964ef901693a62af0dfb8dbcd814dd9b0a77 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Fri, 5 Oct 2018 16:19:17 -0700 Subject: [PATCH 5/7] Removing support for multiple metrics form the waffle interface --- .../infra/common/graphql/introspection.json | 28 +++------------- x-pack/plugins/infra/common/graphql/types.ts | 20 ++++++------ .../infra/public/components/waffle/index.tsx | 9 +++--- .../infra/public/components/waffle/node.tsx | 3 +- .../waffle/waffle_metric_controls.tsx | 15 ++++----- .../waffle/waffle_node_type_switcher.tsx | 4 +-- .../containers/waffle/nodes_to_wafflemap.ts | 2 +- .../waffle/waffle_nodes.gql_query.ts | 4 +-- .../containers/waffle/with_waffle_nodes.tsx | 6 ++-- .../containers/waffle/with_waffle_options.tsx | 24 +++++++------- .../infra/public/containers/with_options.tsx | 2 +- x-pack/plugins/infra/public/lib/lib.ts | 4 +-- .../infra/public/pages/home/page_content.tsx | 6 ++-- .../infra/public/pages/home/toolbar.tsx | 12 +++---- .../store/local/waffle_options/actions.ts | 2 +- .../store/local/waffle_options/reducer.ts | 12 +++---- .../store/local/waffle_options/selector.ts | 2 +- .../infra/server/graphql/nodes/resolvers.ts | 10 ++++-- .../infra/server/graphql/nodes/schema.gql.ts | 2 +- .../lib/adapters/nodes/adapter_types.ts | 2 +- .../extract_group_by_and_node_from_path.ts | 3 ++ .../nodes/extract_paths_and_metrics.ts | 32 ++++++++++++------- .../adapters/nodes/lib/create_node_item.ts | 20 ++++++------ .../nodes/lib/create_partition_bodies.ts | 7 ++-- .../last/metric_buckets_processor.ts | 15 ++------- 25 files changed, 112 insertions(+), 134 deletions(-) diff --git a/x-pack/plugins/infra/common/graphql/introspection.json b/x-pack/plugins/infra/common/graphql/introspection.json index 83fb2de8478cd..0d06adc09acef 100644 --- a/x-pack/plugins/infra/common/graphql/introspection.json +++ b/x-pack/plugins/infra/common/graphql/introspection.json @@ -1481,28 +1481,16 @@ "deprecationReason": null }, { - "name": "metrics", + "name": "metric", "description": "", "args": [ { - "name": "metrics", + "name": "metric", "description": "", "type": { "kind": "NON_NULL", "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "InfraMetricInput", - "ofType": null - } - } - } + "ofType": { "kind": "INPUT_OBJECT", "name": "InfraMetricInput", "ofType": null } }, "defaultValue": null } @@ -1510,15 +1498,7 @@ "type": { "kind": "NON_NULL", "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "InfraNodeMetric", "ofType": null } - } - } + "ofType": { "kind": "OBJECT", "name": "InfraNodeMetric", "ofType": null } }, "isDeprecated": false, "deprecationReason": null diff --git a/x-pack/plugins/infra/common/graphql/types.ts b/x-pack/plugins/infra/common/graphql/types.ts index afb945c1ac60d..a5b8affa34301 100644 --- a/x-pack/plugins/infra/common/graphql/types.ts +++ b/x-pack/plugins/infra/common/graphql/types.ts @@ -117,7 +117,7 @@ export interface InfraResponse { export interface InfraNode { path: InfraNodePath[]; - metrics: InfraNodeMetric[]; + metric: InfraNodeMetric; } export interface InfraNodePath { @@ -404,13 +404,13 @@ export namespace InfraResponseResolvers { export namespace InfraNodeResolvers { export interface Resolvers { path?: PathResolver; - metrics?: MetricsResolver; + metric?: MetricResolver; } export type PathResolver = Resolver; - export type MetricsResolver = Resolver; - export interface MetricsArgs { - metrics: InfraMetricInput[]; + export type MetricResolver = Resolver; + export interface MetricArgs { + metric: InfraMetricInput; } } @@ -534,8 +534,8 @@ export interface IndexFieldsInfraSourceStatusArgs { export interface NodesInfraResponseArgs { path?: InfraPathInput[] | null; } -export interface MetricsInfraNodeArgs { - metrics: InfraMetricInput[]; +export interface MetricInfraNodeArgs { + metric: InfraMetricInput; } export enum InfraIndexType { @@ -653,7 +653,7 @@ export namespace WaffleNodesQuery { sourceId: string; timerange: InfraTimerangeInput; filterQuery?: string | null; - metrics: InfraMetricInput[]; + metric: InfraMetricInput; path: InfraPathInput[]; }; @@ -676,7 +676,7 @@ export namespace WaffleNodesQuery { export type Nodes = { __typename?: 'InfraNode'; path: Path[]; - metrics: Metrics[]; + metric: Metric; }; export type Path = { @@ -684,7 +684,7 @@ export namespace WaffleNodesQuery { value: string; }; - export type Metrics = { + export type Metric = { __typename?: 'InfraNodeMetric'; name: InfraMetricType; value: number; diff --git a/x-pack/plugins/infra/public/components/waffle/index.tsx b/x-pack/plugins/infra/public/components/waffle/index.tsx index 1f576511951e4..8503a73eb765a 100644 --- a/x-pack/plugins/infra/public/components/waffle/index.tsx +++ b/x-pack/plugins/infra/public/components/waffle/index.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { EuiButton, EuiEmptyPrompt } from '@elastic/eui'; -import { get, last, max, min } from 'lodash'; +import { get, max, min } from 'lodash'; import React from 'react'; import styled from 'styled-components'; import { InfraMetricType, InfraNodeType } from '../../../common/graphql/types'; @@ -73,8 +73,7 @@ const extractValuesFromMap = (groups: InfraWaffleMapGroup[], values: number[] = if (isWaffleMapGroupWithNodes(group)) { return acc.concat( group.nodes.map(node => { - const lastMetric = last(node.metrics); - return (lastMetric && lastMetric.value) || 0; + return node.metric.value || 0; }) ); } @@ -113,7 +112,7 @@ export class Waffle extends React.Component { /> ); } - const metric = last(this.props.options.metrics); + const { metric } = this.props.options; const metricFormatter = get( METRIC_FORMATTERS, metric.type, @@ -143,7 +142,7 @@ export class Waffle extends React.Component { // TODO: Change this to a real implimentation using the tickFormatter from the prototype as an example. private formatter = (val: string | number) => { - const metric = last(this.props.options.metrics); + const { metric } = this.props.options; const metricFormatter = get( METRIC_FORMATTERS, metric.type, diff --git a/x-pack/plugins/infra/public/components/waffle/node.tsx b/x-pack/plugins/infra/public/components/waffle/node.tsx index 369d486bb5639..08792a3f36209 100644 --- a/x-pack/plugins/infra/public/components/waffle/node.tsx +++ b/x-pack/plugins/infra/public/components/waffle/node.tsx @@ -5,7 +5,6 @@ */ import { EuiToolTip } from '@elastic/eui'; -import { last } from 'lodash'; import { darken, readableColor } from 'polished'; import React from 'react'; import styled from 'styled-components'; @@ -35,7 +34,7 @@ export class Node extends React.PureComponent { public render() { const { nodeType, node, options, squareSize, bounds, formatter } = this.props; const { isPopoverOpen } = this.state; - const metric = last(node.metrics); + const { metric } = node; const valueMode = squareSize > 110; const rawValue = (metric && metric.value) || 0; const color = colorFromValue(options.legend, rawValue, bounds); diff --git a/x-pack/plugins/infra/public/components/waffle/waffle_metric_controls.tsx b/x-pack/plugins/infra/public/components/waffle/waffle_metric_controls.tsx index 6f6a8fc9ce99b..fe9b015e62457 100644 --- a/x-pack/plugins/infra/public/components/waffle/waffle_metric_controls.tsx +++ b/x-pack/plugins/infra/public/components/waffle/waffle_metric_controls.tsx @@ -11,13 +11,12 @@ import { EuiFilterGroup, EuiPopover, } from '@elastic/eui'; -import { last } from 'lodash'; import React from 'react'; import { InfraMetricInput, InfraMetricType, InfraNodeType } from '../../../common/graphql/types'; interface Props { nodeType: InfraNodeType; - metrics: InfraMetricInput[]; - onChange: (metrics: InfraMetricInput[]) => void; + metric: InfraMetricInput; + onChange: (metric: InfraMetricInput) => void; } const OPTIONS = { @@ -51,13 +50,13 @@ type State = Readonly; export class WaffleMetricControls extends React.PureComponent { public readonly state: State = initialState; public render() { - const currentMetric = last(this.props.metrics); + const { metric } = this.props; const options = OPTIONS[this.props.nodeType]; - const value = currentMetric.type; + const value = metric.type; if (!options.length || !value) { throw Error('Unable to select options or value for metric.'); } - const currentLabel = options.find(o => o.value === currentMetric.type); + const currentLabel = options.find(o => o.value === metric.type); if (!currentLabel) { return 'null'; } @@ -66,7 +65,7 @@ export class WaffleMetricControls extends React.PureComponent { id: 0, title: '', items: options.map(o => { - const icon = o.value === currentMetric.type ? 'check' : 'empty'; + const icon = o.value === metric.type ? 'check' : 'empty'; const panel = { name: o.text, onClick: this.handleClick(o.value), icon }; return panel; }), @@ -101,7 +100,7 @@ export class WaffleMetricControls extends React.PureComponent { }; private handleClick = (value: InfraMetricType) => () => { - this.props.onChange([{ type: value }]); + this.props.onChange({ type: value }); this.handleClose(); }; } diff --git a/x-pack/plugins/infra/public/components/waffle/waffle_node_type_switcher.tsx b/x-pack/plugins/infra/public/components/waffle/waffle_node_type_switcher.tsx index 39fd5da962053..e1071261a8de6 100644 --- a/x-pack/plugins/infra/public/components/waffle/waffle_node_type_switcher.tsx +++ b/x-pack/plugins/infra/public/components/waffle/waffle_node_type_switcher.tsx @@ -17,7 +17,7 @@ interface Props { nodeType: InfraNodeType; changeNodeType: (nodeType: InfraNodeType) => void; changeGroupBy: (groupBy: InfraPathInput[]) => void; - changeMetrics: (metric: InfraMetricInput[]) => void; + changeMetric: (metric: InfraMetricInput) => void; } export class WaffleNodeTypeSwitcher extends React.PureComponent { @@ -40,6 +40,6 @@ export class WaffleNodeTypeSwitcher extends React.PureComponent { private handleClick = (nodeType: InfraNodeType) => () => { this.props.changeNodeType(nodeType); this.props.changeGroupBy([]); - this.props.changeMetrics([{ type: InfraMetricType.cpu }]); + this.props.changeMetric({ type: InfraMetricType.cpu }); }; } diff --git a/x-pack/plugins/infra/public/containers/waffle/nodes_to_wafflemap.ts b/x-pack/plugins/infra/public/containers/waffle/nodes_to_wafflemap.ts index 43da03fb2c4e5..6dad5d0b9405b 100644 --- a/x-pack/plugins/infra/public/containers/waffle/nodes_to_wafflemap.ts +++ b/x-pack/plugins/infra/public/containers/waffle/nodes_to_wafflemap.ts @@ -76,7 +76,7 @@ function createWaffleMapNode(node: InfraNode): InfraWaffleMapNode { id: node.path.map(p => p.value).join('/'), path: node.path, name: last(node.path).value, - metrics: node.metrics, + metric: node.metric, }; } diff --git a/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts b/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts index 519f0063d9d9b..d09dd4af1d510 100644 --- a/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts +++ b/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts @@ -11,7 +11,7 @@ export const waffleNodesQuery = gql` $sourceId: ID! $timerange: InfraTimerangeInput! $filterQuery: String - $metrics: [InfraMetricInput!]! + $metric: InfraMetricInput! $path: [InfraPathInput!]! ) { source(id: $sourceId) { @@ -21,7 +21,7 @@ export const waffleNodesQuery = gql` path { value } - metrics(metrics: $metrics) { + metric(metric: $metric) { name value } diff --git a/x-pack/plugins/infra/public/containers/waffle/with_waffle_nodes.tsx b/x-pack/plugins/infra/public/containers/waffle/with_waffle_nodes.tsx index 79ed84a9b9b75..f8a5a7a607917 100644 --- a/x-pack/plugins/infra/public/containers/waffle/with_waffle_nodes.tsx +++ b/x-pack/plugins/infra/public/containers/waffle/with_waffle_nodes.tsx @@ -28,7 +28,7 @@ interface WithWaffleNodesArgs { interface WithWaffleNodesProps { children: (args: WithWaffleNodesArgs) => React.ReactNode; filterQuery: string | null | undefined; - metrics: InfraMetricInput[]; + metric: InfraMetricInput; groupBy: InfraPathInput[]; nodeType: InfraNodeType; sourceId: string; @@ -44,7 +44,7 @@ const NODE_TYPE_TO_PATH_TYPE = { export const WithWaffleNodes = ({ children, filterQuery, - metrics, + metric, groupBy, nodeType, sourceId, @@ -56,7 +56,7 @@ export const WithWaffleNodes = ({ notifyOnNetworkStatusChange variables={{ sourceId, - metrics, + metric, path: [...groupBy, { type: NODE_TYPE_TO_PATH_TYPE[nodeType] }], timerange, filterQuery, diff --git a/x-pack/plugins/infra/public/containers/waffle/with_waffle_options.tsx b/x-pack/plugins/infra/public/containers/waffle/with_waffle_options.tsx index 5d5b3e4de5cdd..3992d78f71cd0 100644 --- a/x-pack/plugins/infra/public/containers/waffle/with_waffle_options.tsx +++ b/x-pack/plugins/infra/public/containers/waffle/with_waffle_options.tsx @@ -16,7 +16,7 @@ import { bindPlainActionCreators } from '../../utils/typed_redux'; import { UrlStateContainer } from '../../utils/url_state'; const selectOptionsUrlState = createSelector( - waffleOptionsSelectors.selectMetrics, + waffleOptionsSelectors.selectMetric, waffleOptionsSelectors.selectGroupBy, waffleOptionsSelectors.selectNodeType, (metrics, groupBy, nodeType) => ({ @@ -28,13 +28,13 @@ const selectOptionsUrlState = createSelector( export const withWaffleOptions = connect( (state: State) => ({ - metrics: waffleOptionsSelectors.selectMetrics(state), + metric: waffleOptionsSelectors.selectMetric(state), groupBy: waffleOptionsSelectors.selectGroupBy(state), nodeType: waffleOptionsSelectors.selectNodeType(state), urlState: selectOptionsUrlState(state), }), bindPlainActionCreators({ - changeMetrics: waffleOptionsActions.changeMetrics, + changeMetric: waffleOptionsActions.changeMetric, changeGroupBy: waffleOptionsActions.changeGroupBy, changeNodeType: waffleOptionsActions.changeNodeType, }) @@ -47,21 +47,21 @@ export const WithWaffleOptions = asChildFunctionRenderer(withWaffleOptions); */ interface WaffleOptionsUrlState { - metrics?: ReturnType; + metric?: ReturnType; groupBy?: ReturnType; nodeType?: ReturnType; } export const WithWaffleOptionsUrlState = () => ( - {({ changeMetrics, urlState, changeGroupBy, changeNodeType }) => ( + {({ changeMetric, urlState, changeGroupBy, changeNodeType }) => ( { - if (newUrlState && newUrlState.metrics) { - changeMetrics(newUrlState.metrics); + if (newUrlState && newUrlState.metric) { + changeMetric(newUrlState.metric); } if (newUrlState && newUrlState.groupBy) { changeGroupBy(newUrlState.groupBy); @@ -72,7 +72,7 @@ export const WithWaffleOptionsUrlState = () => ( }} onInitialize={initialUrlState => { if (initialUrlState) { - changeMetrics(initialUrlState.metrics || initialWaffleOptionsState.metrics); + changeMetric(initialUrlState.metric || initialWaffleOptionsState.metric); changeGroupBy(initialUrlState.groupBy || initialWaffleOptionsState.groupBy); changeNodeType(initialUrlState.nodeType || initialWaffleOptionsState.nodeType); } @@ -85,7 +85,7 @@ export const WithWaffleOptionsUrlState = () => ( const mapToUrlState = (value: any): WaffleOptionsUrlState | undefined => value ? { - metrics: mapToMetricsUrlState(value.metrics), + metric: mapToMetricUrlState(value.metric), groupBy: mapToGroupByUrlState(value.groupBy), nodeType: mapToNodeTypeUrlState(value.nodeType), } @@ -99,10 +99,8 @@ const isInfraPathInput = (subject: any): subject is InfraPathType => { return subject != null && subject.type != null && InfraPathType[subject.type] != null; }; -const mapToMetricsUrlState = (subject: any) => { - return subject && Array.isArray(subject) && subject.every(isInfraMetricInput) - ? subject - : undefined; +const mapToMetricUrlState = (subject: any) => { + return subject && isInfraMetricInput(subject) ? subject : undefined; }; const mapToGroupByUrlState = (subject: any) => { diff --git a/x-pack/plugins/infra/public/containers/with_options.tsx b/x-pack/plugins/infra/public/containers/with_options.tsx index 0b4c7d6a548a3..0e92a6ef43edb 100644 --- a/x-pack/plugins/infra/public/containers/with_options.tsx +++ b/x-pack/plugins/infra/public/containers/with_options.tsx @@ -30,7 +30,7 @@ const initialState = { wafflemap: { formatter: InfraFormatterType.percent, formatTemplate: '{{value}}', - metrics: [{ type: InfraMetricType.cpu }], + metric: { type: InfraMetricType.cpu }, path: [{ type: InfraPathType.hosts }], /* legend: { diff --git a/x-pack/plugins/infra/public/lib/lib.ts b/x-pack/plugins/infra/public/lib/lib.ts index 2e38392564176..a4fb71131b292 100644 --- a/x-pack/plugins/infra/public/lib/lib.ts +++ b/x-pack/plugins/infra/public/lib/lib.ts @@ -103,7 +103,7 @@ export interface InfraWaffleMapNode { id: string; name: string; path: InfraNodePath[]; - metrics: InfraNodeMetric[]; + metric: InfraNodeMetric; } export type InfraWaffleMapGroup = InfraWaffleMapGroupOfNodes | InfraWaffleMapGroupOfGroups; @@ -165,7 +165,7 @@ export interface InfraWaffleMapOptions { fields?: SourceQuery.Fields | null; formatter: InfraFormatterType; formatTemplate: string; - metrics: InfraMetricInput[]; + metric: InfraMetricInput; path: InfraPathInput[]; legend: InfraWaffleMapLegend; } diff --git a/x-pack/plugins/infra/public/pages/home/page_content.tsx b/x-pack/plugins/infra/public/pages/home/page_content.tsx index c8d1d41562e22..fd907fec83b39 100644 --- a/x-pack/plugins/infra/public/pages/home/page_content.tsx +++ b/x-pack/plugins/infra/public/pages/home/page_content.tsx @@ -27,10 +27,10 @@ export const HomePageContent: React.SFC = () => ( {({ currentTimeRange }) => ( - {({ metrics, groupBy, nodeType }) => ( + {({ metric, groupBy, nodeType }) => ( ( map={nodes} loading={loading} nodeType={nodeType} - options={{ ...wafflemap, metrics, fields: configuredFields }} + options={{ ...wafflemap, metric, fields: configuredFields }} reload={refetch} /> )} diff --git a/x-pack/plugins/infra/public/pages/home/toolbar.tsx b/x-pack/plugins/infra/public/pages/home/toolbar.tsx index 51238aaa7bced..5abccd9f9763d 100644 --- a/x-pack/plugins/infra/public/pages/home/toolbar.tsx +++ b/x-pack/plugins/infra/public/pages/home/toolbar.tsx @@ -42,12 +42,12 @@ export const HomeToolbar: React.SFC = () => ( - {({ nodeType, changeNodeType, changeGroupBy, changeMetrics }) => ( + {({ nodeType, changeNodeType, changeGroupBy, changeMetric }) => ( @@ -81,14 +81,10 @@ export const HomeToolbar: React.SFC = () => ( - {({ changeMetrics, changeGroupBy, groupBy, metrics, nodeType }) => ( + {({ changeMetric, changeGroupBy, groupBy, metric, nodeType }) => ( - + ('CHANGE_METRICS'); +export const changeMetric = actionCreator('CHANGE_METRIC'); export const changeGroupBy = actionCreator('CHANGE_GROUP_BY'); export const changeNodeType = actionCreator('CHANGE_NODE_TYPE'); diff --git a/x-pack/plugins/infra/public/store/local/waffle_options/reducer.ts b/x-pack/plugins/infra/public/store/local/waffle_options/reducer.ts index 0063f5e4bc93a..c736aa47de39c 100644 --- a/x-pack/plugins/infra/public/store/local/waffle_options/reducer.ts +++ b/x-pack/plugins/infra/public/store/local/waffle_options/reducer.ts @@ -13,22 +13,22 @@ import { InfraPathInput, } from '../../../../common/graphql/types'; import { InfraNodeType } from '../../../../server/lib/adapters/nodes'; -import { changeGroupBy, changeMetrics, changeNodeType } from './actions'; +import { changeGroupBy, changeMetric, changeNodeType } from './actions'; export interface WaffleOptionsState { - metrics: InfraMetricInput[]; + metric: InfraMetricInput; groupBy: InfraPathInput[]; nodeType: InfraNodeType; } export const initialWaffleOptionsState: WaffleOptionsState = { - metrics: [{ type: InfraMetricType.cpu }], + metric: { type: InfraMetricType.cpu }, groupBy: [], nodeType: InfraNodeType.host, }; -const currentMetricsReducer = reducerWithInitialState(initialWaffleOptionsState.metrics).case( - changeMetrics, +const currentMetricReducer = reducerWithInitialState(initialWaffleOptionsState.metric).case( + changeMetric, (current, target) => target ); @@ -43,7 +43,7 @@ const currentNodeTypeReducer = reducerWithInitialState(initialWaffleOptionsState ); export const waffleOptionsReducer = combineReducers({ - metrics: currentMetricsReducer, + metric: currentMetricReducer, groupBy: currentGroupByReducer, nodeType: currentNodeTypeReducer, }); diff --git a/x-pack/plugins/infra/public/store/local/waffle_options/selector.ts b/x-pack/plugins/infra/public/store/local/waffle_options/selector.ts index e9afd7ce57b06..6889cd6150ab7 100644 --- a/x-pack/plugins/infra/public/store/local/waffle_options/selector.ts +++ b/x-pack/plugins/infra/public/store/local/waffle_options/selector.ts @@ -6,6 +6,6 @@ import { WaffleOptionsState } from './reducer'; -export const selectMetrics = (state: WaffleOptionsState) => state.metrics; +export const selectMetric = (state: WaffleOptionsState) => state.metric; export const selectGroupBy = (state: WaffleOptionsState) => state.groupBy; export const selectNodeType = (state: WaffleOptionsState) => state.nodeType; diff --git a/x-pack/plugins/infra/server/graphql/nodes/resolvers.ts b/x-pack/plugins/infra/server/graphql/nodes/resolvers.ts index 273234073893e..d85bb8e2c7dc0 100644 --- a/x-pack/plugins/infra/server/graphql/nodes/resolvers.ts +++ b/x-pack/plugins/infra/server/graphql/nodes/resolvers.ts @@ -8,7 +8,7 @@ import { InfraSourceResolvers } from '../../../common/graphql/types'; import { InfraResolvedResult, InfraResolverOf } from '../../lib/adapters/framework'; import { InfraNodeRequestOptions } from '../../lib/adapters/nodes'; import { extractGroupByAndNodeFromPath } from '../../lib/adapters/nodes/extract_group_by_and_node_from_path'; -import { extractPathsAndMetrics } from '../../lib/adapters/nodes/extract_paths_and_metrics'; +import { extractPathsAndMetric } from '../../lib/adapters/nodes/extract_paths_and_metrics'; import { InfraNodesDomain } from '../../lib/domains/nodes_domain'; import { InfraContext } from '../../lib/infra_types'; import { parseFilterQuery } from '../../utils/serialized_query'; @@ -33,15 +33,19 @@ export const createNodeResolvers = ( } => ({ InfraSource: { async map(source, args, { req }, info) { - const { metrics, path } = extractPathsAndMetrics(info); + const { metric, path } = extractPathsAndMetric(info); const { groupBy, nodeType } = extractGroupByAndNodeFromPath(path); + if (!metric) { + throw new Error('The metric argument is not optional'); + } + const options: InfraNodeRequestOptions = { filterQuery: parseFilterQuery(args.filterQuery), nodeType, groupBy, sourceConfiguration: source.configuration, - metrics, + metric, timerange: args.timerange, }; diff --git a/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts b/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts index 7c9427bf7522d..d67b7089dfa31 100644 --- a/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts +++ b/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts @@ -18,7 +18,7 @@ export const nodesSchema: any = gql` type InfraNode { path: [InfraNodePath!]! - metrics(metrics: [InfraMetricInput!]!): [InfraNodeMetric!]! + metric(metric: InfraMetricInput!): InfraNodeMetric! } input InfraTimerangeInput { diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts index 600283f98e6b0..14323349a9628 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts @@ -90,7 +90,7 @@ export interface InfraNodeRequestOptions { sourceConfiguration: InfraSourceConfiguration; timerange: InfraTimerangeInput; groupBy: InfraPathInput[]; - metrics: InfraMetricInput[]; + metric: InfraMetricInput; filterQuery: InfraESQuery | undefined; } diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/extract_group_by_and_node_from_path.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/extract_group_by_and_node_from_path.ts index 9e67ecd7e0ac7..60fa22b4116e4 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/extract_group_by_and_node_from_path.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/extract_group_by_and_node_from_path.ts @@ -20,6 +20,9 @@ const getNodeType = (type: InfraPathType): InfraNodeType => { }; const isEntityType = (path: InfraPathInput) => { + if (!path) { + return false; + } switch (path.type) { case InfraPathType.containers: case InfraPathType.hosts: diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/extract_paths_and_metrics.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/extract_paths_and_metrics.ts index 7b5b514bbdf57..d8c812d0857f9 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/extract_paths_and_metrics.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/extract_paths_and_metrics.ts @@ -18,22 +18,22 @@ import { interface InfraPathsAndMetricOptions { path: InfraPathInput[]; - metrics: InfraMetricInput[]; + metric: InfraMetricInput | null; } -export function extractPathsAndMetrics(info: GraphQLResolveInfo): InfraPathsAndMetricOptions { - if (info.variableValues.metrics && info.variableValues.path) { +export function extractPathsAndMetric(info: GraphQLResolveInfo): InfraPathsAndMetricOptions { + if (info.variableValues.metric && info.variableValues.path) { return { - metrics: info.variableValues.metrics as InfraMetricInput[], + metric: info.variableValues.metric as InfraMetricInput, path: info.variableValues.path as InfraPathInput[], }; } - const { path, metrics }: InfraPathsAndMetricOptions = info.fieldNodes.reduce(parseFieldNodes, { + const { path, metric }: InfraPathsAndMetricOptions = info.fieldNodes.reduce(parseFieldNodes, { path: [], - metrics: [], + metric: null, }); - return { path, metrics }; + return { path, metric }; } function isFieldNode(subject: any): subject is FieldNode { @@ -77,8 +77,18 @@ function extractArgument(selection: FieldNode, name: string): Return function extractPathArgument(selection: FieldNode): InfraPathInput[] { return extractArgument(selection, 'path') as InfraPathInput[]; } -function extractMetricsArgument(selection: FieldNode): InfraMetricInput[] { - return extractArgument(selection, 'metrics') as InfraMetricInput[]; + +function extractMetricArgument(selection: FieldNode): InfraMetricInput | null { + if (!selection.arguments) { + return null; + } + return selection.arguments + .filter(isArgumentNode) + .filter(subject => subject.name.value === 'metric') + .reduce((prev: InfraMetricInput[], argument: ArgumentNode) => { + return valueFromASTUntyped(argument.value); + }, []) + .pop(); } function parseFieldNodes( @@ -90,8 +100,8 @@ function parseFieldNodes( selections.forEach( (selection: SelectionNode): void => { if (isMetricSelection(selection) && selection.arguments) { - const metrics = extractMetricsArgument(selection); - ctx.metrics = metrics || []; + const metric = extractMetricArgument(selection); + ctx.metric = metric; } parseFieldNodes(ctx, selection); } diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_node_item.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_node_item.ts index 04a5cf2191e34..a2d072e0897d7 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_node_item.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_node_item.ts @@ -36,21 +36,19 @@ function createNodeMetrics( options: InfraNodeRequestOptions, node: InfraBucket, bucket: InfraBucket -): InfraNodeMetric[] { - const { timerange, metrics } = options; +): InfraNodeMetric { + const { timerange, metric } = options; const bucketSize = getBucketSizeInSeconds(timerange.interval); const lastBucket = findLastFullBucket(bucket, bucketSize, options); if (!lastBucket) { throw new Error('Date histogram returned an empty set of buckets.'); } - return metrics.filter(metric => lastBucket[metric.type]).map(metric => { - const metricObj = lastBucket[metric.type]; - const value = (metricObj && (metricObj.normalized_value || metricObj.value)) || 0; - return { - name: metric.type, - value, - }; - }); + const metricObj = lastBucket[metric.type]; + const value = (metricObj && (metricObj.normalized_value || metricObj.value)) || 0; + return { + name: metric.type, + value, + }; } export function createNodeItem( @@ -59,7 +57,7 @@ export function createNodeItem( bucket: InfraBucket ): InfraNode { return { - metrics: createNodeMetrics(options, node, bucket), + metric: createNodeMetrics(options, node, bucket), path: [{ value: node.key }], } as InfraNode; } diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_partition_bodies.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_partition_bodies.ts index 10d3e14aa7b8d..83b0ccec28c96 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_partition_bodies.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/lib/create_partition_bodies.ts @@ -25,9 +25,10 @@ export function createPartitionBodies( const { sourceConfiguration }: InfraNodeRequestOptions = nodeOptions; const bodies: InfraESMSearchBody[] = []; const numberOfPartitions: number = Math.ceil(totalNodes / NODE_REQUEST_PARTITION_SIZE); - const indices = nodeOptions.metrics.every(m => m.type === InfraMetricType.logRate) - ? [sourceConfiguration.logAlias] - : [sourceConfiguration.logAlias, sourceConfiguration.metricAlias]; + const indices = + nodeOptions.metric.type === InfraMetricType.logRate + ? [sourceConfiguration.logAlias] + : [sourceConfiguration.logAlias, sourceConfiguration.metricAlias]; times( numberOfPartitions, (partitionId: number): void => { diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/processors/last/metric_buckets_processor.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/processors/last/metric_buckets_processor.ts index 9a4335fcf2844..57e8cf6012617 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/processors/last/metric_buckets_processor.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/processors/last/metric_buckets_processor.ts @@ -12,19 +12,10 @@ import { metricAggregationCreators } from '../../metric_aggregation_creators'; export const metricBucketsProcessor = (options: InfraProcesorRequestOptions) => { return (doc: InfraESSearchBody) => { const result = cloneDeep(doc); - const { metrics, groupBy } = options.nodeOptions; + const { metric, groupBy } = options.nodeOptions; const path = createBasePath(groupBy).concat(['timeseries', 'aggs']); - const aggs = metrics.reduce((acc, metric) => { - const aggregationCreator = metricAggregationCreators[metric.type]; - const metricAgg = aggregationCreator(options.nodeType); - if (!metricAgg) { - return acc; - } - return { - ...acc, - ...metricAgg, - }; - }, {}); + const aggregationCreator = metricAggregationCreators[metric.type]; + const aggs = aggregationCreator(options.nodeType); set(result, path, aggs); return result; }; From 568b7675a68dc7f2b11a57ddfb4dcdc75604e33f Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 16 Oct 2018 09:02:20 -0700 Subject: [PATCH 6/7] refactor map endpoint to remove the info parsing code --- .../infra/common/graphql/introspection.json | 111 +++++++++-------- x-pack/plugins/infra/common/graphql/types.ts | 12 +- .../waffle/waffle_nodes.gql_query.ts | 4 +- .../infra/server/graphql/nodes/resolvers.ts | 50 +++++--- .../infra/server/graphql/nodes/schema.gql.ts | 4 +- .../lib/adapters/nodes/adapter_types.ts | 3 +- .../nodes/elasticsearch_nodes_adapter.ts | 10 +- .../nodes/extract_paths_and_metrics.ts | 115 ------------------ .../lib/adapters/nodes/lib/process_nodes.ts | 17 +-- .../infra/server/lib/domains/nodes_domain.ts | 4 +- 10 files changed, 113 insertions(+), 217 deletions(-) delete mode 100644 x-pack/plugins/infra/server/lib/adapters/nodes/extract_paths_and_metrics.ts diff --git a/x-pack/plugins/infra/common/graphql/introspection.json b/x-pack/plugins/infra/common/graphql/introspection.json index 0d06adc09acef..528c4f1010a64 100644 --- a/x-pack/plugins/infra/common/graphql/introspection.json +++ b/x-pack/plugins/infra/common/graphql/introspection.json @@ -1315,15 +1315,29 @@ "name": "path", "description": "", "type": { - "kind": "LIST", + "kind": "NON_NULL", "name": null, "ofType": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "InfraPathInput", "ofType": null } + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "INPUT_OBJECT", "name": "InfraPathInput", "ofType": null } + } } }, "defaultValue": null + }, + { + "name": "metric", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "INPUT_OBJECT", "name": "InfraMetricInput", "ofType": null } + }, + "defaultValue": null } ], "type": { @@ -1455,6 +1469,45 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "InfraMetricInput", + "description": "", + "fields": null, + "inputFields": [ + { + "name": "type", + "description": "The type of metric", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "ENUM", "name": "InfraMetricType", "ofType": null } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "InfraMetricType", + "description": "", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { "name": "count", "description": "", "isDeprecated": false, "deprecationReason": null }, + { "name": "cpu", "description": "", "isDeprecated": false, "deprecationReason": null }, + { "name": "load", "description": "", "isDeprecated": false, "deprecationReason": null }, + { "name": "memory", "description": "", "isDeprecated": false, "deprecationReason": null }, + { "name": "tx", "description": "", "isDeprecated": false, "deprecationReason": null }, + { "name": "rx", "description": "", "isDeprecated": false, "deprecationReason": null }, + { "name": "logRate", "description": "", "isDeprecated": false, "deprecationReason": null } + ], + "possibleTypes": null + }, { "kind": "OBJECT", "name": "InfraNode", @@ -1483,18 +1536,7 @@ { "name": "metric", "description": "", - "args": [ - { - "name": "metric", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "InfraMetricInput", "ofType": null } - }, - "defaultValue": null - } - ], + "args": [], "type": { "kind": "NON_NULL", "name": null, @@ -1532,45 +1574,6 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "INPUT_OBJECT", - "name": "InfraMetricInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "type", - "description": "The type of metric", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "InfraMetricType", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "InfraMetricType", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { "name": "count", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "cpu", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "load", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "memory", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "tx", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "rx", "description": "", "isDeprecated": false, "deprecationReason": null }, - { "name": "logRate", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, { "kind": "OBJECT", "name": "InfraNodeMetric", diff --git a/x-pack/plugins/infra/common/graphql/types.ts b/x-pack/plugins/infra/common/graphql/types.ts index a5b8affa34301..d3d0522594bf8 100644 --- a/x-pack/plugins/infra/common/graphql/types.ts +++ b/x-pack/plugins/infra/common/graphql/types.ts @@ -397,7 +397,8 @@ export namespace InfraResponseResolvers { export type NodesResolver = Resolver; export interface NodesArgs { - path?: InfraPathInput[] | null; + path: InfraPathInput[]; + metric: InfraMetricInput; } } @@ -408,10 +409,7 @@ export namespace InfraNodeResolvers { } export type PathResolver = Resolver; - export type MetricResolver = Resolver; - export interface MetricArgs { - metric: InfraMetricInput; - } + export type MetricResolver = Resolver; } export namespace InfraNodePathResolvers { @@ -532,9 +530,7 @@ export interface IndexFieldsInfraSourceStatusArgs { indexType?: InfraIndexType | null; } export interface NodesInfraResponseArgs { - path?: InfraPathInput[] | null; -} -export interface MetricInfraNodeArgs { + path: InfraPathInput[]; metric: InfraMetricInput; } diff --git a/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts b/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts index d09dd4af1d510..8da5b160603e7 100644 --- a/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts +++ b/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts @@ -17,11 +17,11 @@ export const waffleNodesQuery = gql` source(id: $sourceId) { id map(timerange: $timerange, filterQuery: $filterQuery) { - nodes(path: $path) { + nodes(path: $path, metric: $metric) { path { value } - metric(metric: $metric) { + metric { name value } diff --git a/x-pack/plugins/infra/server/graphql/nodes/resolvers.ts b/x-pack/plugins/infra/server/graphql/nodes/resolvers.ts index d85bb8e2c7dc0..a0dd14940d7cf 100644 --- a/x-pack/plugins/infra/server/graphql/nodes/resolvers.ts +++ b/x-pack/plugins/infra/server/graphql/nodes/resolvers.ts @@ -4,19 +4,33 @@ * you may not use this file except in compliance with the Elastic License. */ -import { InfraSourceResolvers } from '../../../common/graphql/types'; -import { InfraResolvedResult, InfraResolverOf } from '../../lib/adapters/framework'; +import { InfraResponseResolvers, InfraSourceResolvers } from '../../../common/graphql/types'; +import { + InfraResolvedResult, + InfraResolverOf, + InfraResolverWithoutFields, +} from '../../lib/adapters/framework'; import { InfraNodeRequestOptions } from '../../lib/adapters/nodes'; import { extractGroupByAndNodeFromPath } from '../../lib/adapters/nodes/extract_group_by_and_node_from_path'; -import { extractPathsAndMetric } from '../../lib/adapters/nodes/extract_paths_and_metrics'; import { InfraNodesDomain } from '../../lib/domains/nodes_domain'; import { InfraContext } from '../../lib/infra_types'; import { parseFilterQuery } from '../../utils/serialized_query'; import { QuerySourceResolver } from '../sources/resolvers'; -type InfraSourceMapResolver = InfraResolverOf< +type InfraSourceMapResolver = InfraResolverWithoutFields< InfraSourceResolvers.MapResolver, InfraResolvedResult, + InfraContext, + 'nodes' +>; + +interface QueryMapResponse extends InfraSourceResolvers.MapArgs { + source: InfraResolvedResult; +} + +type InfraNodesResolver = InfraResolverOf< + InfraResponseResolvers.NodesResolver, + QueryMapResponse, InfraContext >; @@ -30,23 +44,31 @@ export const createNodeResolvers = ( InfraSource: { map: InfraSourceMapResolver; }; + InfraResponse: { + nodes: InfraNodesResolver; + }; } => ({ InfraSource: { - async map(source, args, { req }, info) { - const { metric, path } = extractPathsAndMetric(info); - const { groupBy, nodeType } = extractGroupByAndNodeFromPath(path); - - if (!metric) { - throw new Error('The metric argument is not optional'); - } + async map(source, args) { + return { + source, + timerange: args.timerange, + filterQuery: args.filterQuery, + }; + }, + }, + InfraResponse: { + async nodes(mapResponse, args, { req }) { + const { source, timerange, filterQuery } = mapResponse; + const { groupBy, nodeType } = extractGroupByAndNodeFromPath(args.path); const options: InfraNodeRequestOptions = { - filterQuery: parseFilterQuery(args.filterQuery), + filterQuery: parseFilterQuery(filterQuery), nodeType, groupBy, sourceConfiguration: source.configuration, - metric, - timerange: args.timerange, + metric: args.metric, + timerange, }; return await libs.nodes.getNodes(req, options); diff --git a/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts b/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts index d67b7089dfa31..33de32f100805 100644 --- a/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts +++ b/x-pack/plugins/infra/server/graphql/nodes/schema.gql.ts @@ -18,7 +18,7 @@ export const nodesSchema: any = gql` type InfraNode { path: [InfraNodePath!]! - metric(metric: InfraMetricInput!): InfraNodeMetric! + metric: InfraNodeMetric! } input InfraTimerangeInput { @@ -81,7 +81,7 @@ export const nodesSchema: any = gql` } type InfraResponse { - nodes(path: [InfraPathInput!]): [InfraNode!]! + nodes(path: [InfraPathInput!]!, metric: InfraMetricInput!): [InfraNode!]! } extend type InfraSource { diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts index 14323349a9628..9d43317efe084 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/adapter_types.ts @@ -10,7 +10,6 @@ import { InfraPathFilterInput, InfraPathInput, InfraPathType, - InfraResponse, InfraTimerangeInput, } from '../../../../common/graphql/types'; import { JsonObject } from '../../../../common/typed_json'; @@ -18,7 +17,7 @@ import { InfraSourceConfiguration } from '../../sources'; import { InfraFrameworkRequest } from '../framework'; export interface InfraNodesAdapter { - getNodes(req: InfraFrameworkRequest, options: InfraNodeRequestOptions): Promise; + getNodes(req: InfraFrameworkRequest, options: InfraNodeRequestOptions): Promise; } export interface InfraHostsFieldsObject { diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/elasticsearch_nodes_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/elasticsearch_nodes_adapter.ts index fbd477b2616f9..97459ad0cc04b 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/elasticsearch_nodes_adapter.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/elasticsearch_nodes_adapter.ts @@ -12,7 +12,7 @@ import { InfraNodesAggregations, } from './adapter_types'; -import { InfraResponse } from '../../../../common/graphql/types'; +import { InfraNode } from '../../../../common/graphql/types'; import { calculateCardinalityOfNodeField } from './lib/calculate_cardinality'; import { createPartitionBodies } from './lib/create_partition_bodies'; import { processNodes } from './lib/process_nodes'; @@ -26,19 +26,17 @@ export class ElasticsearchNodesAdapter implements InfraNodesAdapter { public async getNodes( req: InfraFrameworkRequest, options: InfraNodeRequestOptions - ): Promise { + ): Promise { const search = (searchOptions: object) => this.framework.callWithRequest<{}, Aggregation>(req, 'search', searchOptions); const msearch = (msearchOptions: object) => this.framework.callWithRequest<{}, Aggregation>(req, 'msearch', msearchOptions); const nodeField = options.sourceConfiguration.fields[options.nodeType]; - const infraResponse: InfraResponse = { nodes: [] }; - const totalNodes = await calculateCardinalityOfNodeField(search, nodeField, options); if (totalNodes === 0) { - return infraResponse; + return []; } const body = createPartitionBodies(totalNodes, options.nodeType, nodeField, options); @@ -61,6 +59,6 @@ export class ElasticsearchNodesAdapter implements InfraNodesAdapter { return processNodes(options, nodeBuckets); } - return infraResponse; + return []; } } diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/extract_paths_and_metrics.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/extract_paths_and_metrics.ts deleted file mode 100644 index d8c812d0857f9..0000000000000 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/extract_paths_and_metrics.ts +++ /dev/null @@ -1,115 +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 { InfraMetricInput, InfraPathInput } from '../../../../common/graphql/types'; - -import { - ArgumentNode, - FieldNode, - GraphQLResolveInfo, - ListValueNode, - SelectionNode, - SelectionSetNode, - valueFromASTUntyped, -} from 'graphql'; - -interface InfraPathsAndMetricOptions { - path: InfraPathInput[]; - metric: InfraMetricInput | null; -} - -export function extractPathsAndMetric(info: GraphQLResolveInfo): InfraPathsAndMetricOptions { - if (info.variableValues.metric && info.variableValues.path) { - return { - metric: info.variableValues.metric as InfraMetricInput, - path: info.variableValues.path as InfraPathInput[], - }; - } - - const { path, metric }: InfraPathsAndMetricOptions = info.fieldNodes.reduce(parseFieldNodes, { - path: [], - metric: null, - }); - return { path, metric }; -} - -function isFieldNode(subject: any): subject is FieldNode { - return subject.kind === 'Field'; -} - -function isListValueNode(subject: any): subject is ListValueNode { - return subject.kind === 'ListValue'; -} - -function isMetricSelection(subject: SelectionNode): subject is FieldNode { - return isFieldNode(subject) && subject.name.value === 'metrics' && subject.selectionSet != null; -} - -function isArgumentNode(subject: any): subject is ArgumentNode { - return subject.kind === 'Argument'; -} - -function hasPathArguments(subject: FieldNode): boolean { - return ( - (subject.arguments && subject.arguments.find(arg => arg.name.value === 'path') && true) || false - ); -} - -function extractArgument(selection: FieldNode, name: string): ReturnType[] { - if (!selection.arguments) { - return []; - } - const result = selection.arguments - .filter(isArgumentNode) - .filter(subject => subject.name.value === name) - .reduce((prev: ReturnType, argument: ArgumentNode) => { - if (isListValueNode(argument.value)) { - return valueFromASTUntyped(argument.value); - } - return prev; - }, []); - return result; -} - -function extractPathArgument(selection: FieldNode): InfraPathInput[] { - return extractArgument(selection, 'path') as InfraPathInput[]; -} - -function extractMetricArgument(selection: FieldNode): InfraMetricInput | null { - if (!selection.arguments) { - return null; - } - return selection.arguments - .filter(isArgumentNode) - .filter(subject => subject.name.value === 'metric') - .reduce((prev: InfraMetricInput[], argument: ArgumentNode) => { - return valueFromASTUntyped(argument.value); - }, []) - .pop(); -} - -function parseFieldNodes( - ctx: InfraPathsAndMetricOptions, - node: SelectionNode -): InfraPathsAndMetricOptions { - if (isFieldNode(node) && node.selectionSet) { - const { selections }: SelectionSetNode = node.selectionSet; - selections.forEach( - (selection: SelectionNode): void => { - if (isMetricSelection(selection) && selection.arguments) { - const metric = extractMetricArgument(selection); - ctx.metric = metric; - } - parseFieldNodes(ctx, selection); - } - ); - if (hasPathArguments(node)) { - const paths = extractPathArgument(node); - ctx.path = paths || []; - } - } - return ctx; -} diff --git a/x-pack/plugins/infra/server/lib/adapters/nodes/lib/process_nodes.ts b/x-pack/plugins/infra/server/lib/adapters/nodes/lib/process_nodes.ts index 63467bb43e3d6..ef55628cb744d 100644 --- a/x-pack/plugins/infra/server/lib/adapters/nodes/lib/process_nodes.ts +++ b/x-pack/plugins/infra/server/lib/adapters/nodes/lib/process_nodes.ts @@ -4,16 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { set } from 'lodash'; - -import { InfraNode, InfraResponse } from '../../../../../common/graphql/types'; +import { InfraNode } from '../../../../../common/graphql/types'; import { InfraBucket, InfraNodeRequestOptions } from '../adapter_types'; import { convertNodesResponseToGroups } from './convert_nodes_response_to_groups'; import { createNodeItem } from './create_node_item'; -export function processNodes(options: InfraNodeRequestOptions, nodes: any[]): InfraResponse { - const response: InfraResponse = { nodes: [] }; - +export function processNodes(options: InfraNodeRequestOptions, nodes: any[]): InfraNode[] { if (options.groupBy.length === 0) { // If there are NO group by options then we need to return a // nodes only response @@ -22,12 +18,9 @@ export function processNodes(options: InfraNodeRequestOptions, nodes: any[]): In return createNodeItem(options, node, node); } ); - set(response, 'nodes', nodeResults); - return response; - } else { - // Return a grouped response - response.nodes = convertNodesResponseToGroups(options, nodes); + return nodeResults; } - return response; + // Return a grouped response + return convertNodesResponseToGroups(options, nodes); } diff --git a/x-pack/plugins/infra/server/lib/domains/nodes_domain.ts b/x-pack/plugins/infra/server/lib/domains/nodes_domain.ts index 576a00df783e1..4c6d990dbeb95 100644 --- a/x-pack/plugins/infra/server/lib/domains/nodes_domain.ts +++ b/x-pack/plugins/infra/server/lib/domains/nodes_domain.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { InfraResponse } from '../../../common/graphql/types'; +import { InfraNode } from '../../../common/graphql/types'; import { InfraFrameworkRequest } from '../adapters/framework'; import { InfraNodeRequestOptions, InfraNodesAdapter } from '../adapters/nodes'; @@ -18,7 +18,7 @@ export class InfraNodesDomain { public async getNodes( req: InfraFrameworkRequest, options: InfraNodeRequestOptions - ): Promise { + ): Promise { return await this.adapter.getNodes(req, options); } } From 8c88f9383c5fd6d80efa038fc46a18069772fc34 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 16 Oct 2018 10:36:49 -0700 Subject: [PATCH 7/7] Updating PR with changes upstream --- .../plugins/infra/public/pages/metrics/layouts/nginx.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/infra/public/pages/metrics/layouts/nginx.ts b/x-pack/plugins/infra/public/pages/metrics/layouts/nginx.ts index e78f8da757ef0..f03580feb72c0 100644 --- a/x-pack/plugins/infra/public/pages/metrics/layouts/nginx.ts +++ b/x-pack/plugins/infra/public/pages/metrics/layouts/nginx.ts @@ -24,7 +24,7 @@ export const nginxLayoutCreator: InfraMetricLayoutCreator = theme => [ requires: ['nginx.access'], type: InfraMetricLayoutSectionType.chart, visConfig: { - formatter: InfraFormatterType.abvNumber, + formatter: InfraFormatterType.abbreviatedNumber, stacked: true, seriesOverrides: { '200s': { color: theme.eui.euiColorVis1, type: InfraMetricLayoutVisualizationType.bar }, @@ -40,7 +40,7 @@ export const nginxLayoutCreator: InfraMetricLayoutCreator = theme => [ requires: ['nginx.statusstub'], type: InfraMetricLayoutSectionType.chart, visConfig: { - formatter: InfraFormatterType.abvNumber, + formatter: InfraFormatterType.abbreviatedNumber, formatterTemplate: '{{value}}/s', seriesOverrides: { rate: { color: theme.eui.euiColorVis1, type: InfraMetricLayoutVisualizationType.area }, @@ -53,7 +53,7 @@ export const nginxLayoutCreator: InfraMetricLayoutCreator = theme => [ requires: ['nginx.statusstub'], type: InfraMetricLayoutSectionType.chart, visConfig: { - formatter: InfraFormatterType.abvNumber, + formatter: InfraFormatterType.abbreviatedNumber, seriesOverrides: { connections: { color: theme.eui.euiColorVis1, @@ -68,7 +68,7 @@ export const nginxLayoutCreator: InfraMetricLayoutCreator = theme => [ requires: ['nginx.statusstub'], type: InfraMetricLayoutSectionType.chart, visConfig: { - formatter: InfraFormatterType.abvNumber, + formatter: InfraFormatterType.abbreviatedNumber, seriesOverrides: { reqPerConns: { color: theme.eui.euiColorVis1,