diff --git a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.test.tsx index 3471c82a43fa4..6ba5ed0056c38 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.test.tsx @@ -18,7 +18,6 @@ import { createMockedIndexPattern } from '../../mocks'; import { LastValueIndexPatternColumn } from './last_value'; import { lastValueOperation } from '.'; import type { FormBasedLayer } from '../../types'; -import type { IndexPattern } from '../../../../types'; import { TermsIndexPatternColumn } from './terms'; import { EuiSwitch, EuiSwitchEvent } from '@elastic/eui'; import { buildExpression, parseExpression } from '@kbn/expressions-plugin/common'; @@ -35,10 +34,9 @@ const defaultProps = { dataViews: dataViewPluginMocks.createStartContract(), data: dataPluginMock.createStartContract(), http: {} as HttpSetup, - indexPattern: { - ...createMockedIndexPattern(), + indexPattern: createMockedIndexPattern({ hasRestrictions: false, - } as IndexPattern, + }), operationDefinitionMap: {}, isFullscreen: false, toggleFullscreen: jest.fn(), @@ -87,7 +85,7 @@ describe('last_value', () => { const esAggsFn = lastValueOperation.toEsAggsFn( { ...lastValueColumn, params: { ...lastValueColumn.params } }, 'col1', - {} as IndexPattern, + createMockedIndexPattern(), layer, uiSettingsMock, [] @@ -110,7 +108,7 @@ describe('last_value', () => { const esAggsFn = lastValueOperation.toEsAggsFn( { ...lastValueColumn, params: { ...lastValueColumn.params, showArrayValues: true } }, 'col1', - {} as IndexPattern, + createMockedIndexPattern(), layer, uiSettingsMock, [] @@ -398,6 +396,23 @@ describe('last_value', () => { }) ).toEqual({ dataType: 'string', isBucketed: false, scale: 'ordinal' }); }); + + it('should return operation with the right type also for tsdb counter types', () => { + expect( + lastValueOperation.getPossibleOperationForField({ + aggregatable: true, + searchable: true, + name: 'test', + displayName: 'test', + type: 'number', + timeSeriesMetric: 'counter', + }) + ).toEqual({ + dataType: 'number', + isBucketed: false, + scale: 'ratio', + }); + }); }); describe('buildColumn', () => { @@ -882,10 +897,8 @@ describe('last_value', () => { }); describe('getErrorMessage', () => { - let indexPattern: IndexPattern; let errorLayer: FormBasedLayer; beforeEach(() => { - indexPattern = createMockedIndexPattern(); errorLayer = { columns: { col1: { @@ -903,9 +916,9 @@ describe('last_value', () => { }; }); it('returns undefined if sourceField exists and sortField is of type date ', () => { - expect(lastValueOperation.getErrorMessage!(errorLayer, 'col1', indexPattern)).toEqual( - undefined - ); + expect( + lastValueOperation.getErrorMessage!(errorLayer, 'col1', createMockedIndexPattern()) + ).toEqual(undefined); }); it('shows error message if the sourceField does not exist in index pattern', () => { errorLayer = { @@ -917,7 +930,7 @@ describe('last_value', () => { } as LastValueIndexPatternColumn, }, }; - expect(lastValueOperation.getErrorMessage!(errorLayer, 'col1', indexPattern)) + expect(lastValueOperation.getErrorMessage!(errorLayer, 'col1', createMockedIndexPattern())) .toMatchInlineSnapshot(` Array [ Object { @@ -968,7 +981,7 @@ describe('last_value', () => { } as LastValueIndexPatternColumn, }, }; - expect(lastValueOperation.getErrorMessage!(errorLayer, 'col1', indexPattern)) + expect(lastValueOperation.getErrorMessage!(errorLayer, 'col1', createMockedIndexPattern())) .toMatchInlineSnapshot(` Array [ Object { @@ -1014,10 +1027,13 @@ describe('last_value', () => { } as LastValueIndexPatternColumn, }, }; - expect(lastValueOperation.getErrorMessage!(errorLayer, 'col1', indexPattern)).toHaveLength(2); + expect( + lastValueOperation.getErrorMessage!(errorLayer, 'col1', createMockedIndexPattern()) + ).toHaveLength(2); }); it('shows error message if the sourceField is of unsupported type', () => { + const indexPattern = createMockedIndexPattern(); indexPattern.getFieldByName('start_date')!.type = 'unsupported_type'; errorLayer = { ...errorLayer, @@ -1045,9 +1061,9 @@ describe('last_value', () => { } as LastValueIndexPatternColumn, }, }; - expect(lastValueOperation.getErrorMessage!(errorLayer, 'col1', indexPattern)).toEqual([ - 'Field bytes is not a date field and cannot be used for sorting', - ]); + expect( + lastValueOperation.getErrorMessage!(errorLayer, 'col1', createMockedIndexPattern()) + ).toEqual(['Field bytes is not a date field and cannot be used for sorting']); }); }); diff --git a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.tsx index f5abbc74683c6..b452d5f90b761 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.tsx @@ -199,8 +199,8 @@ export const lastValueOperation: OperationDefinition< : oldColumn.filter, }; }, - getPossibleOperationForField: ({ aggregationRestrictions, type, timeSeriesMetric }) => { - if (supportedTypes.has(type) && !aggregationRestrictions && timeSeriesMetric !== 'counter') { + getPossibleOperationForField: ({ aggregationRestrictions, type }) => { + if (supportedTypes.has(type) && !aggregationRestrictions) { return { dataType: type as DataType, isBucketed: false, @@ -285,9 +285,12 @@ export const lastValueOperation: OperationDefinition< // time shift is added to wrapping aggFilteredMetric if filter is set timeShift: column.filter ? undefined : column.timeShift, } as const; + // do not use unsupported top hits when using a counter field type + const isCounterMetricFieldUsed = + indexPattern.getFieldByName(column.sourceField)?.timeSeriesMetric === 'counter'; return ( - column.params.showArrayValues + column.params.showArrayValues && !isCounterMetricFieldUsed ? buildExpressionFunction('aggTopHit', { ...initialArgs, aggregate: 'concat', diff --git a/x-pack/test/functional/apps/lens/group4/tsdb.ts b/x-pack/test/functional/apps/lens/group4/tsdb.ts index 3828ef875d3af..dd747600a21ef 100644 --- a/x-pack/test/functional/apps/lens/group4/tsdb.ts +++ b/x-pack/test/functional/apps/lens/group4/tsdb.ts @@ -171,7 +171,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // skip count for now as it's a special function and will // change automatically the unsupported field to Records when detected - const operationsByFieldSupport = [ + const allOperations = [ 'average', 'max', 'last_value', @@ -181,11 +181,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'standard_deviation', 'sum', 'unique_count', - ].map((name) => ({ + ]; + const counterFieldsSupportedOps = ['min', 'max', 'counter_rate', 'last_value']; + const gaugeFieldsSupportedOps = allOperations; + + const operationsByFieldSupport = allOperations.map((name) => ({ name, + // Quick way to make it match the UI name label: `${name[0].toUpperCase()}${name.slice(1).replace('_', ' ')}`, - counter: ['max', 'counter_rate'].includes(name), - gauge: true, + counter: counterFieldsSupportedOps.includes(name), + gauge: gaugeFieldsSupportedOps.includes(name), })); for (const fieldType of ['counter', 'gauge'] as const) {