mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[Query Rules] Query rules telemetry (#225146)
## Summary Adds telemetry to query rules UIs ### 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) - [ ] [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) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
1ebff0e634
commit
cae3861f5d
14 changed files with 177 additions and 24 deletions
|
@ -19,6 +19,7 @@
|
|||
"console",
|
||||
"searchNavigation",
|
||||
"share",
|
||||
"usageCollection",
|
||||
],
|
||||
"requiredBundles": [
|
||||
"kibanaReact",
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export enum AnalyticsEvents {
|
||||
// Empty promp actions
|
||||
gettingStartedButtonClicked = 'getting_started_button_clicked',
|
||||
createInConsoleClicked = 'create_in_console_clicked',
|
||||
emptyPromptLoaded = 'empty_prompt_loaded',
|
||||
|
||||
// Error prompt loaded
|
||||
genericErrorPromptLoaded = 'generic_error_prompt_loaded',
|
||||
notFoundErrorPromptLoaded = 'not_found_error_prompt_loaded',
|
||||
missingPermissionsErrorPromptLoaded = 'missing_permissions_error_prompt_loaded',
|
||||
|
||||
rulesetCreateClicked = 'ruleset_create_clicked',
|
||||
rulesetUpdateClicked = 'ruleset_update_clicked',
|
||||
|
||||
// ruleset detail page actions
|
||||
rulesetDetailPageLoaded = 'ruleset_details_page_loaded',
|
||||
addRuleClicked = 'add_rule_clicked',
|
||||
editRuleClicked = 'edit_rule_clicked',
|
||||
deleteRuleClicked = 'delete_rule_clicked',
|
||||
testInConsoleClicked = 'test_in_console_clicked',
|
||||
deleteRulesetFromHeaderClicked = 'delete_ruleset_from_header_clicked',
|
||||
backToRulesetListClicked = 'back_to_ruleset_list_clicked',
|
||||
|
||||
rulesReordered = 'rules_reordered',
|
||||
ruleFlyoutDocumentsReordered = 'rule_flyout_documents_reordered',
|
||||
|
||||
// ruleset list page actions
|
||||
editRulesetInlineNameClicked = 'edit_ruleset_inline_name_clicked',
|
||||
editRulesetInlineDropdownClicked = 'edit_ruleset_inline_dropdown_clicked',
|
||||
rulesetListPageLoaded = 'ruleset_list_page_loaded',
|
||||
deleteRulesetInlineDropdownClicked = 'delete_ruleset_inline_dropdown_clicked',
|
||||
testRulesetInlineDropdownClicked = 'test_ruleset_inline_dropdown_clicked',
|
||||
rulesetSearched = 'ruleset_searched',
|
||||
addRulesetClicked = 'add_ruleset_clicked',
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
import {
|
||||
EuiButton,
|
||||
|
@ -35,14 +35,22 @@ import { useKibana } from '../../hooks/use_kibana';
|
|||
import queryRulesImg from '../../assets/query-rules-context-alt.svg';
|
||||
import queryRulesDarkImg from '../../assets/query-rules-context-alt-dark.svg';
|
||||
import backgroundPanelImg from '../../assets/query-rule-panel-background.svg';
|
||||
import { AnalyticsEvents } from '../../analytics/constants';
|
||||
import { useUsageTracker } from '../../hooks/use_usage_tracker';
|
||||
import backgroundPaneDarklImg from '../../assets/query-rule-panel-background-dark.svg';
|
||||
|
||||
interface EmptyPromptProps {
|
||||
getStartedAction: () => void;
|
||||
}
|
||||
export const EmptyPrompt: React.FC<EmptyPromptProps> = ({ getStartedAction }) => {
|
||||
const usageTracker = useUsageTracker();
|
||||
const { application, share, console: consolePlugin } = useKibana().services;
|
||||
const { euiTheme, colorMode } = useEuiTheme();
|
||||
|
||||
useEffect(() => {
|
||||
usageTracker?.load(AnalyticsEvents.emptyPromptLoaded);
|
||||
}, [usageTracker]);
|
||||
|
||||
const gradientOverlay = css({
|
||||
background: `linear-gradient(180deg, ${transparentize(
|
||||
euiTheme.colors.backgroundBasePlain,
|
||||
|
@ -101,7 +109,10 @@ export const EmptyPrompt: React.FC<EmptyPromptProps> = ({ getStartedAction }) =>
|
|||
data-test-subj="searchQueryRulesEmptyPromptGetStartedButton"
|
||||
color="primary"
|
||||
fill
|
||||
onClick={getStartedAction}
|
||||
onClick={() => {
|
||||
usageTracker?.click(AnalyticsEvents.gettingStartedButtonClicked);
|
||||
getStartedAction();
|
||||
}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.queryRules.emptyPrompt.getStartedButton"
|
||||
|
@ -240,6 +251,7 @@ export const EmptyPrompt: React.FC<EmptyPromptProps> = ({ getStartedAction }) =>
|
|||
defaultMessage: 'Create in Console',
|
||||
})}
|
||||
showIcon
|
||||
data-test-subj={AnalyticsEvents.createInConsoleClicked}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiHideFor>
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
import { EuiEmptyPrompt } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { useUsageTracker } from '../../hooks/use_usage_tracker';
|
||||
import { AnalyticsEvents } from '../../analytics/constants';
|
||||
|
||||
const ERROR_MESSAGES = {
|
||||
notFound: {
|
||||
|
@ -19,6 +21,7 @@ const ERROR_MESSAGES = {
|
|||
defaultMessage="Requested resource was not found. Check if the URL is correct."
|
||||
/>
|
||||
),
|
||||
analyticsEvent: AnalyticsEvents.notFoundErrorPromptLoaded,
|
||||
},
|
||||
generic: {
|
||||
title: <FormattedMessage id="xpack.queryRules.errorTitle" defaultMessage="An error occurred" />,
|
||||
|
@ -28,6 +31,7 @@ const ERROR_MESSAGES = {
|
|||
defaultMessage="An error occurred while fetching query rules. Check Kibana logs for more information."
|
||||
/>
|
||||
),
|
||||
analyticsEvent: AnalyticsEvents.genericErrorPromptLoaded,
|
||||
},
|
||||
missingPermissions: {
|
||||
title: (
|
||||
|
@ -42,12 +46,17 @@ const ERROR_MESSAGES = {
|
|||
defaultMessage="You do not have the necessary permissions to manage query rules. Contact your system administrator."
|
||||
/>
|
||||
),
|
||||
analyticsEvent: AnalyticsEvents.missingPermissionsErrorPromptLoaded,
|
||||
},
|
||||
};
|
||||
|
||||
export const ErrorPrompt: React.FC<{
|
||||
errorType: 'missingPermissions' | 'generic' | 'notFound';
|
||||
}> = ({ errorType }) => {
|
||||
const useTracker = useUsageTracker();
|
||||
useEffect(() => {
|
||||
useTracker?.load?.(ERROR_MESSAGES[errorType].analyticsEvent);
|
||||
}, [errorType, useTracker]);
|
||||
return (
|
||||
<EuiEmptyPrompt
|
||||
iconType="logoElasticsearch"
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';
|
||||
import {
|
||||
|
@ -31,24 +31,16 @@ import { QueryRulesSets } from '../query_rules_sets/query_rules_sets';
|
|||
import { CreateRulesetModal } from './create_ruleset_modal';
|
||||
|
||||
import { QueryRulesPageTemplate } from '../../layout/query_rules_page_template';
|
||||
import { useUsageTracker } from '../../hooks/use_usage_tracker';
|
||||
import { AnalyticsEvents } from '../../analytics/constants';
|
||||
|
||||
export const QueryRulesOverview = () => {
|
||||
const usageTracker = useUsageTracker();
|
||||
const { colorMode } = useEuiTheme();
|
||||
const {
|
||||
data: queryRulesData,
|
||||
isInitialLoading,
|
||||
isError,
|
||||
error,
|
||||
refetch,
|
||||
} = useFetchQueryRulesSets();
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
refetch();
|
||||
}, 1000);
|
||||
return () => clearInterval(interval);
|
||||
}, [refetch]);
|
||||
const { data: queryRulesData, isInitialLoading, isError, error } = useFetchQueryRulesSets();
|
||||
const [isCreateModalVisible, setIsCreateModalVisible] = useState(false);
|
||||
|
||||
const backgroundProps = css({
|
||||
backgroundImage: `url(${
|
||||
colorMode === 'DARK' ? queryRulesBackgroundDark : queryRulesBackground
|
||||
|
@ -61,6 +53,7 @@ export const QueryRulesOverview = () => {
|
|||
alignContent: 'center',
|
||||
backgroundPosition: 'center center',
|
||||
});
|
||||
|
||||
return (
|
||||
<QueryRulesPageTemplate restrictWidth={false}>
|
||||
{!isInitialLoading && !isError && queryRulesData?._meta.totalItemCount !== 0 && (
|
||||
|
@ -95,6 +88,7 @@ export const QueryRulesOverview = () => {
|
|||
fill
|
||||
iconType="plusInCircle"
|
||||
onClick={() => {
|
||||
usageTracker?.click(AnalyticsEvents.addRulesetClicked);
|
||||
setIsCreateModalVisible(true);
|
||||
}}
|
||||
>
|
||||
|
@ -143,6 +137,7 @@ export const QueryRulesOverview = () => {
|
|||
<EuiFlexItem>
|
||||
<EmptyPrompt
|
||||
getStartedAction={() => {
|
||||
usageTracker?.click(AnalyticsEvents.gettingStartedButtonClicked);
|
||||
setIsCreateModalVisible(true);
|
||||
}}
|
||||
/>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { QueryRulesListRulesetsQueryRulesetListItem } from '@elastic/elasticsearch/lib/api/types';
|
||||
import {
|
||||
|
@ -24,8 +24,11 @@ import { useQueryRulesSetsTableData } from '../../hooks/use_query_rules_sets_tab
|
|||
import { QueryRulesSetsSearch } from './query_rules_sets_search';
|
||||
import { DeleteRulesetModal } from './delete_ruleset_modal';
|
||||
import { UseRunQueryRuleset } from '../../hooks/use_run_query_ruleset';
|
||||
import { useUsageTracker } from '../../hooks/use_usage_tracker';
|
||||
import { AnalyticsEvents } from '../../analytics/constants';
|
||||
|
||||
export const QueryRulesSets = () => {
|
||||
const useTracker = useUsageTracker();
|
||||
const {
|
||||
services: { application, http },
|
||||
} = useKibana();
|
||||
|
@ -43,6 +46,10 @@ export const QueryRulesSets = () => {
|
|||
pageSize
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
useTracker?.load?.(AnalyticsEvents.rulesetListPageLoaded);
|
||||
}, [useTracker]);
|
||||
|
||||
if (!queryRulesData) {
|
||||
return null;
|
||||
}
|
||||
|
@ -57,6 +64,7 @@ export const QueryRulesSets = () => {
|
|||
<EuiLink
|
||||
data-test-subj="queryRuleSetName"
|
||||
onClick={() => {
|
||||
useTracker?.click?.(AnalyticsEvents.editRulesetInlineNameClicked);
|
||||
application.navigateToUrl(
|
||||
http.basePath.prepend(`${PLUGIN_ROUTE_ROOT}/ruleset/${name}`)
|
||||
);
|
||||
|
@ -86,6 +94,9 @@ export const QueryRulesSets = () => {
|
|||
content={i18n.translate('xpack.queryRules.queryRulesSetTable.actions.run', {
|
||||
defaultMessage: 'Test in Console',
|
||||
})}
|
||||
onClick={() => {
|
||||
useTracker?.click?.(AnalyticsEvents.testRulesetInlineDropdownClicked);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
@ -102,10 +113,12 @@ export const QueryRulesSets = () => {
|
|||
icon: 'pencil',
|
||||
color: 'text',
|
||||
type: 'icon',
|
||||
onClick: (ruleset: QueryRulesListRulesetsQueryRulesetListItem) =>
|
||||
onClick: (ruleset: QueryRulesListRulesetsQueryRulesetListItem) => {
|
||||
useTracker?.click?.(AnalyticsEvents.editRulesetInlineDropdownClicked);
|
||||
application.navigateToUrl(
|
||||
http.basePath.prepend(`${PLUGIN_ROUTE_ROOT}/ruleset/${ruleset.ruleset_id}`)
|
||||
),
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: i18n.translate('xpack.queryRules.queryRulesSetTable.actions.delete', {
|
||||
|
@ -121,6 +134,7 @@ export const QueryRulesSets = () => {
|
|||
type: 'icon',
|
||||
isPrimary: true,
|
||||
onClick: (ruleset: QueryRulesListRulesetsQueryRulesetListItem) => {
|
||||
useTracker?.click?.(AnalyticsEvents.deleteRulesetInlineDropdownClicked);
|
||||
setRulesetToDelete(ruleset.ruleset_id);
|
||||
},
|
||||
},
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
import { EuiFieldSearch } from '@elastic/eui';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useUsageTracker } from '../../hooks/use_usage_tracker';
|
||||
import { AnalyticsEvents } from '../../analytics/constants';
|
||||
|
||||
interface QueryRulesSetsSearchProps {
|
||||
searchKey: string;
|
||||
|
@ -17,12 +19,15 @@ export const QueryRulesSetsSearch: React.FC<QueryRulesSetsSearchProps> = ({
|
|||
searchKey,
|
||||
setSearchKey,
|
||||
}) => {
|
||||
const useTracker = useUsageTracker();
|
||||
const onSearch = useCallback(
|
||||
(newSearch: string) => {
|
||||
useTracker?.load?.(AnalyticsEvents.rulesetSearched);
|
||||
|
||||
const trimSearch = newSearch.trim();
|
||||
setSearchKey(trimSearch);
|
||||
},
|
||||
[setSearchKey]
|
||||
[setSearchKey, useTracker]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -16,6 +16,8 @@ import { QueryRuleFlyout } from './query_rule_flyout/query_rule_flyout';
|
|||
import { useGenerateRuleId } from '../../hooks/use_generate_rule_id';
|
||||
import { SearchQueryRulesQueryRule } from '../../types';
|
||||
import { RulesetDetailEmptyPrompt } from '../empty_prompt/ruleset_detail_empty_prompt';
|
||||
import { useUsageTracker } from '../../hooks/use_usage_tracker';
|
||||
import { AnalyticsEvents } from '../../analytics/constants';
|
||||
|
||||
interface QueryRuleDetailPanelProps {
|
||||
rules: SearchQueryRulesQueryRule[];
|
||||
|
@ -46,6 +48,8 @@ export const QueryRuleDetailPanel: React.FC<QueryRuleDetailPanelProps> = ({
|
|||
const [ruleIdToEdit, setRuleIdToEdit] = React.useState<string | null>(null);
|
||||
const [flyoutMode, setFlyoutMode] = React.useState<'create' | 'edit'>('edit');
|
||||
|
||||
const useTracker = useUsageTracker();
|
||||
|
||||
const { mutate: generateRuleId } = useGenerateRuleId(rulesetId);
|
||||
useEffect(() => {
|
||||
if (createMode && rules.length === 0) {
|
||||
|
@ -94,6 +98,7 @@ export const QueryRuleDetailPanel: React.FC<QueryRuleDetailPanelProps> = ({
|
|||
color="primary"
|
||||
data-test-subj="queryRulesetDetailAddRuleButton"
|
||||
onClick={() => {
|
||||
useTracker?.click(AnalyticsEvents.addRuleClicked);
|
||||
generateRuleId(undefined, {
|
||||
onSuccess: (newRuleId) => {
|
||||
setFlyoutMode('create');
|
||||
|
|
|
@ -27,12 +27,14 @@ import { css } from '@emotion/react';
|
|||
import { QueryRulesQueryRule } from '@elastic/elasticsearch/lib/api/types';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useUsageTracker } from '../../../hooks/use_usage_tracker';
|
||||
import { SearchQueryRulesQueryRule } from '../../../../common/types';
|
||||
import { DroppableContainer } from '../styles';
|
||||
import { QueryRuleDraggableListHeader } from './query_rule_draggable_list_header';
|
||||
import { QueryRuleDraggableListItemActionTypeBadge } from './query_rule_draggable_item_action_type_badge';
|
||||
import { QueryRuleDraggableItemCriteriaDisplay } from './query_rule_draggable_item_criteria_display';
|
||||
import { DeleteRulesetRuleModal } from './delete_ruleset_rule_modal';
|
||||
import { AnalyticsEvents } from '../../../analytics/constants';
|
||||
|
||||
export interface QueryRuleDraggableListItemProps {
|
||||
rules: SearchQueryRulesQueryRule[];
|
||||
|
@ -60,6 +62,7 @@ export const QueryRuleDraggableListItem: React.FC<QueryRuleDraggableListItemProp
|
|||
isLastItem = false,
|
||||
}) => {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const useTracker = useUsageTracker();
|
||||
const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);
|
||||
const localTourTargetRef = useRef<HTMLDivElement>(null);
|
||||
const effectiveRef = tourInfo?.tourTargetRef || localTourTargetRef;
|
||||
|
@ -174,6 +177,7 @@ export const QueryRuleDraggableListItem: React.FC<QueryRuleDraggableListItemProp
|
|||
icon="pencil"
|
||||
data-test-subj="searchQueryRulesQueryRulesetDetailEditButton"
|
||||
onClick={() => {
|
||||
useTracker?.click(AnalyticsEvents.editRuleClicked);
|
||||
onEditRuleFlyoutOpen(queryRule.rule_id);
|
||||
closePopover();
|
||||
}}
|
||||
|
@ -204,6 +208,7 @@ export const QueryRuleDraggableListItem: React.FC<QueryRuleDraggableListItemProp
|
|||
`}
|
||||
data-test-subj="searchQueryRulesQueryRulesetDetailDeleteButton"
|
||||
onClick={() => {
|
||||
useTracker?.click(AnalyticsEvents.deleteRuleClicked);
|
||||
setRuleToDelete(queryRule.rule_id);
|
||||
closePopover();
|
||||
}}
|
||||
|
@ -263,11 +268,13 @@ export const QueryRuleDraggableList: React.FC<QueryRuleDraggableListProps> = ({
|
|||
tourInfo,
|
||||
}) => {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const useTracker = useUsageTracker();
|
||||
|
||||
return (
|
||||
<EuiDragDropContext
|
||||
onDragEnd={({ source, destination }) => {
|
||||
if (source && destination) {
|
||||
useTracker?.click(AnalyticsEvents.rulesReordered);
|
||||
const items = euiDragDropReorder(rules, source.index, destination.index);
|
||||
onReorder(items);
|
||||
}
|
||||
|
|
|
@ -10,9 +10,11 @@ import { useEffect, useState } from 'react';
|
|||
import { useFieldArray, useFormContext, useWatch } from 'react-hook-form';
|
||||
import { OnDragEndResponder } from '@hello-pangea/dnd';
|
||||
import { euiDragDropReorder } from '@elastic/eui';
|
||||
import { AnalyticsEvents } from '../../../analytics/constants';
|
||||
import { QueryRuleEditorForm, SearchQueryRulesQueryRule } from '../../../../common/types';
|
||||
import { useFetchIndexNames } from '../../../hooks/use_fetch_index_names';
|
||||
import { isCriteriaAlways } from '../../../utils/query_rules_utils';
|
||||
import { useUsageTracker } from '../../../hooks/use_usage_tracker';
|
||||
|
||||
export const createEmptyRuleset = (
|
||||
rulesetId: QueryRulesQueryRuleset['ruleset_id']
|
||||
|
@ -39,6 +41,7 @@ export const useQueryRuleFlyoutState = ({
|
|||
setIsFormDirty,
|
||||
onSave,
|
||||
}: UseQueryRuleFlyoutStateProps) => {
|
||||
const usageTracker = useUsageTracker();
|
||||
const { control, getValues, reset, setValue, formState, trigger } =
|
||||
useFormContext<QueryRuleEditorForm>();
|
||||
const {
|
||||
|
@ -242,6 +245,7 @@ export const useQueryRuleFlyoutState = ({
|
|||
const shouldShowCriteriaCallout = criteriaCalloutActive && !isAlways;
|
||||
|
||||
const dragEndHandle: OnDragEndResponder<string> = ({ source, destination }) => {
|
||||
usageTracker?.click(AnalyticsEvents.ruleFlyoutDocumentsReordered);
|
||||
if (source && destination && (ruleFromRuleset || createMode)) {
|
||||
if (isDocRule) {
|
||||
const newActions = euiDragDropReorder(actionFields, source.index, destination.index);
|
||||
|
|
|
@ -40,6 +40,8 @@ import { DeleteRulesetModal } from '../query_rules_sets/delete_ruleset_modal';
|
|||
import { QueryRuleDetailPanel } from './query_rule_detail_panel';
|
||||
import { useQueryRulesetDetailState } from './use_query_ruleset_detail_state';
|
||||
import { useFetchQueryRulesetExist } from '../../hooks/use_fetch_ruleset_exists';
|
||||
import { AnalyticsEvents } from '../../analytics/constants';
|
||||
import { useUsageTracker } from '../../hooks/use_usage_tracker';
|
||||
|
||||
export interface QueryRulesetDetailProps {
|
||||
createMode?: boolean;
|
||||
|
@ -55,6 +57,7 @@ export const QueryRulesetDetail: React.FC<QueryRulesetDetailProps> = ({ createMo
|
|||
}>();
|
||||
const { data: rulesetExists, isLoading: isFailsafeLoading } =
|
||||
useFetchQueryRulesetExist(rulesetId);
|
||||
const useTracker = useUsageTracker();
|
||||
|
||||
useEffect(() => {
|
||||
// This is a failsafe in case user navigates to an existing ruleset via URL directly
|
||||
|
@ -63,6 +66,10 @@ export const QueryRulesetDetail: React.FC<QueryRulesetDetailProps> = ({ createMo
|
|||
}
|
||||
}, [createMode, rulesetExists, application, http.basePath, rulesetId]);
|
||||
|
||||
useEffect(() => {
|
||||
useTracker?.load?.(AnalyticsEvents.rulesetDetailPageLoaded);
|
||||
}, [useTracker]);
|
||||
|
||||
const blockRender = (createMode && rulesetExists) || isFailsafeLoading;
|
||||
|
||||
const { mutate: createRuleset } = usePutRuleset(() => {
|
||||
|
@ -186,6 +193,9 @@ export const QueryRulesetDetail: React.FC<QueryRulesetDetailProps> = ({ createMo
|
|||
|
||||
const handleSave = () => {
|
||||
setIsFormDirty(false);
|
||||
useTracker?.click(
|
||||
createMode ? AnalyticsEvents.rulesetCreateClicked : AnalyticsEvents.rulesetUpdateClicked
|
||||
);
|
||||
createRuleset({
|
||||
rulesetId,
|
||||
forceWrite: true,
|
||||
|
@ -232,8 +242,10 @@ export const QueryRulesetDetail: React.FC<QueryRulesetDetailProps> = ({ createMo
|
|||
),
|
||||
color: 'primary',
|
||||
'aria-current': false,
|
||||
onClick: () =>
|
||||
application.navigateToUrl(http.basePath.prepend(`${PLUGIN_ROUTE_ROOT}`)),
|
||||
onClick: () => {
|
||||
useTracker?.click(AnalyticsEvents.backToRulesetListClicked);
|
||||
application.navigateToUrl(http.basePath.prepend(`${PLUGIN_ROUTE_ROOT}`));
|
||||
},
|
||||
},
|
||||
]}
|
||||
restrictWidth
|
||||
|
@ -331,7 +343,10 @@ export const QueryRulesetDetail: React.FC<QueryRulesetDetailProps> = ({ createMo
|
|||
content={i18n.translate('xpack.queryRules.queryRulesetDetail.testButton', {
|
||||
defaultMessage: 'Test in Console',
|
||||
})}
|
||||
onClick={finishTour}
|
||||
onClick={() => {
|
||||
useTracker?.click(AnalyticsEvents.testInConsoleClicked);
|
||||
finishTour();
|
||||
}}
|
||||
/>
|
||||
</EuiTourStep>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { useKibana } from './use_kibana';
|
||||
|
||||
const APP_TRACKER_NAME = 'search_query_rules';
|
||||
|
||||
export const useUsageTracker = () => {
|
||||
const {
|
||||
services: { usageCollection },
|
||||
} = useKibana();
|
||||
|
||||
return useMemo(() => {
|
||||
if (usageCollection) {
|
||||
return {
|
||||
click: usageCollection.reportUiCounter.bind(
|
||||
usageCollection,
|
||||
APP_TRACKER_NAME,
|
||||
METRIC_TYPE.CLICK
|
||||
),
|
||||
count: usageCollection.reportUiCounter.bind(
|
||||
usageCollection,
|
||||
APP_TRACKER_NAME,
|
||||
METRIC_TYPE.COUNT
|
||||
),
|
||||
load: usageCollection.reportUiCounter.bind(
|
||||
usageCollection,
|
||||
APP_TRACKER_NAME,
|
||||
METRIC_TYPE.LOADED
|
||||
),
|
||||
};
|
||||
}
|
||||
}, [usageCollection]);
|
||||
};
|
|
@ -9,6 +9,7 @@ import { SearchNavigationPluginStart } from '@kbn/search-navigation/public';
|
|||
import { AppMountParameters, CoreStart } from '@kbn/core/public';
|
||||
import type { ConsolePluginStart } from '@kbn/console-plugin/public';
|
||||
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
|
||||
export * from '../common/types';
|
||||
export interface AppPluginStartDependencies {
|
||||
|
@ -16,6 +17,7 @@ export interface AppPluginStartDependencies {
|
|||
console?: ConsolePluginStart;
|
||||
share?: SharePluginStart;
|
||||
searchNavigation?: SearchNavigationPluginStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}
|
||||
|
||||
export type AppServicesContext = CoreStart & AppPluginStartDependencies;
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
"@kbn/search-index-documents",
|
||||
"@kbn/unsaved-changes-prompt",
|
||||
"@kbn/deeplinks-analytics",
|
||||
"@kbn/analytics",
|
||||
"@kbn/usage-collection-plugin",
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue