mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[TSVB][Lens] Added support of Variance aggregation for navigate to lens (#143209)
* Added support of variance for navigate to lens * Fixed types * Fixed type * Fix variance for moving average and derivative Co-authored-by: Stratoula Kalafateli <efstratia.kalafateli@elastic.co> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
3cb5fedca7
commit
3cf9778127
10 changed files with 123 additions and 2 deletions
|
@ -31,5 +31,6 @@ export { convertToDateHistogramColumn } from './date_histogram';
|
|||
export { convertToTermsColumn } from './terms';
|
||||
export { convertToCounterRateColumn } from './counter_rate';
|
||||
export { convertToStandartDeviationColumn } from './std_deviation';
|
||||
export { convertVarianceToFormulaColumn } from './variance';
|
||||
|
||||
export * from './types';
|
||||
|
|
|
@ -237,7 +237,11 @@ const convertMovingAvgOrDerivativeToColumns = (
|
|||
const [nestedFieldId, _] = subMetricField?.split('[') ?? [];
|
||||
// support nested aggs with formula
|
||||
const additionalSubFunction = metrics.find(({ id }) => id === nestedFieldId);
|
||||
if (additionalSubFunction || pipelineAgg.name === 'counter_rate') {
|
||||
if (
|
||||
additionalSubFunction ||
|
||||
pipelineAgg.name === 'counter_rate' ||
|
||||
subFunctionMetric.type === 'variance'
|
||||
) {
|
||||
const formula = getPipelineSeriesFormula(metric, metrics, subFunctionMetric, {
|
||||
metaValue,
|
||||
reducedTimeRange,
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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 { stubLogstashDataView } from '@kbn/data-views-plugin/common/data_view.stub';
|
||||
import { createSeries } from '../__mocks__';
|
||||
import { FormulaColumn } from './types';
|
||||
import { Metric } from '../../../../common/types';
|
||||
import { TSVB_METRIC_TYPES } from '../../../../common/enums';
|
||||
import { convertVarianceToFormulaColumn } from './variance';
|
||||
|
||||
describe('convertVarianceToFormulaColumn', () => {
|
||||
const series = createSeries();
|
||||
const dataView = stubLogstashDataView;
|
||||
const metric: Metric = {
|
||||
id: 'some-id',
|
||||
type: TSVB_METRIC_TYPES.VARIANCE,
|
||||
};
|
||||
const field = dataView.fields[0].name;
|
||||
|
||||
test.each<
|
||||
[string, Parameters<typeof convertVarianceToFormulaColumn>, Partial<FormulaColumn> | null]
|
||||
>([
|
||||
['null if field is not provided', [{ series, metrics: [metric], dataView }], null],
|
||||
[
|
||||
'correct formula column',
|
||||
[{ series, metrics: [{ ...metric, field }], dataView }],
|
||||
{
|
||||
meta: { metricId: 'some-id' },
|
||||
operationType: 'formula',
|
||||
params: {
|
||||
formula: 'pow(standard_deviation(bytes), 2)',
|
||||
},
|
||||
},
|
||||
],
|
||||
])('should return %s', (_, input, expected) => {
|
||||
if (expected === null) {
|
||||
expect(convertVarianceToFormulaColumn(...input)).toBeNull();
|
||||
} else {
|
||||
expect(convertVarianceToFormulaColumn(...input)).toEqual(expect.objectContaining(expected));
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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 { getFormulaEquivalent } from '../metrics';
|
||||
import { createFormulaColumn } from './formula';
|
||||
import { CommonColumnsConverterArgs } from './types';
|
||||
|
||||
export const convertVarianceToFormulaColumn = (
|
||||
{ series, metrics, dataView }: CommonColumnsConverterArgs,
|
||||
reducedTimeRange?: string
|
||||
) => {
|
||||
const metric = metrics[metrics.length - 1];
|
||||
|
||||
const field = metric.field ? dataView.getFieldByName(metric.field) : undefined;
|
||||
if (!field) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const script = getFormulaEquivalent(metric, metrics, {
|
||||
reducedTimeRange,
|
||||
timeShift: series.offset_time,
|
||||
});
|
||||
if (!script) return null;
|
||||
return createFormulaColumn(script, { series, metric, dataView });
|
||||
};
|
|
@ -62,6 +62,12 @@ describe('getFormulaEquivalent', () => {
|
|||
mode: 'upper',
|
||||
};
|
||||
|
||||
const variance: Metric = {
|
||||
id: 'some-random-value',
|
||||
type: TSVB_METRIC_TYPES.VARIANCE,
|
||||
field: 'test-1',
|
||||
};
|
||||
|
||||
const sibblingPipelineMetric: Metric[] = [
|
||||
{
|
||||
id: 'test-1',
|
||||
|
@ -141,6 +147,11 @@ describe('getFormulaEquivalent', () => {
|
|||
[stdDeviationMetricWithUpperMode, [stdDeviationMetricWithUpperMode], {}],
|
||||
'average(test-1) + 1.5 * standard_deviation(test-1)',
|
||||
],
|
||||
[
|
||||
'correct formula if metric is variance',
|
||||
[variance, [variance], {}],
|
||||
'pow(standard_deviation(test-1), 2)',
|
||||
],
|
||||
[
|
||||
'correct formula if metric is supported',
|
||||
[supportedMetric, [supportedMetric], {}],
|
||||
|
|
|
@ -144,6 +144,12 @@ export const getFormulaEquivalent = (
|
|||
case 'static': {
|
||||
return `${currentMetric.value}`;
|
||||
}
|
||||
case 'variance': {
|
||||
return `${aggFormula}(standard_deviation(${currentMetric.field}${addAdditionalArgs({
|
||||
reducedTimeRange,
|
||||
timeShift,
|
||||
})}), 2)`;
|
||||
}
|
||||
case 'std_deviation': {
|
||||
if (currentMetric.mode === 'lower') {
|
||||
return `average(${currentMetric.field}${addAdditionalArgs({
|
||||
|
|
|
@ -55,6 +55,7 @@ interface LocalSupportedMetrics {
|
|||
[TSVB_METRIC_TYPES.STATIC]: Metric<typeof Operations.STATIC_VALUE>;
|
||||
[TSVB_METRIC_TYPES.POSITIVE_RATE]: Metric<typeof Operations.COUNTER_RATE>;
|
||||
[TSVB_METRIC_TYPES.MOVING_AVERAGE]: Metric<typeof Operations.MOVING_AVERAGE>;
|
||||
[TSVB_METRIC_TYPES.VARIANCE]: Metric<typeof Operations.FORMULA>;
|
||||
}
|
||||
|
||||
type UnsupportedSupportedMetrics = Exclude<MetricType, keyof LocalSupportedMetrics>;
|
||||
|
@ -250,6 +251,15 @@ export const SUPPORTED_METRICS: SupportedMetrics = {
|
|||
supportedPanelTypes,
|
||||
supportedTimeRangeModes,
|
||||
},
|
||||
variance: {
|
||||
name: 'formula',
|
||||
isFormula: true,
|
||||
formula: 'pow',
|
||||
isFullReference: false,
|
||||
isFieldRequired: true,
|
||||
supportedPanelTypes,
|
||||
supportedTimeRangeModes,
|
||||
},
|
||||
} as const;
|
||||
|
||||
type SupportedMetricsKeys = keyof LocalSupportedMetrics;
|
||||
|
|
|
@ -23,6 +23,7 @@ const mockConvertToStaticValueColumn = jest.fn();
|
|||
const mockConvertStaticValueToFormulaColumn = jest.fn();
|
||||
const mockConvertToStandartDeviationColumn = jest.fn();
|
||||
const mockConvertMetricAggregationColumnWithoutSpecialParams = jest.fn();
|
||||
const mockConvertVarianceToFormulaColumn = jest.fn();
|
||||
|
||||
jest.mock('../convert', () => ({
|
||||
convertMathToFormulaColumn: jest.fn(() => mockConvertMathToFormulaColumn()),
|
||||
|
@ -38,6 +39,7 @@ jest.mock('../convert', () => ({
|
|||
convertMetricAggregationColumnWithoutSpecialParams: jest.fn(() =>
|
||||
mockConvertMetricAggregationColumnWithoutSpecialParams()
|
||||
),
|
||||
convertVarianceToFormulaColumn: jest.fn(() => mockConvertVarianceToFormulaColumn()),
|
||||
}));
|
||||
|
||||
describe('getMetricsColumns', () => {
|
||||
|
@ -163,6 +165,11 @@ describe('getMetricsColumns', () => {
|
|||
],
|
||||
mockConvertToStandartDeviationColumn,
|
||||
],
|
||||
[
|
||||
'call convertVarianceToFormulaColumn if metric type is variance',
|
||||
[createSeries({ metrics: [{ type: TSVB_METRIC_TYPES.VARIANCE, id: '1' }] }), dataView, 1],
|
||||
mockConvertVarianceToFormulaColumn,
|
||||
],
|
||||
[
|
||||
'call convertMetricAggregationColumnWithoutSpecialParams if metric type is another supported type',
|
||||
[createSeries({ metrics: [{ type: METRIC_TYPES.AVG, id: '1' }] }), dataView, 1],
|
||||
|
|
|
@ -25,6 +25,7 @@ import {
|
|||
convertMetricAggregationColumnWithoutSpecialParams,
|
||||
convertToCounterRateColumn,
|
||||
convertToStandartDeviationColumn,
|
||||
convertVarianceToFormulaColumn,
|
||||
} from '../convert';
|
||||
import { getValidColumns } from './columns';
|
||||
|
||||
|
@ -120,6 +121,10 @@ export const getMetricsColumns = (
|
|||
const column = convertToLastValueColumn(columnsConverterArgs, reducedTimeRange);
|
||||
return getValidColumns(column);
|
||||
}
|
||||
case 'variance': {
|
||||
const column = convertVarianceToFormulaColumn(columnsConverterArgs, reducedTimeRange);
|
||||
return getValidColumns(column);
|
||||
}
|
||||
case 'static': {
|
||||
const column = isStaticValueColumnSupported
|
||||
? convertToStaticValueColumn(columnsConverterArgs, {
|
||||
|
|
|
@ -144,7 +144,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('should not allow converting of unsupported aggregations', async () => {
|
||||
await visualBuilder.selectAggType('Variance');
|
||||
await visualBuilder.selectAggType('Sum of Squares');
|
||||
await visualBuilder.setFieldForAggregation('machine.ram');
|
||||
|
||||
await header.waitUntilLoadingHasFinished();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue