Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Obs ai assistant][ESQL] Visualizes a query #174677

Merged
merged 52 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
0548517
[Obs ai assistant][ESQL] Visualizes a query
stratoula Jan 11, 2024
9132a88
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Jan 11, 2024
a60baff
Make CI happy again
stratoula Jan 11, 2024
e90f370
Merge branch 'main' into obs-ai-assistant-visualize-esql
stratoula Jan 12, 2024
e59aa6c
Happy CI, happy life
stratoula Jan 12, 2024
ccbc3ae
Merge branch 'main' into obs-ai-assistant-visualize-esql
stratoula Jan 15, 2024
09ff297
Make the assistant flyout work with the inline editing component
stratoula Jan 16, 2024
b6a37f1
Fixes jest test
stratoula Jan 16, 2024
08bd3f4
Merge branch 'main' into obs-ai-assistant-visualize-esql
stratoula Jan 16, 2024
bba1b4e
Merge branch 'main' into obs-ai-assistant-visualize-esql
stratoula Jan 17, 2024
df0c56a
Add unit test in getAttributed function
stratoula Jan 17, 2024
2016b6a
Minor tweaks
stratoula Jan 17, 2024
e7a171a
Cleanup
stratoula Jan 17, 2024
704b8f5
More cleanup
stratoula Jan 17, 2024
2bb0c06
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Jan 17, 2024
5628842
Write some tests
stratoula Jan 17, 2024
5e71490
Simplifications
stratoula Jan 17, 2024
60a1d40
Merge branch 'main' into obs-ai-assistant-visualize-esql
stratoula Jan 17, 2024
1b4e2da
Fix CI
stratoula Jan 17, 2024
c8b3896
Remove commented out code
stratoula Jan 18, 2024
b5fe67b
Merge branch 'main' into obs-ai-assistant-visualize-esql
stratoula Jan 18, 2024
e843fec
Address Pr comments
stratoula Jan 20, 2024
84e26ff
Merge branch 'main' into obs-ai-assistant-visualize-esql
stratoula Jan 22, 2024
6b01204
Merge with main and resolve conflicts
stratoula Jan 22, 2024
4632fb1
Merge with main and resolve conflicts
stratoula Jan 25, 2024
cfcda31
Merge with main and resolve conflicts
stratoula Jan 26, 2024
ccd5810
[Obs AI Assistant] Correct executed ES|QL query
dgieselaar Jan 26, 2024
536fce1
Merge branch 'obs-ai-assistant-execute-corrected' into obs-ai-assista…
dgieselaar Jan 26, 2024
887603b
Extract and display preferred chart
dgieselaar Jan 26, 2024
63ce42f
Fix the update visualization call
stratoula Jan 26, 2024
2d1e844
Small fix on Visualize query CTA
stratoula Jan 26, 2024
d0cca57
Restore the execute_query function as AssistantOnly function for disp…
stratoula Jan 26, 2024
b1cd423
Merge with main and resolve conflicts
stratoula Jan 29, 2024
b9805c1
Rename esql to query function
dgieselaar Jan 30, 2024
cd4b939
Merge branch 'main' into obs-ai-assistant-visualize-esql
stratoula Jan 31, 2024
a72b140
Improving the variable name storing the lens overrides made by the user
stratoula Jan 31, 2024
2c5bd3b
Update x-pack/plugins/observability_ai_assistant/server/functions/que…
stratoula Jan 31, 2024
4547567
Merge branch 'main' into obs-ai-assistant-visualize-esql
stratoula Jan 31, 2024
7894fbd
Integrate Conversation List and Edit Visualisation
CoenWarmer Feb 2, 2024
4d69406
Merge branch 'obs-ai-assistant-visualize-esql' of https://github.com/…
CoenWarmer Feb 2, 2024
029a531
Merge branch 'main' of github.com:elastic/kibana into obs-ai-assistan…
CoenWarmer Feb 2, 2024
f874e16
Fix import
CoenWarmer Feb 2, 2024
d76002e
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Feb 2, 2024
2a13505
Clean translations
CoenWarmer Feb 3, 2024
dac6998
Merge branch 'obs-ai-assistant-visualize-esql' of https://github.com/…
CoenWarmer Feb 3, 2024
98fc8da
Fix types
CoenWarmer Feb 3, 2024
9f39185
Merge branch 'main' into obs-ai-assistant-visualize-esql
stratoula Feb 5, 2024
d79102c
Fix intl console warning
stratoula Feb 5, 2024
df07b85
Styling fixes
CoenWarmer Feb 5, 2024
66924a0
Merge branch 'obs-ai-assistant-visualize-esql' of https://github.com/…
CoenWarmer Feb 5, 2024
5705307
Make ui vis editor sidebar slightly wider
CoenWarmer Feb 5, 2024
0d7c31b
Merge with main and resolve conflicts
stratoula Feb 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .i18nrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
"visTypeXy": "src/plugins/vis_types/xy",
"visualizations": "src/plugins/visualizations",
"visualizationUiComponents": "packages/kbn-visualization-ui-components",
"visualizationUtils": "packages/kbn-visualization-utils",
"unifiedDocViewer": ["src/plugins/unified_doc_viewer", "packages/kbn-unified-doc-viewer"],
"unifiedSearch": "src/plugins/unified_search",
"unifiedFieldList": "packages/kbn-unified-field-list",
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-field-types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export {
getKbnFieldType,
getKbnTypeNames,
getFilterableKbnTypeNames,
normalizeType,
} from './src/kbn_field_types';

export type { KbnFieldTypeOptions } from './src/types';
Expand Down
16 changes: 15 additions & 1 deletion packages/kbn-field-types/src/kbn_field_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { createKbnFieldTypes, kbnFieldTypeUnknown } from './kbn_field_types_factory';
import { KbnFieldType } from './kbn_field_type';
import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from './types';
Expand Down Expand Up @@ -49,3 +48,18 @@ export const castEsToKbnFieldTypeName = (esType: ES_FIELD_TYPES | string): KBN_F
*/
export const getFilterableKbnTypeNames = (): string[] =>
registeredKbnTypes.filter((type) => type.filterable).map((type) => type.name);

export function normalizeType(type: string) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ I just moved this helper here as we are duplicating this code in many places.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this function takes an Elasticsearch field type and translates it to a Kibana field type? If so, perhaps we could call this function something like

esFieldTypeToKibanaFieldType

normalizeType could mean practically anything. (I know you didn't name this function BTW—still thought the comment was worth making 🤷‍♂️ )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this is fair, I just moved it and didnt think to rename. I addressed it here e843fec

switch (type) {
case ES_FIELD_TYPES._INDEX:
case ES_FIELD_TYPES.GEO_POINT:
case ES_FIELD_TYPES.IP:
return KBN_FIELD_TYPES.STRING;
case '_version':
return KBN_FIELD_TYPES.NUMBER;
case 'datetime':
return KBN_FIELD_TYPES.DATE;
default:
return castEsToKbnFieldTypeName(type);
}
}
134 changes: 134 additions & 0 deletions packages/kbn-visualization-utils/__mocks__/suggestions_mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* 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 { Suggestion } from '../src/types';

export const currentSuggestionMock = {
title: 'Heat map',
hide: false,
score: 0.6,
previewIcon: 'heatmap',
visualizationId: 'lnsHeatmap',
visualizationState: {
shape: 'heatmap',
layerId: '46aa21fa-b747-4543-bf90-0b40007c546d',
layerType: 'data',
legend: {
isVisible: true,
position: 'right',
type: 'heatmap_legend',
},
gridConfig: {
type: 'heatmap_grid',
isCellLabelVisible: false,
isYAxisLabelVisible: true,
isXAxisLabelVisible: true,
isYAxisTitleVisible: false,
isXAxisTitleVisible: false,
},
valueAccessor: '5b9b8b76-0836-4a12-b9c0-980c9900502f',
xAccessor: '81e332d6-ee37-42a8-a646-cea4fc75d2d3',
},
keptLayerIds: ['46aa21fa-b747-4543-bf90-0b40007c546d'],
datasourceState: {
layers: {
'46aa21fa-b747-4543-bf90-0b40007c546d': {
index: 'd3d7af60-4c81-11e8-b3d7-01146121b73d',
query: {
esql: 'FROM kibana_sample_data_flights | keep Dest, AvgTicketPrice',
},
columns: [
{
columnId: '81e332d6-ee37-42a8-a646-cea4fc75d2d3',
fieldName: 'Dest',
meta: {
type: 'string',
},
},
{
columnId: '5b9b8b76-0836-4a12-b9c0-980c9900502f',
fieldName: 'AvgTicketPrice',
meta: {
type: 'number',
},
},
],
timeField: 'timestamp',
},
},
indexPatternRefs: [],
initialContext: {
dataViewSpec: {
id: 'd3d7af60-4c81-11e8-b3d7-01146121b73d',
version: 'WzM1ODA3LDFd',
title: 'kibana_sample_data_flights',
timeFieldName: 'timestamp',
sourceFilters: [],
fields: {
AvgTicketPrice: {
count: 0,
name: 'AvgTicketPrice',
type: 'number',
esTypes: ['float'],
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
format: {
id: 'number',
params: {
pattern: '$0,0.[00]',
},
},
shortDotsEnable: false,
isMapped: true,
},
Dest: {
count: 0,
name: 'Dest',
type: 'string',
esTypes: ['keyword'],
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
format: {
id: 'string',
},
shortDotsEnable: false,
isMapped: true,
},
timestamp: {
count: 0,
name: 'timestamp',
type: 'date',
esTypes: ['date'],
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true,
format: {
id: 'date',
},
shortDotsEnable: false,
isMapped: true,
},
},
allowNoIndex: false,
name: 'Kibana Sample Data Flights',
},
fieldName: '',
contextualFields: ['Dest', 'AvgTicketPrice'],
query: {
esql: 'FROM "kibana_sample_data_flights"',
},
},
},
datasourceId: 'textBased',
columns: 2,
changeType: 'initial',
} as Suggestion;
drewdaemon marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions packages/kbn-visualization-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
*/

export { getTimeZone } from './src/get_timezone';
export { getLensAttributesFromSuggestion } from './src/get_lens_attributes';
export { TooltipWrapper } from './src/tooltip_wrapper';
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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 { getLensAttributesFromSuggestion } from './get_lens_attributes';
import { AggregateQuery } from '@kbn/es-query';
import type { DataView } from '@kbn/data-views-plugin/public';
import { currentSuggestionMock } from '../__mocks__/suggestions_mock';

describe('getLensAttributesFromSuggestion', () => {
const dataView = {
id: `index-pattern-with-timefield-id`,
title: `index-pattern-with-timefield-title`,
fields: [],
getFieldByName: jest.fn(),
timeFieldName: '@timestamp',
isPersisted: () => false,
toSpec: () => ({}),
} as unknown as DataView;
const query: AggregateQuery = { esql: 'from foo | limit 10' };

it('should return correct attributes for given suggestion', () => {
const lensAttrs = getLensAttributesFromSuggestion({
filters: [],
query,
dataView,
suggestion: currentSuggestionMock,
});
expect(lensAttrs).toEqual({
state: expect.objectContaining({
adHocDataViews: {
'index-pattern-with-timefield-id': {},
},
}),
references: [
{
id: 'index-pattern-with-timefield-id',
name: 'textBasedLanguages-datasource-layer-suggestion',
type: 'index-pattern',
},
],
title: currentSuggestionMock.title,
visualizationType: 'lnsHeatmap',
});
});
});
64 changes: 64 additions & 0 deletions packages/kbn-visualization-utils/src/get_lens_attributes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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 { i18n } from '@kbn/i18n';
import type { DataView } from '@kbn/data-views-plugin/public';
import type { AggregateQuery, Query, Filter } from '@kbn/es-query';
import type { Suggestion } from './types';

export const getLensAttributesFromSuggestion = ({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ I can reuse it in Lens but I will do it on a follow up PR. I moved it on the package because othwerise it creates circular dependencies.

filters,
query,
suggestion,
dataView,
}: {
filters: Filter[];
query: Query | AggregateQuery;
suggestion: Suggestion | undefined;
dataView?: DataView;
}) => {
const suggestionDatasourceState = Object.assign({}, suggestion?.datasourceState);
const suggestionVisualizationState = Object.assign({}, suggestion?.visualizationState);
const datasourceStates =
suggestion && suggestion.datasourceState
? {
[suggestion.datasourceId!]: {
...suggestionDatasourceState,
},
}
: {
formBased: {},
};
const visualization = suggestionVisualizationState;
const attributes = {
title: suggestion
? suggestion.title
: i18n.translate('visualizationUtils.config.suggestion.title', {
defaultMessage: 'New suggestion',
}),
references: [
{
id: dataView?.id ?? '',
name: `textBasedLanguages-datasource-layer-suggestion`,
type: 'index-pattern',
},
],
state: {
datasourceStates,
filters,
query,
visualization,
...(dataView &&
dataView.id &&
!dataView.isPersisted() && {
adHocDataViews: { [dataView.id]: dataView.toSpec(false) },
}),
},
visualizationType: suggestion ? suggestion.visualizationId : 'lnsXY',
};
return attributes;
};
43 changes: 43 additions & 0 deletions packages/kbn-visualization-utils/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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 { Ast } from '@kbn/interpreter';
import type { IconType } from '@elastic/eui/src/components/icon/icon';

/**
* Indicates what was changed in this table compared to the currently active table of this layer.
* * `initial` means the layer associated with this table does not exist in the current configuration
* * `unchanged` means the table is the same in the currently active configuration
* * `reduced` means the table is a reduced version of the currently active table (some columns dropped, but not all of them)
* * `extended` means the table is an extended version of the currently active table (added one or multiple additional columns)
* * `reorder` means the table columns have changed order, which change the data as well
* * `layers` means the change is a change to the layer structure, not to the table
*/
export type TableChangeType =
| 'initial'
| 'unchanged'
| 'reduced'
| 'extended'
| 'reorder'
| 'layers';

export interface Suggestion<T = unknown, V = unknown> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ Same as above. This can be reused in Lens and unified-histogram but I will do it on a follow up PR

visualizationId: string;
datasourceState?: V;
datasourceId?: string;
columns: number;
score: number;
title: string;
visualizationState: T;
previewExpression?: Ast | string;
previewIcon: IconType;
hide?: boolean;
// flag to indicate if the visualization is incomplete
incomplete?: boolean;
changeType: TableChangeType;
keptLayerIds: string[];
}
4 changes: 4 additions & 0 deletions packages/kbn-visualization-utils/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@
],
"kbn_references": [
"@kbn/core",
"@kbn/i18n",
"@kbn/interpreter",
"@kbn/data-views-plugin",
"@kbn/es-query",
]
}
23 changes: 2 additions & 21 deletions src/plugins/data/common/search/expressions/esql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,9 @@
*/

import type { KibanaRequest } from '@kbn/core/server';
import { castEsToKbnFieldTypeName, ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types';
import { normalizeType } from '@kbn/field-types';
import { i18n } from '@kbn/i18n';
import type {
Datatable,
DatatableColumnType,
ExpressionFunctionDefinition,
} from '@kbn/expressions-plugin/common';
import type { Datatable, ExpressionFunctionDefinition } from '@kbn/expressions-plugin/common';
import { RequestAdapter } from '@kbn/inspector-plugin/common';

import { zipObject } from 'lodash';
Expand Down Expand Up @@ -56,21 +52,6 @@ interface EsqlStartDependencies {
uiSettings: UiSettingsCommon;
}

function normalizeType(type: string): DatatableColumnType {
switch (type) {
case ES_FIELD_TYPES._INDEX:
case ES_FIELD_TYPES.GEO_POINT:
case ES_FIELD_TYPES.IP:
return KBN_FIELD_TYPES.STRING;
case '_version':
return KBN_FIELD_TYPES.NUMBER;
case 'datetime':
return KBN_FIELD_TYPES.DATE;
default:
return castEsToKbnFieldTypeName(type) as DatatableColumnType;
}
}

function extractTypeAndReason(attributes: any): { type?: string; reason?: string } {
if (['type', 'reason'].every((prop) => prop in attributes)) {
return attributes;
Expand Down