diff --git a/x-pack/plugins/observability_solution/infra/public/components/ml/anomaly_detection/job_setup_screen.tsx b/x-pack/plugins/observability_solution/infra/public/components/ml/anomaly_detection/job_setup_screen.tsx index 9543e84585c02..e2ee8a127a881 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/ml/anomaly_detection/job_setup_screen.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/ml/anomaly_detection/job_setup_screen.tsx @@ -38,7 +38,7 @@ import { FixedDatePicker } from '../../fixed_datepicker'; import { DEFAULT_K8S_PARTITION_FIELD } from '../../../containers/ml/modules/metrics_k8s/module_descriptor'; import { convertKueryToElasticSearchQuery } from '../../../utils/kuery'; import { INFRA_ML_FLYOUT_FEEDBACK_LINK } from './flyout_home'; -import { KibanaEnvironmentContext } from '../../../hooks/use_kibana'; +import { KibanaEnvironmentContext, useKibanaContextForPlugin } from '../../../hooks/use_kibana'; import { MetricsExplorerKueryBar } from '../../../pages/metrics/metrics_explorer/components/kuery_bar'; interface Props { @@ -60,6 +60,7 @@ export const JobSetupScreen = (props: Props) => { const trackMetric = useUiTracker({ app: 'infra_metrics' }); const { kibanaVersion, isCloudEnv, isServerlessEnv } = useContext(KibanaEnvironmentContext); const { euiTheme } = useEuiTheme(); + const { telemetry } = useKibanaContextForPlugin().services; const indices = host.sourceConfiguration.indices; @@ -95,23 +96,47 @@ export const JobSetupScreen = (props: Props) => { } }, [props.jobType, kubernetes.jobSummaries, host.jobSummaries]); - const updateStart = useCallback((date: Moment) => { - setStartDate(date); - }, []); + const updateStart = useCallback( + (date: Moment) => { + setStartDate(date); + telemetry.reportAnomalyDetectionDateFieldChange({ + job_type: props.jobType, + start_date: date.toISOString(), + }); + }, + [telemetry, props.jobType] + ); const createJobs = useCallback(() => { + const date = moment(startDate).toDate(); if (hasSummaries) { + telemetry.reportAnomalyDetectionSetup({ + job_type: props.jobType, + configured_fields: { + start_date: date.toISOString(), + partition_field: partitionField ? partitionField[0] : undefined, + filter_field: filter ? filter : undefined, + }, + }); cleanUpAndSetUpModule( indices, - moment(startDate).toDate().getTime(), + date.getTime(), undefined, filterQuery, partitionField ? partitionField[0] : undefined ); } else { + telemetry.reportAnomalyDetectionSetup({ + job_type: props.jobType, + configured_fields: { + start_date: date.toISOString(), + partition_field: partitionField ? partitionField[0] : undefined, + filter_field: filter, + }, + }); setUpModule( indices, - moment(startDate).toDate().getTime(), + date.getTime(), undefined, filterQuery, partitionField ? partitionField[0] : undefined @@ -125,22 +150,36 @@ export const JobSetupScreen = (props: Props) => { indices, partitionField, startDate, + telemetry, + filter, + props.jobType, ]); const onFilterChange = useCallback( (f: string) => { setFilter(f || ''); setFilterQuery(convertKueryToElasticSearchQuery(f, metricsView?.dataViewReference) || ''); + telemetry.reportAnomalyDetectionFilterFieldChange({ + job_type: props.jobType, + filter_field: f ? f : undefined, + }); }, - [metricsView?.dataViewReference] + [metricsView?.dataViewReference, telemetry, props.jobType] ); /* eslint-disable-next-line react-hooks/exhaustive-deps */ const debouncedOnFilterChange = useCallback(debounce(onFilterChange, 500), [onFilterChange]); - const onPartitionFieldChange = useCallback((value: Array<{ label: string }>) => { - setPartitionField(value.map((v) => v.label)); - }, []); + const onPartitionFieldChange = useCallback( + (value: Array<{ label: string }>) => { + setPartitionField(value.map((v) => v.label)); + telemetry.reportAnomalyDetectionPartitionFieldChange({ + job_type: props.jobType, + partition_field: value.length > 0 ? value[0].label : undefined, + }); + }, + [telemetry, props.jobType] + ); useEffect(() => { if (props.jobType === 'kubernetes') { diff --git a/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.mock.ts b/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.mock.ts index d5ea4958b95f2..2f68c4f5501c6 100644 --- a/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.mock.ts +++ b/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.mock.ts @@ -21,4 +21,8 @@ export const createTelemetryClientMock = (): jest.Mocked => ({ reportAddMetricsCalloutTryItClicked: jest.fn(), reportAddMetricsCalloutLearnMoreClicked: jest.fn(), reportAddMetricsCalloutDismissed: jest.fn(), + reportAnomalyDetectionSetup: jest.fn(), + reportAnomalyDetectionDateFieldChange: jest.fn(), + reportAnomalyDetectionFilterFieldChange: jest.fn(), + reportAnomalyDetectionPartitionFieldChange: jest.fn(), }); diff --git a/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts b/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts index d5dcf9d3f0c8d..0adf6a04dea7f 100644 --- a/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts +++ b/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_client.ts @@ -9,6 +9,10 @@ import type { AnalyticsServiceSetup } from '@kbn/core-analytics-server'; import { reportPerformanceMetricEvent } from '@kbn/ebt-tools'; import { AddMetricsCalloutEventParams, + AnomalyDetectionDateFieldChangeParams, + AnomalyDetectionFilterFieldChangeParams, + AnomalyDetectionPartitionFieldChangeParams, + AnomalyDetectionSetupParams, AssetDashboardLoadedParams, AssetDetailsFlyoutViewedParams, AssetDetailsPageViewedParams, @@ -114,4 +118,35 @@ export class TelemetryClient implements ITelemetryClient { public reportAddMetricsCalloutDismissed = (params: AddMetricsCalloutEventParams) => { this.analytics.reportEvent(InfraTelemetryEventTypes.ADD_METRICS_CALLOUT_DISMISSED, params); }; + + public reportAnomalyDetectionSetup = (params: AnomalyDetectionSetupParams) => { + this.analytics.reportEvent(InfraTelemetryEventTypes.ANOMALY_DETECTION_SETUP, params); + }; + + public reportAnomalyDetectionDateFieldChange = ( + params: AnomalyDetectionDateFieldChangeParams + ) => { + this.analytics.reportEvent( + InfraTelemetryEventTypes.ANOMALY_DETECTION_DATE_FIELD_CHANGE, + params + ); + }; + + public reportAnomalyDetectionPartitionFieldChange = ( + params: AnomalyDetectionPartitionFieldChangeParams + ) => { + this.analytics.reportEvent( + InfraTelemetryEventTypes.ANOMALY_DETECTION_PARTITION_FIELD_CHANGE, + params + ); + }; + + public reportAnomalyDetectionFilterFieldChange = ( + params: AnomalyDetectionFilterFieldChangeParams + ) => { + this.analytics.reportEvent( + InfraTelemetryEventTypes.ANOMALY_DETECTION_FILTER_FIELD_CHANGE, + params + ); + }; } diff --git a/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_events.ts b/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_events.ts index ec2f918354cbf..7f025c1051755 100644 --- a/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_events.ts +++ b/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_events.ts @@ -264,6 +264,98 @@ const addMetricsCalloutDismissed: InfraTelemetryEvent = { }, }; +const anomalyDetectionSetup: InfraTelemetryEvent = { + eventType: InfraTelemetryEventTypes.ANOMALY_DETECTION_SETUP, + schema: { + job_type: { + type: 'text', + _meta: { + description: 'Type of job for the anomaly detection', + }, + }, + configured_fields: { + properties: { + start_date: { + type: 'text', + _meta: { + description: 'Start date for the anomaly detection job', + }, + }, + partition_field: { + type: 'text', + _meta: { + description: 'Partition field for the anomaly detection job', + optional: true, + }, + }, + filter_field: { + type: 'text', + _meta: { + description: 'Filter field for the anomaly detection job', + optional: true, + }, + }, + }, + }, + }, +}; + +const anomalyDetectionDateFieldChange: InfraTelemetryEvent = { + eventType: InfraTelemetryEventTypes.ANOMALY_DETECTION_DATE_FIELD_CHANGE, + schema: { + job_type: { + type: 'text', + _meta: { + description: 'Type of job for the anomaly detection', + }, + }, + start_date: { + type: 'text', + _meta: { + description: 'Start date for the anomaly detection job', + }, + }, + }, +}; + +const anomalyDetectionPartitionFieldChange: InfraTelemetryEvent = { + eventType: InfraTelemetryEventTypes.ANOMALY_DETECTION_PARTITION_FIELD_CHANGE, + schema: { + job_type: { + type: 'text', + _meta: { + description: 'Type of job for the anomaly detection', + }, + }, + partition_field: { + type: 'text', + _meta: { + description: 'Partition field for the anomaly detection job', + optional: true, + }, + }, + }, +}; + +const anomalyDetectionFilterFieldChange: InfraTelemetryEvent = { + eventType: InfraTelemetryEventTypes.ANOMALY_DETECTION_FILTER_FIELD_CHANGE, + schema: { + job_type: { + type: 'text', + _meta: { + description: 'Type of job for the anomaly detection', + }, + }, + filter_field: { + type: 'text', + _meta: { + description: 'Filter field for the anomaly detection job', + optional: true, + }, + }, + }, +}; + export const infraTelemetryEvents = [ assetDetailsFlyoutViewed, assetDetailsPageViewed, @@ -277,4 +369,8 @@ export const infraTelemetryEvents = [ addMetricsCalloutTryItClicked, addMetricsCalloutLearnMoreClicked, addMetricsCalloutDismissed, + anomalyDetectionSetup, + anomalyDetectionDateFieldChange, + anomalyDetectionPartitionFieldChange, + anomalyDetectionFilterFieldChange, ]; diff --git a/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts b/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts index 78f4d0e64d792..afce0e37126a5 100644 --- a/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts +++ b/x-pack/plugins/observability_solution/infra/public/services/telemetry/telemetry_service.test.ts @@ -52,6 +52,19 @@ describe('TelemetryService', () => { expect(telemetry).toHaveProperty('reportHostFlyoutFilterRemoved'); expect(telemetry).toHaveProperty('reportHostFlyoutFilterAdded'); expect(telemetry).toHaveProperty('reportHostsViewQuerySubmitted'); + expect(telemetry).toHaveProperty('reportHostsViewTotalHostCountRetrieved'); + expect(telemetry).toHaveProperty('reportAssetDetailsFlyoutViewed'); + expect(telemetry).toHaveProperty('reportAssetDetailsPageViewed'); + expect(telemetry).toHaveProperty('reportPerformanceMetricEvent'); + expect(telemetry).toHaveProperty('reportAssetDashboardLoaded'); + expect(telemetry).toHaveProperty('reportAddMetricsCalloutAddMetricsClicked'); + expect(telemetry).toHaveProperty('reportAddMetricsCalloutTryItClicked'); + expect(telemetry).toHaveProperty('reportAddMetricsCalloutLearnMoreClicked'); + expect(telemetry).toHaveProperty('reportAddMetricsCalloutDismissed'); + expect(telemetry).toHaveProperty('reportAnomalyDetectionSetup'); + expect(telemetry).toHaveProperty('reportAnomalyDetectionDateFieldChange'); + expect(telemetry).toHaveProperty('reportAnomalyDetectionPartitionFieldChange'); + expect(telemetry).toHaveProperty('reportAnomalyDetectionFilterFieldChange'); }); }); @@ -343,4 +356,99 @@ describe('TelemetryService', () => { ); }); }); + + describe('#reportAnomalyDetectionSetup', () => { + it('should report anomaly detection setup with properties', async () => { + const setupParams = getSetupParams(); + service.setup(setupParams); + const telemetry = service.start(); + const jobType = 'host'; + const configuredFields = { + start_date: new Date().toISOString(), + partition_field: 'partitionField', + filter_field: 'filterField', + }; + + telemetry.reportAnomalyDetectionSetup({ + job_type: jobType, + configured_fields: configuredFields, + }); + + expect(setupParams.analytics.reportEvent).toHaveBeenCalledTimes(1); + expect(setupParams.analytics.reportEvent).toHaveBeenCalledWith( + 'Infra Anomaly Detection Job Setup', + { + job_type: jobType, + configured_fields: configuredFields, + } + ); + }); + }); + + describe('#reportAnomalyDetectionDateFieldChange', () => { + it('should report anomaly detection date field change with properties', async () => { + const setupParams = getSetupParams(); + service.setup(setupParams); + const telemetry = service.start(); + const startDate = new Date().toISOString(); + + telemetry.reportAnomalyDetectionDateFieldChange({ + job_type: 'host', + start_date: startDate, + }); + + expect(setupParams.analytics.reportEvent).toHaveBeenCalledTimes(1); + expect(setupParams.analytics.reportEvent).toHaveBeenCalledWith( + 'Infra Anomaly Detection Job Date Field Change', + { + job_type: 'host', + start_date: startDate, + } + ); + }); + }); + + describe('#reportAnomalyDetectionPartitionFieldChange', () => { + it('should report anomaly detection partition field change with properties', async () => { + const setupParams = getSetupParams(); + service.setup(setupParams); + const telemetry = service.start(); + + telemetry.reportAnomalyDetectionPartitionFieldChange({ + job_type: 'host', + partition_field: 'partitionField', + }); + + expect(setupParams.analytics.reportEvent).toHaveBeenCalledTimes(1); + expect(setupParams.analytics.reportEvent).toHaveBeenCalledWith( + 'Infra Anomaly Detection Job Partition Field Change', + { + job_type: 'host', + partition_field: 'partitionField', + } + ); + }); + }); + + describe('#reportAnomalyDetectionFilterFieldChange', () => { + it('should report anomaly detection filter field change with properties', async () => { + const setupParams = getSetupParams(); + service.setup(setupParams); + const telemetry = service.start(); + + telemetry.reportAnomalyDetectionFilterFieldChange({ + job_type: 'host', + filter_field: 'filterField', + }); + + expect(setupParams.analytics.reportEvent).toHaveBeenCalledTimes(1); + expect(setupParams.analytics.reportEvent).toHaveBeenCalledWith( + 'Infra Anomaly Detection Job Filter Field Change', + { + job_type: 'host', + filter_field: 'filterField', + } + ); + }); + }); }); diff --git a/x-pack/plugins/observability_solution/infra/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/infra/public/services/telemetry/types.ts index 14816421fe695..982fddfd9492c 100644 --- a/x-pack/plugins/observability_solution/infra/public/services/telemetry/types.ts +++ b/x-pack/plugins/observability_solution/infra/public/services/telemetry/types.ts @@ -26,6 +26,10 @@ export enum InfraTelemetryEventTypes { ADD_METRICS_CALLOUT_TRY_IT_CLICKED = 'Add Metrics Callout Try It Clicked', ADD_METRICS_CALLOUT_LEARN_MORE_CLICKED = 'Add Metrics Callout Learn More Clicked', ADD_METRICS_CALLOUT_DISMISSED = 'Add Metrics Callout Dismissed', + ANOMALY_DETECTION_SETUP = 'Infra Anomaly Detection Job Setup', + ANOMALY_DETECTION_DATE_FIELD_CHANGE = 'Infra Anomaly Detection Job Date Field Change', + ANOMALY_DETECTION_PARTITION_FIELD_CHANGE = 'Infra Anomaly Detection Job Partition Field Change', + ANOMALY_DETECTION_FILTER_FIELD_CHANGE = 'Infra Anomaly Detection Job Filter Field Change', } export interface HostsViewQuerySubmittedParams { @@ -69,6 +73,26 @@ export interface AddMetricsCalloutEventParams { view: string; } +export interface AnomalyDetectionSetupParams { + job_type: string; + configured_fields: { start_date: string; partition_field?: string; filter_field?: string }; +} + +export interface AnomalyDetectionDateFieldChangeParams { + job_type: string; + start_date: string; +} + +export interface AnomalyDetectionPartitionFieldChangeParams { + job_type: string; + partition_field?: string; +} + +export interface AnomalyDetectionFilterFieldChangeParams { + job_type: string; + filter_field?: string; +} + export type InfraTelemetryEventParams = | HostsViewQuerySubmittedParams | HostEntryClickedParams @@ -76,7 +100,11 @@ export type InfraTelemetryEventParams = | HostsViewQueryHostsCountRetrievedParams | AssetDetailsFlyoutViewedParams | AssetDashboardLoadedParams - | AddMetricsCalloutEventParams; + | AddMetricsCalloutEventParams + | AnomalyDetectionSetupParams + | AnomalyDetectionDateFieldChangeParams + | AnomalyDetectionPartitionFieldChangeParams + | AnomalyDetectionFilterFieldChangeParams; export interface PerformanceMetricInnerEvents { key1?: string; @@ -102,6 +130,12 @@ export interface ITelemetryClient { reportAddMetricsCalloutTryItClicked(params: AddMetricsCalloutEventParams): void; reportAddMetricsCalloutLearnMoreClicked(params: AddMetricsCalloutEventParams): void; reportAddMetricsCalloutDismissed(params: AddMetricsCalloutEventParams): void; + reportAnomalyDetectionSetup(params: AnomalyDetectionSetupParams): void; + reportAnomalyDetectionDateFieldChange(params: AnomalyDetectionDateFieldChangeParams): void; + reportAnomalyDetectionPartitionFieldChange( + params: AnomalyDetectionPartitionFieldChangeParams + ): void; + reportAnomalyDetectionFilterFieldChange(params: AnomalyDetectionFilterFieldChangeParams): void; } export type InfraTelemetryEvent = @@ -152,4 +186,20 @@ export type InfraTelemetryEvent = | { eventType: InfraTelemetryEventTypes.ADD_METRICS_CALLOUT_DISMISSED; schema: RootSchema; + } + | { + eventType: InfraTelemetryEventTypes.ANOMALY_DETECTION_SETUP; + schema: RootSchema; + } + | { + eventType: InfraTelemetryEventTypes.ANOMALY_DETECTION_DATE_FIELD_CHANGE; + schema: RootSchema; + } + | { + eventType: InfraTelemetryEventTypes.ANOMALY_DETECTION_PARTITION_FIELD_CHANGE; + schema: RootSchema; + } + | { + eventType: InfraTelemetryEventTypes.ANOMALY_DETECTION_FILTER_FIELD_CHANGE; + schema: RootSchema; };