diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_bucket_size.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_bucket_size.js index b9ce76f7176b45..ad20f434bedf54 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_bucket_size.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_bucket_size.js @@ -45,8 +45,6 @@ const calculateBucketData = (timeInterval, capabilities) => { if (converted) { intervalString = converted.value + converted.unit; } - - intervalString = undefined; } else { intervalString = '1ms'; } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/index.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/index.js index de93ff22fa5980..e2211e4843bd68 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/index.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/index.js @@ -15,6 +15,6 @@ export { getLastMetric } from './get_last_metric'; export { getSiblingAggValue } from './get_sibling_agg_value'; export { getSplits } from './get_splits'; export { getTimerange } from './get_timerange'; -export { mapBucket } from './map_bucket'; export { parseSettings } from './parse_settings'; +export { mapEmptyToZero } from './map_empty_to_zero'; export { overwrite } from './overwrite'; diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_bucket.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_bucket.js deleted file mode 100644 index dd48aa3705d41c..00000000000000 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_bucket.js +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { getAggValue } from './get_agg_value'; - -export function mapBucket(metric) { - return (bucket) => [bucket.key, getAggValue(bucket, metric)]; -} diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_bucket.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_empty_to_zero.test.ts similarity index 53% rename from src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_bucket.test.js rename to src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_empty_to_zero.test.ts index 63ba294b7dc46a..b5f1adc3f02022 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_bucket.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_empty_to_zero.test.ts @@ -6,39 +6,47 @@ * Side Public License, v 1. */ -import { mapBucket } from './map_bucket'; +import { mapEmptyToZero } from './map_empty_to_zero'; -describe('mapBucket(metric)', () => { +describe('mapEmptyToZero(metric, buckets)', () => { test('returns bucket key and value for basic metric', () => { const metric = { id: 'AVG', type: 'avg' }; - const bucket = { - key: 1234, - AVG: { value: 1 }, - }; - expect(mapBucket(metric)(bucket)).toEqual([1234, 1]); + const buckets = [ + { + key: 1234, + AVG: { value: 1 }, + }, + ]; + expect(mapEmptyToZero(metric, buckets)).toEqual([[1234, 1]]); }); test('returns bucket key and value for std_deviation', () => { const metric = { id: 'STDDEV', type: 'std_deviation' }; - const bucket = { - key: 1234, - STDDEV: { std_deviation: 1 }, - }; - expect(mapBucket(metric)(bucket)).toEqual([1234, 1]); + const buckets = [ + { + key: 1234, + STDDEV: { std_deviation: 1 }, + }, + ]; + expect(mapEmptyToZero(metric, buckets)).toEqual([[1234, 1]]); }); test('returns bucket key and value for percentiles', () => { const metric = { id: 'PCT', type: 'percentile', percent: 50 }; - const bucket = { - key: 1234, - PCT: { values: { '50.0': 1 } }, - }; - expect(mapBucket(metric)(bucket)).toEqual([1234, 1]); + const buckets = [ + { + key: 1234, + PCT: { values: { '50.0': 1 } }, + }, + ]; + expect(mapEmptyToZero(metric, buckets)).toEqual([[1234, 1]]); }); test('returns bucket key and value for derivative', () => { const metric = { id: 'DERV', type: 'derivative', field: 'io', unit: '1s' }; - const bucket = { - key: 1234, - DERV: { value: 100, normalized_value: 1 }, - }; - expect(mapBucket(metric)(bucket)).toEqual([1234, 1]); + const buckets = [ + { + key: 1234, + DERV: { value: 100, normalized_value: 1 }, + }, + ]; + expect(mapEmptyToZero(metric, buckets)).toEqual([[1234, 1]]); }); }); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_empty_to_zero.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_empty_to_zero.ts new file mode 100644 index 00000000000000..0490193a76e81a --- /dev/null +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_empty_to_zero.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +// @ts-expect-error not typed yet +import { getAggValue } from './get_agg_value'; +import { METRIC_TYPES } from '../../../../../data/common'; +import type { Metric } from '../../../../common/types'; + +export const mapEmptyToZero = (metric: Metric, buckets: any[]) => { + // Metric types where an empty set equals `zero` + const isSettableToZero = [ + METRIC_TYPES.COUNT, + METRIC_TYPES.CARDINALITY, + METRIC_TYPES.SUM, + ].includes(metric.type as METRIC_TYPES); + + return isSettableToZero && !buckets.length + ? [[undefined, 0]] + : buckets.map((bucket) => [bucket.key, getAggValue(bucket, metric)]); +}; diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/math.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/math.js index d3cff76524ee36..a6addc8ba0e53b 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/math.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/math.js @@ -10,10 +10,7 @@ import { convertIntervalToUnit } from '../../helpers/unit_to_seconds'; const percentileValueMatch = /\[([0-9\.]+)\]$/; import { startsWith, flatten, values, first, last } from 'lodash'; -import { getDefaultDecoration } from '../../helpers/get_default_decoration'; -import { getSiblingAggValue } from '../../helpers/get_sibling_agg_value'; -import { getSplits } from '../../helpers/get_splits'; -import { mapBucket } from '../../helpers/map_bucket'; +import { getDefaultDecoration, getSiblingAggValue, getSplits, mapEmptyToZero } from '../../helpers'; import { evaluate } from '@kbn/tinymath'; export function mathAgg(resp, panel, series, meta, extractFields) { @@ -44,7 +41,7 @@ export function mathAgg(resp, panel, series, meta, extractFields) { } else { const percentileMatch = v.field.match(percentileValueMatch); const m = percentileMatch ? { ...metric, percent: percentileMatch[1] } : { ...metric }; - acc[v.name] = split.timeseries.buckets.map(mapBucket(m)); + acc[v.name] = mapEmptyToZero(m, split.timeseries.buckets); } return acc; }, {}); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.js index b9a4139a723138..cc406041ad8742 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.js @@ -6,10 +6,7 @@ * Side Public License, v 1. */ -import { getDefaultDecoration } from '../../helpers/get_default_decoration'; -import { getSplits } from '../../helpers/get_splits'; -import { getLastMetric } from '../../helpers/get_last_metric'; -import { mapBucket } from '../../helpers/map_bucket'; +import { getDefaultDecoration, getSplits, getLastMetric, mapEmptyToZero } from '../../helpers'; import { METRIC_TYPES } from '../../../../../common/enums'; export function stdMetric(resp, panel, series, meta, extractFields) { @@ -26,7 +23,7 @@ export function stdMetric(resp, panel, series, meta, extractFields) { const decoration = getDefaultDecoration(series); (await getSplits(resp, panel, series, meta, extractFields)).forEach((split) => { - const data = split.timeseries.buckets.map(mapBucket(metric)); + const data = mapEmptyToZero(metric, split.timeseries.buckets); results.push({ id: `${split.id}`, label: split.label, diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/std_metric.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/std_metric.js index a648258745a15e..140212c2ec9070 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/std_metric.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/response_processors/table/std_metric.js @@ -6,9 +6,7 @@ * Side Public License, v 1. */ -import { getSplits } from '../../helpers/get_splits'; -import { getLastMetric } from '../../helpers/get_last_metric'; -import { mapBucket } from '../../helpers/map_bucket'; +import { getSplits, getLastMetric, mapEmptyToZero } from '../../helpers'; import { METRIC_TYPES } from '../../../../../common/enums'; export function stdMetric(bucket, panel, series, meta, extractFields) { @@ -32,7 +30,7 @@ export function stdMetric(bucket, panel, series, meta, extractFields) { }; (await getSplits(fakeResp, panel, series, meta, extractFields)).forEach((split) => { - const data = split.timeseries.buckets.map(mapBucket(metric)); + const data = mapEmptyToZero(metric, split.timeseries.buckets); results.push({ id: split.id, label: split.label,