From 8528662fcafa6383ccde7bfa949f60c0907ca9a6 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Wed, 10 Jun 2020 16:53:40 -0700 Subject: [PATCH 1/5] [TSVB] Add support for histogram type --- .../vis_type_timeseries/common/constants.ts | 32 +++++++ .../common/metric_types.js | 2 + .../components/aggs/histogram_support.test.js | 84 +++++++++++++++++++ .../application/components/aggs/percentile.js | 2 +- .../aggs/percentile_rank/percentile_rank.js | 2 +- .../components/aggs/positive_rate.js | 2 +- .../application/components/aggs/std_agg.js | 15 +++- 7 files changed, 134 insertions(+), 5 deletions(-) create mode 100644 src/plugins/vis_type_timeseries/public/application/components/aggs/histogram_support.test.js diff --git a/src/plugins/vis_type_timeseries/common/constants.ts b/src/plugins/vis_type_timeseries/common/constants.ts index fc402d6ab7db5..c71c36d1a3cf4 100644 --- a/src/plugins/vis_type_timeseries/common/constants.ts +++ b/src/plugins/vis_type_timeseries/common/constants.ts @@ -18,3 +18,35 @@ */ export const MAX_BUCKETS_SETTING = 'metrics:max_buckets'; + +// Tests Constants +export const UI_RESTRICTIONS = { '*': true }; +export const INDEX_PATTERN = 'some-pattern'; +export const FIELDS = { + [INDEX_PATTERN]: [ + { + type: 'date', + name: '@timestamp', + }, + { + type: 'number', + name: 'system.cpu.user.pct', + }, + { + type: 'histogram', + name: 'histogram_value', + }, + ], +}; +export const METRIC = { + type: 'avg', + field: 'system.cpu.user.pct', +}; +export const SERIES = { + metrics: [METRIC], +}; +export const PANEL = { + type: 'timeseries', + index_pattern: INDEX_PATTERN, + series: SERIES, +}; diff --git a/src/plugins/vis_type_timeseries/common/metric_types.js b/src/plugins/vis_type_timeseries/common/metric_types.js index 9dc6085b080e9..082ff21cf17c6 100644 --- a/src/plugins/vis_type_timeseries/common/metric_types.js +++ b/src/plugins/vis_type_timeseries/common/metric_types.js @@ -27,6 +27,8 @@ export const METRIC_TYPES = { VARIANCE: 'variance', SUM_OF_SQUARES: 'sum_of_squares', CARDINALITY: 'cardinality', + VALUE_COUNT: 'value_count', + AVERAGE: 'avg', }; export const EXTENDED_STATS_TYPES = [ diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/histogram_support.test.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/histogram_support.test.js new file mode 100644 index 0000000000000..cab017927ff5b --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/histogram_support.test.js @@ -0,0 +1,84 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { mountWithIntl } from 'test_utils/enzyme_helpers'; +import { Agg } from './agg'; +import { FieldSelect } from './field_select'; +import { FIELDS, METRIC, SERIES, PANEL } from '../../../../common/constants'; +const runTest = (aggType, name, test) => { + describe(aggType, () => { + const metric = { + ...METRIC, + type: aggType, + field: 'histogram_value', + }; + const series = { ...SERIES, metrics: [metric] }; + const panel = { ...PANEL, series }; + + it(name, () => { + const wrapper = mountWithIntl( +
+ +
+ ); + test(wrapper); + }); + }); +}; + +describe('Histogram Types', () => { + describe('supported', () => { + const shouldHaveHistogramSupport = (aggType) => { + runTest(aggType, 'supports', (wrapper) => + expect(wrapper.find(FieldSelect).at(0).props().restrict).toContain('histogram') + ); + }; + shouldHaveHistogramSupport('avg'); + shouldHaveHistogramSupport('value_count'); + shouldHaveHistogramSupport('percentile'); + shouldHaveHistogramSupport('percentile_rank'); + }); + describe('not supported', () => { + const shouldNotHaveHistogramSupport = (aggType) => { + runTest(aggType, 'does not support', (wrapper) => + expect(wrapper.find(FieldSelect).at(0).props().restrict).not.toContain('histogram') + ); + }; + shouldNotHaveHistogramSupport('cardinality'); + shouldNotHaveHistogramSupport('max'); + shouldNotHaveHistogramSupport('min'); + shouldNotHaveHistogramSupport('sum'); + shouldNotHaveHistogramSupport('variance'); + shouldNotHaveHistogramSupport('sum_of_squares'); + shouldNotHaveHistogramSupport('std_deviation'); + shouldNotHaveHistogramSupport('positive_rate'); + shouldNotHaveHistogramSupport('top_hit'); + }); +}); diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile.js index 6a7bf1bffe83c..f12c0c8f6f465 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile.js @@ -36,7 +36,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { KBN_FIELD_TYPES } from '../../../../../../plugins/data/public'; import { Percentiles, newPercentile } from './percentile_ui'; -const RESTRICT_FIELDS = [KBN_FIELD_TYPES.NUMBER]; +const RESTRICT_FIELDS = [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.HISTOGRAM]; const checkModel = (model) => Array.isArray(model.percentiles); diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile_rank/percentile_rank.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile_rank/percentile_rank.js index c8af4089ed783..90d5aa7c39590 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile_rank/percentile_rank.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile_rank/percentile_rank.js @@ -38,7 +38,7 @@ import { import { FormattedMessage } from '@kbn/i18n/react'; import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public'; -const RESTRICT_FIELDS = [KBN_FIELD_TYPES.NUMBER]; +const RESTRICT_FIELDS = [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.HISTOGRAM]; export const PercentileRankAgg = (props) => { const { series, panel, fields } = props; diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/positive_rate.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/positive_rate.js index 3ca89f7289d65..c20bcc1babc1d 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/positive_rate.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/positive_rate.js @@ -123,7 +123,7 @@ export const PositiveRateAgg = (props) => { type !== KBN_FIELD_TYPES.HISTOGRAM); + case METRIC_TYPES.VALUE_COUNT: + case METRIC_TYPES.AVERAGE: + return [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.HISTOGRAM]; + default: + return [KBN_FIELD_TYPES.NUMBER]; + } +} + export function StandardAgg(props) { const { model, panel, series, fields, uiRestrictions } = props; const handleChange = createChangeHandler(props.onChange, model); const handleSelectChange = createSelectHandler(handleChange); - const restrictFields = model.type === METRIC_TYPES.CARDINALITY ? [] : [KBN_FIELD_TYPES.NUMBER]; - + const restrictFields = getSupportedFieldsByMetricType(model.type); const indexPattern = (series.override_index_pattern && series.series_index_pattern) || panel.index_pattern; const htmlId = htmlIdGenerator(); From 42bf37cdab4aa56ff1d0fa1a7b5f4a1496adb03c Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Mon, 15 Jun 2020 09:21:36 -0700 Subject: [PATCH 2/5] Merge branch 'master' of github.com:elastic/kibana into issue-52426-tsvb-support-for-histograms From 016ae3bf16bc78fe303d09e774d4ec698c2e7a71 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 7 Jul 2020 09:40:36 -0700 Subject: [PATCH 3/5] Adding support to filter ratio; updating test --- .../vis_type_timeseries/common/constants.ts | 32 ------------ .../components/aggs/filter_ratio.js | 4 +- .../components/aggs/histogram_support.test.js | 26 +++++++--- .../public/test_utils/index.ts | 49 +++++++++++++++++++ 4 files changed, 70 insertions(+), 41 deletions(-) create mode 100644 src/plugins/vis_type_timeseries/public/test_utils/index.ts diff --git a/src/plugins/vis_type_timeseries/common/constants.ts b/src/plugins/vis_type_timeseries/common/constants.ts index c71c36d1a3cf4..fc402d6ab7db5 100644 --- a/src/plugins/vis_type_timeseries/common/constants.ts +++ b/src/plugins/vis_type_timeseries/common/constants.ts @@ -18,35 +18,3 @@ */ export const MAX_BUCKETS_SETTING = 'metrics:max_buckets'; - -// Tests Constants -export const UI_RESTRICTIONS = { '*': true }; -export const INDEX_PATTERN = 'some-pattern'; -export const FIELDS = { - [INDEX_PATTERN]: [ - { - type: 'date', - name: '@timestamp', - }, - { - type: 'number', - name: 'system.cpu.user.pct', - }, - { - type: 'histogram', - name: 'histogram_value', - }, - ], -}; -export const METRIC = { - type: 'avg', - field: 'system.cpu.user.pct', -}; -export const SERIES = { - metrics: [METRIC], -}; -export const PANEL = { - type: 'timeseries', - index_pattern: INDEX_PATTERN, - series: SERIES, -}; diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js index b5311e3832da4..dbb6bd771634f 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js @@ -57,7 +57,9 @@ export const FilterRatioAgg = (props) => { const htmlId = htmlIdGenerator(); const restrictFields = - model.metric_agg === METRIC_TYPES.CARDINALITY ? [] : [KBN_FIELD_TYPES.NUMBER]; + model.metric_agg === METRIC_TYPES.CARDINALITY + ? [] + : [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.HISTOGRAM]; return ( { +import { FIELDS, METRIC, SERIES, PANEL } from '../../../test_utils'; +const runTest = (aggType, name, test, additionalProps = {}) => { describe(aggType, () => { const metric = { ...METRIC, type: aggType, field: 'histogram_value', + ...additionalProps, }; const series = { ...SERIES, metrics: [metric] }; const panel = { ...PANEL, series }; @@ -55,20 +56,29 @@ const runTest = (aggType, name, test) => { describe('Histogram Types', () => { describe('supported', () => { - const shouldHaveHistogramSupport = (aggType) => { - runTest(aggType, 'supports', (wrapper) => - expect(wrapper.find(FieldSelect).at(0).props().restrict).toContain('histogram') + const shouldHaveHistogramSupport = (aggType, additionalProps = {}) => { + runTest( + aggType, + 'supports', + (wrapper) => + expect(wrapper.find(FieldSelect).at(0).props().restrict).toContain('histogram'), + additionalProps ); }; shouldHaveHistogramSupport('avg'); shouldHaveHistogramSupport('value_count'); shouldHaveHistogramSupport('percentile'); shouldHaveHistogramSupport('percentile_rank'); + shouldHaveHistogramSupport('filter_ratio', { metric_agg: 'avg' }); }); describe('not supported', () => { - const shouldNotHaveHistogramSupport = (aggType) => { - runTest(aggType, 'does not support', (wrapper) => - expect(wrapper.find(FieldSelect).at(0).props().restrict).not.toContain('histogram') + const shouldNotHaveHistogramSupport = (aggType, additionalProps = {}) => { + runTest( + aggType, + 'does not support', + (wrapper) => + expect(wrapper.find(FieldSelect).at(0).props().restrict).not.toContain('histogram'), + additionalProps ); }; shouldNotHaveHistogramSupport('cardinality'); diff --git a/src/plugins/vis_type_timeseries/public/test_utils/index.ts b/src/plugins/vis_type_timeseries/public/test_utils/index.ts new file mode 100644 index 0000000000000..affa718dc9ea6 --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/test_utils/index.ts @@ -0,0 +1,49 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const UI_RESTRICTIONS = { '*': true }; +export const INDEX_PATTERN = 'some-pattern'; +export const FIELDS = { + [INDEX_PATTERN]: [ + { + type: 'date', + name: '@timestamp', + }, + { + type: 'number', + name: 'system.cpu.user.pct', + }, + { + type: 'histogram', + name: 'histogram_value', + }, + ], +}; +export const METRIC = { + type: 'avg', + field: 'system.cpu.user.pct', +}; +export const SERIES = { + metrics: [METRIC], +}; +export const PANEL = { + type: 'timeseries', + index_pattern: INDEX_PATTERN, + series: SERIES, +}; From 62d2b6a9e8e9d96d876f3a997e4c8ff61e8b2235 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Wed, 8 Jul 2020 11:36:39 -0700 Subject: [PATCH 4/5] Limist aggs for filter_ratio and histogram fields; add test for AggSelect; Fixes #70984 --- .../common/metric_types.js | 1 + .../components/aggs/agg_select.test.tsx | 184 ++++++++++++++++++ .../components/aggs/agg_select.tsx | 17 ++ .../components/aggs/filter_ratio.js | 12 +- .../components/aggs/histogram_support.test.js | 2 +- .../application/components/aggs/std_agg.js | 1 + .../public/test_utils/index.ts | 1 + 7 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 src/plugins/vis_type_timeseries/public/application/components/aggs/agg_select.test.tsx diff --git a/src/plugins/vis_type_timeseries/common/metric_types.js b/src/plugins/vis_type_timeseries/common/metric_types.js index 082ff21cf17c6..05836a6df410a 100644 --- a/src/plugins/vis_type_timeseries/common/metric_types.js +++ b/src/plugins/vis_type_timeseries/common/metric_types.js @@ -29,6 +29,7 @@ export const METRIC_TYPES = { CARDINALITY: 'cardinality', VALUE_COUNT: 'value_count', AVERAGE: 'avg', + SUM: 'sum', }; export const EXTENDED_STATS_TYPES = [ diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_select.test.tsx b/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_select.test.tsx new file mode 100644 index 0000000000000..968fa5384e1d8 --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_select.test.tsx @@ -0,0 +1,184 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { mountWithIntl } from 'test_utils/enzyme_helpers'; +import { AggSelect } from './agg_select'; +import { METRIC, SERIES } from '../../../test_utils'; +import { EuiComboBox } from '@elastic/eui'; + +describe('TSVB AggSelect', () => { + const setup = (panelType: string, value: string) => { + const metric = { + ...METRIC, + type: 'filter_ratio', + field: 'histogram_value', + }; + const series = { ...SERIES, metrics: [metric] }; + + const wrapper = mountWithIntl( +
+ +
+ ); + return wrapper; + }; + + it('should only display filter ratio compattible aggs', () => { + const wrapper = setup('filter_ratio', 'avg'); + expect(wrapper.find(EuiComboBox).props().options).toMatchInlineSnapshot(` + Array [ + Object { + "label": "Average", + "value": "avg", + }, + Object { + "label": "Cardinality", + "value": "cardinality", + }, + Object { + "label": "Count", + "value": "count", + }, + Object { + "label": "Positive Rate", + "value": "positive_rate", + }, + Object { + "label": "Max", + "value": "max", + }, + Object { + "label": "Min", + "value": "min", + }, + Object { + "label": "Sum", + "value": "sum", + }, + Object { + "label": "Value Count", + "value": "value_count", + }, + ] + `); + }); + + it('should only display histogram compattible aggs', () => { + const wrapper = setup('histogram', 'avg'); + expect(wrapper.find(EuiComboBox).props().options).toMatchInlineSnapshot(` + Array [ + Object { + "label": "Average", + "value": "avg", + }, + Object { + "label": "Count", + "value": "count", + }, + Object { + "label": "Sum", + "value": "sum", + }, + Object { + "label": "Value Count", + "value": "value_count", + }, + ] + `); + }); + + it('should only display metrics compattible aggs', () => { + const wrapper = setup('metrics', 'avg'); + expect(wrapper.find(EuiComboBox).props().options).toMatchInlineSnapshot(` + Array [ + Object { + "label": "Average", + "value": "avg", + }, + Object { + "label": "Cardinality", + "value": "cardinality", + }, + Object { + "label": "Count", + "value": "count", + }, + Object { + "label": "Filter Ratio", + "value": "filter_ratio", + }, + Object { + "label": "Positive Rate", + "value": "positive_rate", + }, + Object { + "label": "Max", + "value": "max", + }, + Object { + "label": "Min", + "value": "min", + }, + Object { + "label": "Percentile", + "value": "percentile", + }, + Object { + "label": "Percentile Rank", + "value": "percentile_rank", + }, + Object { + "label": "Static Value", + "value": "static", + }, + Object { + "label": "Std. Deviation", + "value": "std_deviation", + }, + Object { + "label": "Sum", + "value": "sum", + }, + Object { + "label": "Sum of Squares", + "value": "sum_of_squares", + }, + Object { + "label": "Top Hit", + "value": "top_hit", + }, + Object { + "label": "Value Count", + "value": "value_count", + }, + Object { + "label": "Variance", + "value": "variance", + }, + ] + `); + }); +}); diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_select.tsx index 6fa1a2adaa08e..7701d351e5478 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/agg_select.tsx @@ -225,6 +225,19 @@ const specialAggs: AggSelectOption[] = [ }, ]; +const FILTER_RATIO_AGGS = [ + 'avg', + 'cardinality', + 'count', + 'positive_rate', + 'max', + 'min', + 'sum', + 'value_count', +]; + +const HISTOGRAM_AGGS = ['avg', 'count', 'sum', 'value_count']; + const allAggOptions = [...metricAggs, ...pipelineAggs, ...siblingAggs, ...specialAggs]; function filterByPanelType(panelType: string) { @@ -257,6 +270,10 @@ export function AggSelect(props: AggSelectUiProps) { let options: EuiComboBoxOptionOption[]; if (panelType === 'metrics') { options = metricAggs; + } else if (panelType === 'filter_ratio') { + options = metricAggs.filter((m) => FILTER_RATIO_AGGS.includes(`${m.value}`)); + } else if (panelType === 'histogram') { + options = metricAggs.filter((m) => HISTOGRAM_AGGS.includes(`${m.value}`)); } else { const disableSiblingAggs = (agg: AggSelectOption) => ({ ...agg, diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js index dbb6bd771634f..9e6e171b28205 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js @@ -38,6 +38,14 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { KBN_FIELD_TYPES } from '../../../../../../plugins/data/public'; import { METRIC_TYPES } from '../../../../../../plugins/vis_type_timeseries/common/metric_types'; +const isFieldHistogram = (fields, indexPattern, field) => { + const indexFields = fields[indexPattern]; + if (!indexFields) return false; + const fieldObject = indexFields.find((f) => f.name === field); + if (!fieldObject) return false; + return fieldObject.type === KBN_FIELD_TYPES.HISTOGRAM; +}; + export const FilterRatioAgg = (props) => { const { series, fields, panel } = props; @@ -131,7 +139,9 @@ export const FilterRatioAgg = (props) => { diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/histogram_support.test.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/histogram_support.test.js index 1f0c8ca4f2cb5..7af33ba11f247 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/histogram_support.test.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/histogram_support.test.js @@ -66,6 +66,7 @@ describe('Histogram Types', () => { ); }; shouldHaveHistogramSupport('avg'); + shouldHaveHistogramSupport('sum'); shouldHaveHistogramSupport('value_count'); shouldHaveHistogramSupport('percentile'); shouldHaveHistogramSupport('percentile_rank'); @@ -84,7 +85,6 @@ describe('Histogram Types', () => { shouldNotHaveHistogramSupport('cardinality'); shouldNotHaveHistogramSupport('max'); shouldNotHaveHistogramSupport('min'); - shouldNotHaveHistogramSupport('sum'); shouldNotHaveHistogramSupport('variance'); shouldNotHaveHistogramSupport('sum_of_squares'); shouldNotHaveHistogramSupport('std_deviation'); diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/std_agg.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/std_agg.js index a132828157faf..17e162a7febe5 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/std_agg.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/std_agg.js @@ -42,6 +42,7 @@ function getSupportedFieldsByMetricType(type) { return Object.values(KBN_FIELD_TYPES).filter((type) => type !== KBN_FIELD_TYPES.HISTOGRAM); case METRIC_TYPES.VALUE_COUNT: case METRIC_TYPES.AVERAGE: + case METRIC_TYPES.SUM: return [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.HISTOGRAM]; default: return [KBN_FIELD_TYPES.NUMBER]; diff --git a/src/plugins/vis_type_timeseries/public/test_utils/index.ts b/src/plugins/vis_type_timeseries/public/test_utils/index.ts index affa718dc9ea6..96ecc89b70c2d 100644 --- a/src/plugins/vis_type_timeseries/public/test_utils/index.ts +++ b/src/plugins/vis_type_timeseries/public/test_utils/index.ts @@ -36,6 +36,7 @@ export const FIELDS = { ], }; export const METRIC = { + id: 'sample_metric', type: 'avg', field: 'system.cpu.user.pct', }; From cfca4ab7384e896c852ae45557b16268c9ea90be Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Thu, 9 Jul 2020 11:16:19 -0700 Subject: [PATCH 5/5] Ensure only compatible fields are displayed for filter ratio metric aggs --- .../components/aggs/filter_ratio.js | 9 +- .../components/aggs/filter_ratio.test.js | 136 ++++++++++++++++++ .../application/components/aggs/std_agg.js | 16 +-- .../get_supported_fields_by_metric_type.js | 34 +++++ ...et_supported_fields_by_metric_type.test.js | 44 ++++++ 5 files changed, 217 insertions(+), 22 deletions(-) create mode 100644 src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.test.js create mode 100644 src/plugins/vis_type_timeseries/public/application/components/lib/get_supported_fields_by_metric_type.js create mode 100644 src/plugins/vis_type_timeseries/public/application/components/lib/get_supported_fields_by_metric_type.test.js diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js index 9e6e171b28205..2aa994c09a2ad 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/filter_ratio.js @@ -36,7 +36,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { KBN_FIELD_TYPES } from '../../../../../../plugins/data/public'; -import { METRIC_TYPES } from '../../../../../../plugins/vis_type_timeseries/common/metric_types'; +import { getSupportedFieldsByMetricType } from '../lib/get_supported_fields_by_metric_type'; const isFieldHistogram = (fields, indexPattern, field) => { const indexFields = fields[indexPattern]; @@ -64,11 +64,6 @@ export const FilterRatioAgg = (props) => { const model = { ...defaults, ...props.model }; const htmlId = htmlIdGenerator(); - const restrictFields = - model.metric_agg === METRIC_TYPES.CARDINALITY - ? [] - : [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.HISTOGRAM]; - return ( { { + const setup = (metric) => { + const series = { ...SERIES, metrics: [metric] }; + const panel = { ...PANEL, series }; + + const wrapper = mountWithIntl( +
+ +
+ ); + return wrapper; + }; + + describe('histogram support', () => { + it('should only display histogram compattible aggs', () => { + const metric = { + ...METRIC, + metric_agg: 'avg', + field: 'histogram_value', + }; + const wrapper = setup(metric); + expect(wrapper.find(EuiComboBox).at(1).props().options).toMatchInlineSnapshot(` + Array [ + Object { + "label": "Average", + "value": "avg", + }, + Object { + "label": "Count", + "value": "count", + }, + Object { + "label": "Sum", + "value": "sum", + }, + Object { + "label": "Value Count", + "value": "value_count", + }, + ] + `); + }); + const shouldNotHaveHistogramField = (agg) => { + it(`should not have histogram fields for ${agg}`, () => { + const metric = { + ...METRIC, + metric_agg: agg, + field: '', + }; + const wrapper = setup(metric); + expect(wrapper.find(EuiComboBox).at(2).props().options).toMatchInlineSnapshot(` + Array [ + Object { + "label": "number", + "options": Array [ + Object { + "label": "system.cpu.user.pct", + "value": "system.cpu.user.pct", + }, + ], + }, + ] + `); + }); + }; + shouldNotHaveHistogramField('max'); + shouldNotHaveHistogramField('min'); + shouldNotHaveHistogramField('positive_rate'); + + it(`should not have histogram fields for cardinality`, () => { + const metric = { + ...METRIC, + metric_agg: 'cardinality', + field: '', + }; + const wrapper = setup(metric); + expect(wrapper.find(EuiComboBox).at(2).props().options).toMatchInlineSnapshot(` + Array [ + Object { + "label": "date", + "options": Array [ + Object { + "label": "@timestamp", + "value": "@timestamp", + }, + ], + }, + Object { + "label": "number", + "options": Array [ + Object { + "label": "system.cpu.user.pct", + "value": "system.cpu.user.pct", + }, + ], + }, + ] + `); + }); + }); +}); diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/std_agg.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/std_agg.js index 17e162a7febe5..b882981f6b5c7 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/std_agg.js +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/std_agg.js @@ -33,21 +33,7 @@ import { EuiSpacer, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { KBN_FIELD_TYPES } from '../../../../../../plugins/data/public'; -import { METRIC_TYPES } from '../../../../../../plugins/vis_type_timeseries/common/metric_types'; - -function getSupportedFieldsByMetricType(type) { - switch (type) { - case METRIC_TYPES.CARDINALITY: - return Object.values(KBN_FIELD_TYPES).filter((type) => type !== KBN_FIELD_TYPES.HISTOGRAM); - case METRIC_TYPES.VALUE_COUNT: - case METRIC_TYPES.AVERAGE: - case METRIC_TYPES.SUM: - return [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.HISTOGRAM]; - default: - return [KBN_FIELD_TYPES.NUMBER]; - } -} +import { getSupportedFieldsByMetricType } from '../lib/get_supported_fields_by_metric_type'; export function StandardAgg(props) { const { model, panel, series, fields, uiRestrictions } = props; diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/get_supported_fields_by_metric_type.js b/src/plugins/vis_type_timeseries/public/application/components/lib/get_supported_fields_by_metric_type.js new file mode 100644 index 0000000000000..c1d7aa9d40bd9 --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/get_supported_fields_by_metric_type.js @@ -0,0 +1,34 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { KBN_FIELD_TYPES } from '../../../../../../plugins/data/public'; +import { METRIC_TYPES } from '../../../../../../plugins/vis_type_timeseries/common/metric_types'; + +export function getSupportedFieldsByMetricType(type) { + switch (type) { + case METRIC_TYPES.CARDINALITY: + return Object.values(KBN_FIELD_TYPES).filter((t) => t !== KBN_FIELD_TYPES.HISTOGRAM); + case METRIC_TYPES.VALUE_COUNT: + case METRIC_TYPES.AVERAGE: + case METRIC_TYPES.SUM: + return [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.HISTOGRAM]; + default: + return [KBN_FIELD_TYPES.NUMBER]; + } +} diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/get_supported_fields_by_metric_type.test.js b/src/plugins/vis_type_timeseries/public/application/components/lib/get_supported_fields_by_metric_type.test.js new file mode 100644 index 0000000000000..3cd3fac191bf1 --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/get_supported_fields_by_metric_type.test.js @@ -0,0 +1,44 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { getSupportedFieldsByMetricType } from './get_supported_fields_by_metric_type'; + +describe('getSupportedFieldsByMetricType', () => { + const shouldHaveHistogramAndNumbers = (type) => + it(`should return numbers and histogram for ${type}`, () => { + expect(getSupportedFieldsByMetricType(type)).toEqual(['number', 'histogram']); + }); + const shouldHaveOnlyNumbers = (type) => + it(`should return only numbers for ${type}`, () => { + expect(getSupportedFieldsByMetricType(type)).toEqual(['number']); + }); + + shouldHaveHistogramAndNumbers('value_count'); + shouldHaveHistogramAndNumbers('avg'); + shouldHaveHistogramAndNumbers('sum'); + + shouldHaveOnlyNumbers('positive_rate'); + shouldHaveOnlyNumbers('std_deviation'); + shouldHaveOnlyNumbers('max'); + shouldHaveOnlyNumbers('min'); + + it(`should return everything but histogram for cardinality`, () => { + expect(getSupportedFieldsByMetricType('cardinality')).not.toContain('histogram'); + }); +});