Skip to content

Commit

Permalink
[ES|QL] Support counter fields (elastic#186292)
Browse files Browse the repository at this point in the history
- Closes elastic#186160

## Summary

This PR adds a new util to help with converting ES|QL column into data
view field representation
https://github.com/elastic/kibana/blob/9d63332c74523b00f2b9056352a5b3a86eaf2b75/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.
elastic#186154 (comment)

<img width="1988" alt="Screenshot 2024-07-03 at 13 48 20"
src="https://github.com/elastic/kibana/assets/1415710/14ce9cd8-8a02-4f3c-8845-c19c30079a75">

---------

Co-authored-by: kibanamachine <[email protected]>
Co-authored-by: Elastic Machine <[email protected]>
Co-authored-by: Stratoula Kalafateli <[email protected]>
Co-authored-by: Matthias Wilhelm <[email protected]>
(cherry picked from commit 692b656)
  • Loading branch information
jughosta committed Jul 9, 2024
1 parent d765ed3 commit b97ae85
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 15 deletions.
2 changes: 1 addition & 1 deletion packages/kbn-data-view-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Original file line number Diff line number Diff line change
@@ -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,
})
);
});
});
Original file line number Diff line number Diff line change
@@ -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 } : {}),
};
}
4 changes: 4 additions & 0 deletions packages/kbn-data-view-utils/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,9 @@
],
"exclude": [
"target/**/*"
],
"kbn_references": [
"@kbn/data-views-plugin",
"@kbn/expressions-plugin",
]
}
4 changes: 4 additions & 0 deletions packages/kbn-field-types/src/kbn_field_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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;
}
1 change: 1 addition & 0 deletions packages/kbn-field-utils/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"@kbn/react-field",
"@kbn/field-types",
"@kbn/expressions-plugin",
"@kbn/data-view-utils",
],
"exclude": ["target/**/*"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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))
);
}

0 comments on commit b97ae85

Please sign in to comment.