From a2a135d5b0541e237700264633b8d34e4eef95ad Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 30 Sep 2024 20:48:14 +1000 Subject: [PATCH] [8.x] [Cloud Security] UI counter telemetry (#194390) # Backport This will backport the following commits from `main` to `8.x`: - [[Cloud Security] UI counter telemetry](https://github.com/elastic/kibana/pull/193721) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) Co-authored-by: Ido Cohen <90558359+CohenIdo@users.noreply.github.com> --- .../index.ts | 1 + .../tsconfig.json | 2 + .../utils/ui_metrics.ts | 57 +++++++++++++++++++ .../use_cloud_security_grouping.ts | 6 ++ .../components/detection_rule_counter.tsx | 6 ++ .../public/components/take_action.tsx | 10 +++- .../latest_findings/latest_findings_table.tsx | 7 ++- .../public/pages/rules/rules_table.tsx | 6 ++ .../vulnerability_overview_tab.tsx | 8 +++ .../cloud_security_posture/public/plugin.tsx | 4 ++ .../cloud_security_posture/tsconfig.json | 3 +- ...isconfiguration_findings_details_table.tsx | 14 +++++ .../entity_details_flyout/index.tsx | 31 ++++++---- .../security_solution/public/plugin.tsx | 4 ++ 14 files changed, 145 insertions(+), 14 deletions(-) create mode 100644 x-pack/packages/kbn-cloud-security-posture-common/utils/ui_metrics.ts diff --git a/x-pack/packages/kbn-cloud-security-posture-common/index.ts b/x-pack/packages/kbn-cloud-security-posture-common/index.ts index 4cb5a8d6e1bd8..dc4e930f537e6 100644 --- a/x-pack/packages/kbn-cloud-security-posture-common/index.ts +++ b/x-pack/packages/kbn-cloud-security-posture-common/index.ts @@ -27,3 +27,4 @@ export { buildEntityFlyoutPreviewQuery, } from './utils/helpers'; export { getAbbreviatedNumber } from './utils/get_abbreviated_number'; +export { UiMetricService } from './utils/ui_metrics'; diff --git a/x-pack/packages/kbn-cloud-security-posture-common/tsconfig.json b/x-pack/packages/kbn-cloud-security-posture-common/tsconfig.json index 17961df586258..c6bdf82c1d223 100644 --- a/x-pack/packages/kbn-cloud-security-posture-common/tsconfig.json +++ b/x-pack/packages/kbn-cloud-security-posture-common/tsconfig.json @@ -18,5 +18,7 @@ "@kbn/config-schema", "@kbn/data-views-plugin", "@kbn/i18n", + "@kbn/analytics", + "@kbn/usage-collection-plugin", ] } diff --git a/x-pack/packages/kbn-cloud-security-posture-common/utils/ui_metrics.ts b/x-pack/packages/kbn-cloud-security-posture-common/utils/ui_metrics.ts new file mode 100644 index 0000000000000..9ea12ef7ed45f --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture-common/utils/ui_metrics.ts @@ -0,0 +1,57 @@ +/* + * 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 { UiCounterMetricType } from '@kbn/analytics'; +import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; + +export const APP_NAME = 'cloud-security'; + +export const ENTITY_FLYOUT_MISCONFIGURATION_VIEW_VISITS = + 'entity-flyout-misconfiguration-view-visits'; +export const NAV_TO_FINDINGS_BY_HOST_NAME_FRPOM_ENTITY_FLYOUT = + 'nav-to-findings-by-host-name-from-entity-flyout'; +export const NAV_TO_FINDINGS_BY_RULE_NAME_FRPOM_ENTITY_FLYOUT = + 'nav-to-findings-by-rule-name-from-entity-flyout'; +export const CREATE_DETECTION_RULE_FROM_FLYOUT = 'create-detection-rule-from-flyout'; +export const CREATE_DETECTION_FROM_TABLE_ROW_ACTION = 'create-detection-from-table-row-action'; +export const VULNERABILITIES_FLYOUT_VISITS = 'vulnerabilities-flyout-visits'; +export const OPEN_FINDINGS_FLYOUT = 'open-findings-flyout'; +export const GROUP_BY_CLICK = 'group-by-click'; +export const CHANGE_RULE_STATE = 'change-rule-state'; + +type CloudSecurityUiCounters = + | typeof ENTITY_FLYOUT_MISCONFIGURATION_VIEW_VISITS + | typeof NAV_TO_FINDINGS_BY_HOST_NAME_FRPOM_ENTITY_FLYOUT + | typeof VULNERABILITIES_FLYOUT_VISITS + | typeof NAV_TO_FINDINGS_BY_RULE_NAME_FRPOM_ENTITY_FLYOUT + | typeof OPEN_FINDINGS_FLYOUT + | typeof CREATE_DETECTION_RULE_FROM_FLYOUT + | typeof CREATE_DETECTION_FROM_TABLE_ROW_ACTION + | typeof GROUP_BY_CLICK + | typeof CHANGE_RULE_STATE; + +export class UiMetricService { + private usageCollection: UsageCollectionSetup | undefined; + + public setup(usageCollection: UsageCollectionSetup) { + this.usageCollection = usageCollection; + } + + private track(metricType: UiCounterMetricType, eventName: CloudSecurityUiCounters) { + if (!this.usageCollection) { + // Usage collection might be disabled in Kibana config. + return; + } + return this.usageCollection.reportUiCounter(APP_NAME, metricType, eventName); + } + + public trackUiMetric(metricType: UiCounterMetricType, eventName: CloudSecurityUiCounters) { + return this.track(metricType, eventName); + } +} + +export const uiMetricService = new UiMetricService(); diff --git a/x-pack/plugins/cloud_security_posture/public/components/cloud_security_grouping/use_cloud_security_grouping.ts b/x-pack/plugins/cloud_security_posture/public/components/cloud_security_grouping/use_cloud_security_grouping.ts index e480233f376fa..026ec612ea115 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/cloud_security_grouping/use_cloud_security_grouping.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/cloud_security_grouping/use_cloud_security_grouping.ts @@ -9,6 +9,11 @@ import { isNoneGroup, useGrouping } from '@kbn/grouping'; import * as uuid from 'uuid'; import type { DataView } from '@kbn/data-views-plugin/common'; import { GroupOption, GroupPanelRenderer, GetGroupStats } from '@kbn/grouping/src'; +import { + GROUP_BY_CLICK, + uiMetricService, +} from '@kbn/cloud-security-posture-common/utils/ui_metrics'; +import { METRIC_TYPE } from '@kbn/analytics'; import { useUrlQuery } from '../../common/hooks/use_url_query'; @@ -73,6 +78,7 @@ export const useCloudSecurityGrouping = ({ setUrlQuery({ groupBy: groupByFields, }); + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, GROUP_BY_CLICK); }, }); diff --git a/x-pack/plugins/cloud_security_posture/public/components/detection_rule_counter.tsx b/x-pack/plugins/cloud_security_posture/public/components/detection_rule_counter.tsx index 5465c144b6772..01309ce334d3c 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/detection_rule_counter.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/detection_rule_counter.tsx @@ -9,6 +9,11 @@ import React, { useCallback, useState } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiLink, EuiLoadingSpinner, EuiSkeletonText, EuiText } from '@elastic/eui'; import type { HttpSetup } from '@kbn/core/public'; +import { + CREATE_DETECTION_RULE_FROM_FLYOUT, + uiMetricService, +} from '@kbn/cloud-security-posture-common/utils/ui_metrics'; +import { METRIC_TYPE } from '@kbn/analytics'; import { useHistory } from 'react-router-dom'; import useSessionStorage from 'react-use/lib/useSessionStorage'; import { useQueryClient } from '@tanstack/react-query'; @@ -62,6 +67,7 @@ export const DetectionRuleCounter = ({ tags, createRuleFn }: DetectionRuleCounte }, [history]); const createDetectionRuleOnClick = useCallback(async () => { + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, CREATE_DETECTION_RULE_FROM_FLYOUT); const startServices = { analytics, notifications, i18n, theme }; setIsCreateRuleLoading(true); const ruleResponse = await createRuleFn(http); diff --git a/x-pack/plugins/cloud_security_posture/public/components/take_action.tsx b/x-pack/plugins/cloud_security_posture/public/components/take_action.tsx index 5db9482c8b41a..8c7bcb5886d8d 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/take_action.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/take_action.tsx @@ -22,6 +22,11 @@ import type { HttpSetup } from '@kbn/core/public'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n as kbnI18n } from '@kbn/i18n'; import { QueryClient, useMutation, useQueryClient } from '@tanstack/react-query'; +import { + CREATE_DETECTION_FROM_TABLE_ROW_ACTION, + uiMetricService, +} from '@kbn/cloud-security-posture-common/utils/ui_metrics'; +import { METRIC_TYPE } from '@kbn/analytics'; import type { RuleResponse } from '../common/types'; import { CREATE_RULE_ACTION_SUBJ, TAKE_ACTION_SUBJ } from './test_subjects'; import { useKibana } from '../common/hooks/use_kibana'; @@ -239,7 +244,10 @@ const CreateDetectionRule = ({ mutate()} + onClick={() => { + mutate(); + uiMetricService.trackUiMetric(METRIC_TYPE.CLICK, CREATE_DETECTION_FROM_TABLE_ROW_ACTION); + }} data-test-subj={CREATE_RULE_ACTION_SUBJ} > | undefined): CspFinding | un const flyoutComponent = (row: DataTableRecord, onCloseFlyout: () => void): JSX.Element => { const finding = row.raw._source; if (!finding || !isCspFinding(finding)) return <>; - + uiMetricService.trackUiMetric(METRIC_TYPE.COUNT, OPEN_FINDINGS_FLYOUT); return ; }; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_table.tsx index 54513283cec5c..a30e009c85198 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_table.tsx @@ -19,6 +19,11 @@ import { EuiTableSortingType, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { METRIC_TYPE } from '@kbn/analytics'; +import { + CHANGE_RULE_STATE, + uiMetricService, +} from '@kbn/cloud-security-posture-common/utils/ui_metrics'; import { uniqBy } from 'lodash'; import { ColumnNameWithTooltip } from '../../components/column_name_with_tooltip'; import type { CspBenchmarkRulesWithStates, RulesState } from './rules_container'; @@ -281,6 +286,7 @@ const RuleStateSwitch = ({ rule }: { rule: CspBenchmarkRulesWithStates }) => { }; const changeCspRuleStateFn = async () => { if (rule?.metadata.benchmark.rule_number) { + uiMetricService.trackUiMetric(METRIC_TYPE.COUNT, CHANGE_RULE_STATE); mutateRulesStates({ newState: nextRuleState, ruleIds: [rulesObjectRequest], diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_overview_tab.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_overview_tab.tsx index e25bbbf6c3111..b050b374d692a 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_overview_tab.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/vulnerabilities_finding_flyout/vulnerability_overview_tab.tsx @@ -23,6 +23,12 @@ import { VectorScoreBase, CspVulnerabilityFinding, } from '@kbn/cloud-security-posture-common/schema/vulnerabilities/latest'; +import { METRIC_TYPE } from '@kbn/analytics'; + +import { + VULNERABILITIES_FLYOUT_VISITS, + uiMetricService, +} from '@kbn/cloud-security-posture-common/utils/ui_metrics'; import { getDatasetDisplayName } from '../../../common/utils/get_dataset_display_name'; import { CspFlyoutMarkdown } from '../../configurations/findings_flyout/findings_flyout'; import { NvdLogo } from '../../../assets/icons/nvd_logo_svg'; @@ -218,6 +224,8 @@ const VulnerabilityOverviewTiles = ({ vulnerabilityRecord }: VulnerabilityTabPro export const VulnerabilityOverviewTab = ({ vulnerabilityRecord }: VulnerabilityTabProps) => { const { vulnerability } = vulnerabilityRecord; + uiMetricService.trackUiMetric(METRIC_TYPE.COUNT, VULNERABILITIES_FLYOUT_VISITS); + const emptyFixesMessageState = i18n.translate( 'xpack.csp.vulnerabilities.vulnerabilityOverviewTab.emptyFixesMessage', { diff --git a/x-pack/plugins/cloud_security_posture/public/plugin.tsx b/x-pack/plugins/cloud_security_posture/public/plugin.tsx index d07d930660ec6..b66e7a2b62f2e 100755 --- a/x-pack/plugins/cloud_security_posture/public/plugin.tsx +++ b/x-pack/plugins/cloud_security_posture/public/plugin.tsx @@ -10,6 +10,7 @@ import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app'; import type { CspClientPluginStartDeps } from '@kbn/cloud-security-posture'; +import { uiMetricService } from '@kbn/cloud-security-posture-common/utils/ui_metrics'; import { CspLoadingState } from './components/csp_loading_state'; import type { CspRouterProps } from './application/csp_router'; import type { CspClientPluginSetup, CspClientPluginStart, CspClientPluginSetupDeps } from './types'; @@ -47,6 +48,9 @@ export class CspPlugin plugins: CspClientPluginSetupDeps ): CspClientPluginSetup { this.isCloudEnabled = plugins.cloud.isCloudEnabled; + + if (plugins.usageCollection) uiMetricService.setup(plugins.usageCollection); + // Return methods that should be available to other plugins return {}; } diff --git a/x-pack/plugins/cloud_security_posture/tsconfig.json b/x-pack/plugins/cloud_security_posture/tsconfig.json index 4e43b6df2485e..501f9a560cdf6 100755 --- a/x-pack/plugins/cloud_security_posture/tsconfig.json +++ b/x-pack/plugins/cloud_security_posture/tsconfig.json @@ -64,7 +64,8 @@ "@kbn/react-kibana-mount", "@kbn/spaces-plugin", "@kbn/cloud-security-posture-common", - "@kbn/cloud-security-posture" + "@kbn/cloud-security-posture", + "@kbn/analytics" ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx b/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx index ba413709d6cca..a27f92407fbdd 100644 --- a/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx +++ b/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx @@ -17,6 +17,12 @@ import { DistributionBar } from '@kbn/security-solution-distribution-bar'; import { useNavigateFindings } from '@kbn/cloud-security-posture/src/hooks/use_navigate_findings'; import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { CspEvaluationBadge } from '@kbn/cloud-security-posture'; +import { + NAV_TO_FINDINGS_BY_HOST_NAME_FRPOM_ENTITY_FLYOUT, + NAV_TO_FINDINGS_BY_RULE_NAME_FRPOM_ENTITY_FLYOUT, + uiMetricService, +} from '@kbn/cloud-security-posture-common/utils/ui_metrics'; +import { METRIC_TYPE } from '@kbn/analytics'; type MisconfigurationFindingDetailFields = Pick; @@ -107,6 +113,10 @@ export const MisconfigurationFindingsDetailsTable = memo( }; const navToFindingsByName = (name: string, queryField: 'host.name' | 'user.name') => { + uiMetricService.trackUiMetric( + METRIC_TYPE.CLICK, + NAV_TO_FINDINGS_BY_RULE_NAME_FRPOM_ENTITY_FLYOUT + ); navToFindings({ [queryField]: name }, ['rule.name']); }; @@ -154,6 +164,10 @@ export const MisconfigurationFindingsDetailsTable = memo( { + uiMetricService.trackUiMetric( + METRIC_TYPE.CLICK, + NAV_TO_FINDINGS_BY_HOST_NAME_FRPOM_ENTITY_FLYOUT + ); navToFindingsByName(queryName, fieldName); }} > diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/index.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/index.tsx index 2a94ee0438293..ddcdc252bff76 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/index.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/index.tsx @@ -7,6 +7,11 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; +import { + ENTITY_FLYOUT_MISCONFIGURATION_VIEW_VISITS, + uiMetricService, +} from '@kbn/cloud-security-posture-common/utils/ui_metrics'; +import { METRIC_TYPE } from '@kbn/analytics'; import { EntityDetailsLeftPanelTab } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header'; import { PREFIX } from '../../../flyout/shared/test_ids'; import type { RiskInputsTabProps } from './tabs/risk_inputs/risk_inputs_tab'; @@ -34,14 +39,18 @@ export const getInsightsInputTab = ({ }: { name: string; fieldName: 'host.name' | 'user.name'; -}) => ({ - id: EntityDetailsLeftPanelTab.CSP_INSIGHTS, - 'data-test-subj': INSIGHTS_TAB_TEST_ID, - name: ( - - ), - content: , -}); +}) => { + uiMetricService.trackUiMetric(METRIC_TYPE.COUNT, ENTITY_FLYOUT_MISCONFIGURATION_VIEW_VISITS); + + return { + id: EntityDetailsLeftPanelTab.CSP_INSIGHTS, + 'data-test-subj': INSIGHTS_TAB_TEST_ID, + name: ( + + ), + content: , + }; +}; diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index 991f591773aa7..f7c35fbcb99f5 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -20,6 +20,7 @@ import type { import { DEFAULT_APP_CATEGORIES } from '@kbn/core/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import type { TriggersAndActionsUIPublicPluginSetup } from '@kbn/triggers-actions-ui-plugin/public'; +import { uiMetricService } from '@kbn/cloud-security-posture-common/utils/ui_metrics'; import { getLazyCloudSecurityPosturePliAuthBlockExtension } from './cloud_security_posture/lazy_cloud_security_posture_pli_auth_block_extension'; import { getLazyEndpointAgentTamperProtectionExtension } from './management/pages/policy/view/ingest_manager_integration/lazy_endpoint_agent_tamper_protection_extension'; import type { @@ -107,6 +108,9 @@ export class Plugin implements IPlugin