[ES|QL] Support counter fields (#186292)

- Closes https://github.com/elastic/kibana/issues/186160

## Summary

This PR adds a new util to help with converting ES|QL column into data
view field representation
9d63332c74/packages/kbn-data-view-utils/src/utils/convert_to_data_view_field.ts (L13)

This allows to handle counter fields in a more predicable way despite of
the different format of ES|QL column data.
https://github.com/elastic/kibana/pull/186154#issuecomment-2164973060

<img width="1988" alt="Screenshot 2024-07-03 at 13 48 20"
src="14ce9cd8-8a02-4f3c-8845-c19c30079a75">

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Co-authored-by: Stratoula Kalafateli <efstratia.kalafateli@elastic.co>
Co-authored-by: Matthias Wilhelm <matthias.wilhelm@elastic.co>
This commit is contained in:
Julia Rechkunova 2024-07-09 12:32:48 +02:00 committed by GitHub
parent 2e8ca07ced
commit 692b656f9c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 113 additions and 15 deletions

View file

@ -7,6 +7,6 @@
*/
export * from './src/constants';
export { convertDatatableColumnToDataViewFieldSpec } from './src/utils/convert_to_data_view_field_spec';
export { createRegExpPatternFrom } from './src/utils/create_regexp_pattern_from';
export { testPatternAgainstAllowedList } from './src/utils/test_pattern_against_allowed_list';

View file

@ -0,0 +1,60 @@
/*
* 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 { DatatableColumnType } from '@kbn/expressions-plugin/common';
import { convertDatatableColumnToDataViewFieldSpec } from './convert_to_data_view_field_spec';
describe('convertDatatableColumnToDataViewFieldSpec', () => {
it('should return a DataViewField object for a counter column', () => {
const column = {
id: 'bytes_counter',
name: 'bytes_counter',
meta: {
esType: 'counter_long',
type: 'number' as DatatableColumnType,
},
isNull: false,
};
const result = convertDatatableColumnToDataViewFieldSpec(column);
expect(result).toEqual(
expect.objectContaining({
name: 'bytes_counter',
type: 'number',
esTypes: ['long'],
searchable: true,
aggregatable: false,
isNull: false,
timeSeriesMetric: 'counter',
})
);
});
it('should return a DataViewField object with timeSeriesMetric undefined if esType does not start with counter_', () => {
const column = {
id: 'test',
name: 'test',
meta: {
esType: 'keyword',
type: 'string' as DatatableColumnType,
},
isNull: false,
};
const result = convertDatatableColumnToDataViewFieldSpec(column);
expect(result.timeSeriesMetric).toBeUndefined();
expect(result).toEqual(
expect.objectContaining({
name: 'test',
type: 'string',
esTypes: ['keyword'],
searchable: true,
aggregatable: false,
isNull: false,
})
);
});
});

View file

@ -0,0 +1,37 @@
/*
* 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 type { DatatableColumn } from '@kbn/expressions-plugin/common';
import type { MappingTimeSeriesMetricType } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import type { FieldSpec } from '@kbn/data-views-plugin/common';
/**
* Convert a datatable column to a DataViewFieldSpec
*/
export function convertDatatableColumnToDataViewFieldSpec(column: DatatableColumn): FieldSpec {
let esType = column.meta?.esType;
let timeSeriesMetric: MappingTimeSeriesMetricType | undefined;
// 'counter_integer', 'counter_long', 'counter_double'...
if (esType?.startsWith('counter_')) {
esType = esType?.replace('counter_', '');
timeSeriesMetric = 'counter';
}
// `DataViewField` class is defined in "data-views" plugin, so we can't create an instance of it from a package.
// We will return a data view field spec here instead then.
return {
name: column.name,
type: column.meta?.type ?? 'unknown',
esTypes: esType ? [esType] : undefined,
searchable: true,
aggregatable: false,
isNull: Boolean(column?.isNull),
...(timeSeriesMetric ? { timeSeriesMetric } : {}),
};
}

View file

@ -14,5 +14,9 @@
],
"exclude": [
"target/**/*"
],
"kbn_references": [
"@kbn/data-views-plugin",
"@kbn/expressions-plugin",
]
}

View file

@ -50,6 +50,10 @@ export const getFilterableKbnTypeNames = (): string[] =>
registeredKbnTypes.filter((type) => type.filterable).map((type) => type.name);
export function esFieldTypeToKibanaFieldType(type: string) {
// 'counter_integer', 'counter_long', 'counter_double'...
if (type.startsWith('counter_')) {
return KBN_FIELD_TYPES.NUMBER;
}
switch (type) {
case ES_FIELD_TYPES._INDEX:
return KBN_FIELD_TYPES.STRING;

View file

@ -7,6 +7,7 @@
*/
import type { DatatableColumnMeta } from '@kbn/expressions-plugin/common';
import { convertDatatableColumnToDataViewFieldSpec } from '@kbn/data-view-utils';
import { getFieldIconType } from './get_field_icon_type';
export function getTextBasedColumnIconType(
@ -19,10 +20,8 @@ export function getTextBasedColumnIconType(
| null
): string | null {
return columnMeta && columnMeta.type
? getFieldIconType({
name: '',
type: columnMeta.type,
esTypes: columnMeta.esType ? [columnMeta.esType] : [],
})
? getFieldIconType(
convertDatatableColumnToDataViewFieldSpec({ id: '', name: '', meta: columnMeta })
)
: null;
}

View file

@ -10,6 +10,7 @@
"@kbn/react-field",
"@kbn/field-types",
"@kbn/expressions-plugin",
"@kbn/data-view-utils",
],
"exclude": ["target/**/*"]
}

View file

@ -8,6 +8,7 @@
import { difference } from 'lodash';
import { type DataView, DataViewField } from '@kbn/data-views-plugin/public';
import { convertDatatableColumnToDataViewFieldSpec } from '@kbn/data-view-utils';
import type { DatatableColumn } from '@kbn/expressions-plugin/common';
import { fieldWildcardFilter } from '@kbn/kibana-utils-plugin/public';
import { isNestedFieldParent } from '@kbn/discover-utils';
@ -66,14 +67,6 @@ export function getEsqlQueryFieldList(esqlQueryColumns?: DatatableColumn[]): Dat
return [];
}
return esqlQueryColumns.map(
(column) =>
new DataViewField({
name: column.name,
type: column.meta?.type ?? 'unknown',
esTypes: column.meta?.esType ? [column.meta?.esType] : undefined,
searchable: true,
aggregatable: false,
isNull: Boolean(column?.isNull),
})
(column) => new DataViewField(convertDatatableColumnToDataViewFieldSpec(column))
);
}