Skip to content

Commit 7677690

Browse files
authored
[ES|QL] Recommended query selection telemetry events (#240757)
## Summary This PR adds the below telemetry events in the esql editor - [x] esql.recommended_query_clicked (help or autocomplete) - [x] esql.query_submitted (source: help) ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This was checked for breaking HTTP API changes, and any breaking changes have been approved by the breaking-change committee. The `release_note:breaking` label should be applied in these situations. - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [ ] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) - [ ] Review the [backport guidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing) and apply applicable `backport:*` labels. ### Identify risks Does this PR introduce any risks? For example, consider risks like hard to test bugs, performance regression, potential of data loss. Describe the risk, its severity, and mitigation for each identified risk. Invite stakeholders and evaluate how to proceed before merging. - [ ] [See some risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) - [ ] ...
1 parent 638ecef commit 7677690

File tree

9 files changed

+86
-24
lines changed

9 files changed

+86
-24
lines changed

packages/kbn-optimizer/limits.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ pageLoadAssetSize:
4848
embeddableAlertsTable: 6524
4949
embeddableEnhanced: 8448
5050
enterpriseSearch: 38000
51-
esql: 16289
51+
esql: 16500
5252
esqlDataGrid: 10209
5353
esUiShared: 101220
5454
eventAnnotation: 22361

src/platform/packages/private/kbn-esql-editor/src/editor_footer/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ interface EditorFooterProps {
5151
warnings?: MonacoMessage[];
5252
detectedTimestamp?: string;
5353
onErrorClick: (error: MonacoMessage) => void;
54-
runQuery: (source: TelemetryQuerySubmittedProps['query_source']) => void;
54+
runQuery: (source: TelemetryQuerySubmittedProps['source']) => void;
5555
updateQuery: (qs: string) => void;
5656
isHistoryOpen: boolean;
5757
setIsHistoryOpen: (status: boolean) => void;

src/platform/packages/private/kbn-esql-editor/src/esql_editor.tsx

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,6 @@ import type { ComponentProps } from 'react';
4848
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4949
import { createPortal } from 'react-dom';
5050
import useObservable from 'react-use/lib/useObservable';
51-
import {
52-
hasLimitBeforeAggregate,
53-
missingSortBeforeLimit,
54-
} from '@kbn/esql-utils/src/utils/query_parsing_helpers';
5551
import type { TelemetryQuerySubmittedProps } from '@kbn/esql-types/src/esql_telemetry_types';
5652
import { QuerySource } from '@kbn/esql-types/src/esql_telemetry_types';
5753
import { useCanCreateLookupIndex, useLookupIndexCommand } from './custom_commands';
@@ -201,7 +197,7 @@ const ESQLEditorInternal = function ESQLEditor({
201197
);
202198

203199
const onQuerySubmit = useCallback(
204-
(source: TelemetryQuerySubmittedProps['query_source']) => {
200+
(source: TelemetryQuerySubmittedProps['source']) => {
205201
if (isQueryLoading && isLoading && allowQueryCancellation) {
206202
abortController?.abort();
207203
setIsQueryLoading(false);
@@ -218,11 +214,8 @@ const ESQLEditorInternal = function ESQLEditor({
218214
// TODO: add rest of options
219215
if (currentValue) {
220216
telemetryService.trackQuerySubmitted({
221-
query_source: source,
222-
query_length: editor1.current?.getModel()?.getValueLength().toString() ?? '0',
223-
query_lines: editor1.current?.getModel()?.getLineCount().toString() ?? '0',
224-
anti_limit_before_aggregate: hasLimitBeforeAggregate(currentValue),
225-
anti_missing_sort_before_limit: missingSortBeforeLimit(currentValue),
217+
source,
218+
query: currentValue,
226219
});
227220
}
228221
onTextLangQuerySubmit({ esql: currentValue } as AggregateQuery, abc);
@@ -336,6 +329,11 @@ const ESQLEditorInternal = function ESQLEditor({
336329
openTimePickerPopover();
337330
});
338331

332+
monaco.editor.registerCommand('esql.recommendedQuery.accept', (...args) => {
333+
const [, { queryLabel }] = args;
334+
telemetryService.trackRecommendedQueryClicked(QuerySource.AUTOCOMPLETE, queryLabel);
335+
});
336+
339337
const controlCommands = [
340338
{ command: 'esql.control.multi_values.create', variableType: ESQLVariableType.MULTI_VALUES },
341339
{ command: 'esql.control.time_literal.create', variableType: ESQLVariableType.TIME_LITERAL },

src/platform/packages/private/kbn-esql-editor/src/telemetry/events_registration.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export const ESQL_QUERY_HISTORY_OPENED = 'esql.query_history_opened';
2020
export const ESQL_QUERY_HISTORY_CLICKED = 'esql.query_history_clicked';
2121
export const ESQL_STARRED_QUERY_CLICKED = 'esql.starred_query_clicked';
2222
export const ESQL_QUERY_SUBMITTED = 'esql.query_submitted';
23+
export const ESQL_RECOMMENDED_QUERY_CLICKED = 'esql.recommended_query_clicked';
2324

2425
/**
2526
* Registers the esql editor analytics events.
@@ -110,4 +111,22 @@ export const registerESQLEditorAnalyticsEvents = once((analytics: AnalyticsServi
110111
},
111112
},
112113
});
114+
analytics.registerEventType({
115+
eventType: ESQL_RECOMMENDED_QUERY_CLICKED,
116+
schema: {
117+
trigger_source: {
118+
type: 'keyword',
119+
_meta: {
120+
description:
121+
'The UI surface where the recommendation was shown. Possible values are: help|autocomplete',
122+
},
123+
},
124+
recommended_query: {
125+
type: 'keyword',
126+
_meta: {
127+
description: 'The label of the recommended query that was clicked',
128+
},
129+
},
130+
},
131+
});
113132
});

src/platform/packages/private/kbn-esql-editor/src/telemetry/telemetry_service.ts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,18 @@
88
*/
99
import type { AnalyticsServiceStart } from '@kbn/core/server';
1010
import type { TelemetryQuerySubmittedProps } from '@kbn/esql-types/src/esql_telemetry_types';
11+
import { QuerySource } from '@kbn/esql-types/src/esql_telemetry_types';
12+
import { BasicPrettyPrinter, Parser } from '@kbn/esql-ast';
13+
import {
14+
hasLimitBeforeAggregate,
15+
missingSortBeforeLimit,
16+
} from '@kbn/esql-utils/src/utils/query_parsing_helpers';
1117
import {
1218
ESQL_LOOKUP_JOIN_ACTION_SHOWN,
1319
ESQL_QUERY_HISTORY_CLICKED,
1420
ESQL_QUERY_HISTORY_OPENED,
1521
ESQL_QUERY_SUBMITTED,
22+
ESQL_RECOMMENDED_QUERY_CLICKED,
1623
ESQL_STARRED_QUERY_CLICKED,
1724
ESQL_SUGGESTIONS_WITH_CUSTOM_COMMAND_SHOWN,
1825
} from './events_registration';
@@ -100,13 +107,35 @@ export class ESQLEditorTelemetryService {
100107
}
101108
}
102109

103-
public trackQuerySubmitted(props: TelemetryQuerySubmittedProps) {
110+
public trackQuerySubmitted({ source, query }: TelemetryQuerySubmittedProps) {
111+
// parsing and prettifying the raw query
112+
// to remove comments for accurately measuring its length
113+
const { root } = Parser.parse(query);
114+
const prettyQuery = BasicPrettyPrinter.print(root);
115+
const hasLimitBeforeStats =
116+
source === QuerySource.HELP || source === QuerySource.AUTOCOMPLETE
117+
? false
118+
: hasLimitBeforeAggregate(query);
119+
const hasMissingSortBeforeLimit =
120+
source === QuerySource.HELP || source === QuerySource.AUTOCOMPLETE
121+
? false
122+
: missingSortBeforeLimit(query);
104123
this._reportEvent(ESQL_QUERY_SUBMITTED, {
105-
query_source: props.query_source,
106-
query_length: props.query_length,
107-
query_lines: props.query_lines,
108-
anti_limit_before_aggregate: props.anti_limit_before_aggregate,
109-
anti_missing_sort_before_limit: props.anti_missing_sort_before_limit,
124+
query_source: source,
125+
query_length: prettyQuery.length.toString(),
126+
query_lines: query.split('\n').length.toString(),
127+
anti_limit_before_aggregate: hasLimitBeforeStats,
128+
anti_missing_sort_before_limit: hasMissingSortBeforeLimit,
129+
});
130+
}
131+
132+
public trackRecommendedQueryClicked(
133+
source: QuerySource.HELP | QuerySource.AUTOCOMPLETE,
134+
label: string
135+
) {
136+
this._reportEvent(ESQL_RECOMMENDED_QUERY_CLICKED, {
137+
trigger_source: source,
138+
recommended_query: label,
110139
});
111140
}
112141
}

src/platform/packages/shared/kbn-esql-ast/src/commands_registry/options/recommended_queries/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ export const getRecommendedQueriesSuggestionsFromStaticTemplates = async (
196196
kind: 'Issue',
197197
detail: query.description,
198198
sortText: query?.sortText ?? 'E',
199+
command: {
200+
id: 'esql.recommendedQuery.accept',
201+
title: 'Accept recommended query',
202+
arguments: [{ queryLabel: query.label }],
203+
},
199204
};
200205
});
201206

src/platform/packages/shared/kbn-esql-ast/src/commands_registry/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export interface ISuggestionItem {
7171
command?: {
7272
title: string;
7373
id: string;
74+
arguments?: { [key: string]: string }[];
7475
};
7576
/**
7677
* The range that should be replaced when the suggestion is applied

src/platform/packages/shared/kbn-esql-types/src/esql_telemetry_types.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,10 @@ export enum QuerySource {
1717
STARRED = 'starred',
1818
MANUAL = 'manual',
1919
HELP = 'help',
20+
AUTOCOMPLETE = 'autocomplete',
2021
}
2122

2223
export interface TelemetryQuerySubmittedProps {
23-
query_source: QuerySource;
24-
query_length: string;
25-
query_lines: string;
26-
anti_limit_before_aggregate: boolean;
27-
anti_missing_sort_before_limit: boolean;
24+
source: QuerySource;
25+
query: string;
2826
}

src/platform/plugins/shared/unified_search/public/query_string_input/esql_menu_popover.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import { getRecommendedQueriesTemplates } from '@kbn/esql-ast/src/commands_regis
2828
import { LanguageDocumentationFlyout } from '@kbn/language-documentation';
2929
import { getCategorizationField } from '@kbn/aiops-utils';
3030
import { prettifyQueryTemplate } from '@kbn/esql-ast/src/commands_registry/options/recommended_queries/utils';
31+
import { ESQLEditorTelemetryService } from '@kbn/esql-editor/src/telemetry/telemetry_service';
32+
import { QuerySource } from '@kbn/esql-types/src/esql_telemetry_types';
3133
import type { IUnifiedSearchPluginServices } from '../types';
3234

3335
export interface ESQLMenuPopoverProps {
@@ -42,7 +44,7 @@ export const ESQLMenuPopover: React.FC<ESQLMenuPopoverProps> = ({
4244
onESQLQuerySubmit,
4345
}) => {
4446
const kibana = useKibana<IUnifiedSearchPluginServices>();
45-
const { docLinks, http, chrome } = kibana.services;
47+
const { docLinks, http, chrome, analytics } = kibana.services;
4648

4749
const { euiTheme } = useEuiTheme();
4850

@@ -54,6 +56,8 @@ export const ESQLMenuPopover: React.FC<ESQLMenuPopoverProps> = ({
5456
RecommendedQuery[]
5557
>([]);
5658

59+
const telemetryServiceRef = useRef(new ESQLEditorTelemetryService(analytics));
60+
5761
const { queryForRecommendedQueries, timeFieldName, categorizationField } = useMemo(() => {
5862
if (adHocDataview && typeof adHocDataview !== 'string') {
5963
const textFields = adHocDataview.fields?.getByType('string') ?? [];
@@ -244,7 +248,15 @@ export const ESQLMenuPopover: React.FC<ESQLMenuPopoverProps> = ({
244248
return {
245249
name: query.label,
246250
onClick: () => {
251+
telemetryServiceRef.current.trackRecommendedQueryClicked(
252+
QuerySource.HELP,
253+
query.label
254+
);
247255
onESQLQuerySubmit?.(query.queryString);
256+
telemetryServiceRef.current.trackQuerySubmitted({
257+
source: QuerySource.HELP,
258+
query: query.queryString,
259+
});
248260
setIsESQLMenuPopoverOpen(false);
249261
},
250262
};

0 commit comments

Comments
 (0)