diff --git a/src/plugins/vis_type_timeseries/common/metric_types.js b/src/plugins/vis_type_timeseries/common/metric_types.js
index 9dc6085b080e9..05836a6df410a 100644
--- a/src/plugins/vis_type_timeseries/common/metric_types.js
+++ b/src/plugins/vis_type_timeseries/common/metric_types.js
@@ -27,6 +27,9 @@ export const METRIC_TYPES = {
VARIANCE: 'variance',
SUM_OF_SQUARES: 'sum_of_squares',
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 b5311e3832da4..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,15 @@ 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];
+ 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;
@@ -56,9 +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];
-
return (
{
@@ -149,7 +156,7 @@ export const FilterRatioAgg = (props) => {
{
+ 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/histogram_support.test.js b/src/plugins/vis_type_timeseries/public/application/components/aggs/histogram_support.test.js
new file mode 100644
index 0000000000000..7af33ba11f247
--- /dev/null
+++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/histogram_support.test.js
@@ -0,0 +1,94 @@
+/*
+ * 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 '../../../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 };
+
+ it(name, () => {
+ const wrapper = mountWithIntl(
+
+ );
+ test(wrapper);
+ });
+ });
+};
+
+describe('Histogram Types', () => {
+ describe('supported', () => {
+ const shouldHaveHistogramSupport = (aggType, additionalProps = {}) => {
+ runTest(
+ aggType,
+ 'supports',
+ (wrapper) =>
+ expect(wrapper.find(FieldSelect).at(0).props().restrict).toContain('histogram'),
+ additionalProps
+ );
+ };
+ shouldHaveHistogramSupport('avg');
+ shouldHaveHistogramSupport('sum');
+ shouldHaveHistogramSupport('value_count');
+ shouldHaveHistogramSupport('percentile');
+ shouldHaveHistogramSupport('percentile_rank');
+ shouldHaveHistogramSupport('filter_ratio', { metric_agg: 'avg' });
+ });
+ describe('not supported', () => {
+ const shouldNotHaveHistogramSupport = (aggType, additionalProps = {}) => {
+ runTest(
+ aggType,
+ 'does not support',
+ (wrapper) =>
+ expect(wrapper.find(FieldSelect).at(0).props().restrict).not.toContain('histogram'),
+ additionalProps
+ );
+ };
+ shouldNotHaveHistogramSupport('cardinality');
+ shouldNotHaveHistogramSupport('max');
+ shouldNotHaveHistogramSupport('min');
+ 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.tsx b/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx
index a16f5aeefc49c..d02a16ade2bba 100644
--- a/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx
+++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/percentile_rank/percentile_rank.tsx
@@ -41,7 +41,7 @@ import { IFieldType, KBN_FIELD_TYPES } from '../../../../../../../plugins/data/p
import { MetricsItemsSchema, PanelSchema, SeriesItemsSchema } from '../../../../../common/types';
import { DragHandleProps } from '../../../../types';
-const RESTRICT_FIELDS = [KBN_FIELD_TYPES.NUMBER];
+const RESTRICT_FIELDS = [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.HISTOGRAM];
interface PercentileRankAggProps {
disableDelete: boolean;
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) => {
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');
+ });
+});
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..96ecc89b70c2d
--- /dev/null
+++ b/src/plugins/vis_type_timeseries/public/test_utils/index.ts
@@ -0,0 +1,50 @@
+/*
+ * 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 = {
+ id: 'sample_metric',
+ type: 'avg',
+ field: 'system.cpu.user.pct',
+};
+export const SERIES = {
+ metrics: [METRIC],
+};
+export const PANEL = {
+ type: 'timeseries',
+ index_pattern: INDEX_PATTERN,
+ series: SERIES,
+};