From 0871ba89b2a804d02355feb5eae7f1ece2879dbe Mon Sep 17 00:00:00 2001 From: iblancof Date: Thu, 17 Oct 2024 11:49:34 +0200 Subject: [PATCH 01/36] Create new Inventory telemetry events --- .../services/telemetry/telemetry_client.ts | 20 +++++- .../services/telemetry/telemetry_events.ts | 64 ++++++++++++++++++- .../public/services/telemetry/types.ts | 24 ++++++- 3 files changed, 105 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts index 1e36e8d6649ae..aa2c505a775fc 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts @@ -6,7 +6,14 @@ */ import { AnalyticsServiceSetup } from '@kbn/core-analytics-browser'; -import { type ITelemetryClient, TelemetryEventTypes, type InventoryAddDataParams } from './types'; +import { + type ITelemetryClient, + TelemetryEventTypes, + type InventoryAddDataParams, + type EntityInventoryViewedParams, + type SearchQuerySubmittedParams, + type EntityViewClickedParams, +} from './types'; export class TelemetryClient implements ITelemetryClient { constructor(private analytics: AnalyticsServiceSetup) {} @@ -14,4 +21,15 @@ export class TelemetryClient implements ITelemetryClient { public reportInventoryAddData = (params: InventoryAddDataParams) => { this.analytics.reportEvent(TelemetryEventTypes.INVENTORY_ADD_DATA_CLICKED, params); }; + + public reportEntityInventoryViewed = (params: EntityInventoryViewedParams) => { + this.analytics.reportEvent(TelemetryEventTypes.ENTITY_INVENTORY_VIEWED, params); + }; + + public reportSearchQuerySbmitted = (params: SearchQuerySubmittedParams) => { + this.analytics.reportEvent(TelemetryEventTypes.SEARCH_QUERY_SUBMITTED, params); + }; + public reportEntityViewClicked = (params: EntityViewClickedParams) => { + this.analytics.reportEvent(TelemetryEventTypes.ENTITY_VIEW_CLICKED, params); + }; } diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts index c1509499e694b..32028cd05511c 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts @@ -25,4 +25,66 @@ const inventoryAddDataEventType: TelemetryEvent = { }, }; -export const inventoryTelemetryEventBasedTypes = [inventoryAddDataEventType]; +const entityInventoryViewedEventType: TelemetryEvent = { + eventType: TelemetryEventTypes.ENTITY_INVENTORY_VIEWED, + schema: { + view_state: { + type: 'keyword', + _meta: { + description: 'State of the view: empty, populated or eem_disabled.', + }, + }, + }, +}; + +const searchQuerySubmittedEventType: TelemetryEvent = { + eventType: TelemetryEventTypes.SEARCH_QUERY_SUBMITTED, + schema: { + kuery_fields: { + type: 'array', + items: { + type: 'text', + _meta: { + description: 'Kuery fields used in the search.', + }, + }, + }, + timerange: { + type: 'text', + _meta: { + description: 'Timerange of the search.', + }, + }, + action: { + type: 'keyword', + _meta: { + description: 'Action performed: submit or refresh.', + }, + }, + }, +}; + +const entityViewClickedEventType: TelemetryEvent = { + eventType: TelemetryEventTypes.ENTITY_VIEW_CLICKED, + schema: { + entity_type: { + type: 'keyword', + _meta: { + description: 'Type of the entity: container, host or service.', + }, + }, + view_type: { + type: 'keyword', + _meta: { + description: 'Type of the view: detail or flyout.', + }, + }, + }, +}; + +export const inventoryTelemetryEventBasedTypes = [ + inventoryAddDataEventType, + entityInventoryViewedEventType, + searchQuerySubmittedEventType, + entityViewClickedEventType, +]; diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts index e5fdf162b750c..44f5647305aaf 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts @@ -16,7 +16,26 @@ export interface InventoryAddDataParams { journey?: 'add_data' | 'associate_existing_service_logs'; } -export type TelemetryEventParams = InventoryAddDataParams; +export interface EntityInventoryViewedParams { + view_state: 'empty' | 'populated' | 'eem_disabled'; +} + +export interface SearchQuerySubmittedParams { + kuery_fields: string[]; + timerange: string; + action: 'submit' | 'refresh'; +} + +export interface EntityViewClickedParams { + entity_type: 'container' | 'host' | 'service'; + view_type: 'detail' | 'flyout'; +} + +export type TelemetryEventParams = + | InventoryAddDataParams + | EntityInventoryViewedParams + | SearchQuerySubmittedParams + | EntityViewClickedParams; export interface ITelemetryClient { reportInventoryAddData(params: InventoryAddDataParams): void; @@ -24,6 +43,9 @@ export interface ITelemetryClient { export enum TelemetryEventTypes { INVENTORY_ADD_DATA_CLICKED = 'inventory_add_data_clicked', + ENTITY_INVENTORY_VIEWED = 'Entity Inventory Viewed', + SEARCH_QUERY_SUBMITTED = 'Search Query Submitted', + ENTITY_VIEW_CLICKED = 'Entity View Clicked', } export interface TelemetryEvent { From b5f8f05e4688458df3479ae8e660cacceed77326 Mon Sep 17 00:00:00 2001 From: iblancof Date: Thu, 17 Oct 2024 12:00:50 +0200 Subject: [PATCH 02/36] Add new events to ITelemetryClient --- .../inventory/public/services/telemetry/types.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts index 44f5647305aaf..b682cc67fc2e0 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts @@ -39,6 +39,9 @@ export type TelemetryEventParams = export interface ITelemetryClient { reportInventoryAddData(params: InventoryAddDataParams): void; + reportEntityInventoryViewed(params: EntityInventoryViewedParams): void; + reportSearchQuerySbmitted(params: SearchQuerySubmittedParams): void; + reportEntityViewClicked(params: EntityViewClickedParams): void; } export enum TelemetryEventTypes { From c3c957c492d6dc45cff8c26aa2c04b60023b6f0a Mon Sep 17 00:00:00 2001 From: iblancof Date: Thu, 17 Oct 2024 12:05:55 +0200 Subject: [PATCH 03/36] Add tests for new events --- .../telemetry/telemetry_service.test.ts | 77 ++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts index ffa05ffbff9a2..1c94be2e024a0 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts @@ -8,7 +8,12 @@ import { coreMock } from '@kbn/core/server/mocks'; import { inventoryTelemetryEventBasedTypes } from './telemetry_events'; import { TelemetryService } from './telemetry_service'; -import { TelemetryEventTypes } from './types'; +import { + type EntityInventoryViewedParams, + type EntityViewClickedParams, + type SearchQuerySubmittedParams, + TelemetryEventTypes, +} from './types'; describe('TelemetryService', () => { let service: TelemetryService; @@ -48,7 +53,15 @@ describe('TelemetryService', () => { service.setup(setupParams); const telemetry = service.start(); - expect(telemetry).toHaveProperty('reportInventoryAddData'); + const expectedProperties = [ + 'reportInventoryAddData', + 'reportEntityInventoryViewed', + 'reportSearchQuerySbmitted', + 'reportEntityViewClicked', + ]; + expectedProperties.forEach((property) => { + expect(telemetry).toHaveProperty(property); + }); }); }); @@ -73,4 +86,64 @@ describe('TelemetryService', () => { ); }); }); + + describe('#reportEntityInventoryViewed', () => { + it('should report entity inventory viewed with properties', async () => { + const setupParams = getSetupParams(); + service.setup(setupParams); + const telemetry = service.start(); + const params: EntityInventoryViewedParams = { + view_state: 'empty', + }; + + telemetry.reportEntityInventoryViewed(params); + + expect(setupParams.analytics.reportEvent).toHaveBeenCalledTimes(1); + expect(setupParams.analytics.reportEvent).toHaveBeenCalledWith( + TelemetryEventTypes.ENTITY_INVENTORY_VIEWED, + params + ); + }); + }); + + describe('#reportSearchQuerySbmitted', () => { + it('should report search query submitted with properties', async () => { + const setupParams = getSetupParams(); + service.setup(setupParams); + const telemetry = service.start(); + const params: SearchQuerySubmittedParams = { + kuery_fields: ['_index'], + timerange: 'now-1y/d - now', + action: 'submit', + }; + + telemetry.reportSearchQuerySbmitted(params); + + expect(setupParams.analytics.reportEvent).toHaveBeenCalledTimes(1); + expect(setupParams.analytics.reportEvent).toHaveBeenCalledWith( + TelemetryEventTypes.SEARCH_QUERY_SUBMITTED, + params + ); + }); + }); + + describe('#reportEntityViewClicked', () => { + it('should report entity view clicked with properties', async () => { + const setupParams = getSetupParams(); + service.setup(setupParams); + const telemetry = service.start(); + const params: EntityViewClickedParams = { + entity_type: 'container', + view_type: 'detail', + }; + + telemetry.reportEntityViewClicked(params); + + expect(setupParams.analytics.reportEvent).toHaveBeenCalledTimes(1); + expect(setupParams.analytics.reportEvent).toHaveBeenCalledWith( + TelemetryEventTypes.ENTITY_VIEW_CLICKED, + params + ); + }); + }); }); From d05d1a31e6bc7b9df206e8e6f892e02ff2f5fe37 Mon Sep 17 00:00:00 2001 From: iblancof Date: Thu, 17 Oct 2024 15:41:19 +0200 Subject: [PATCH 04/36] Rename Search Query Submitted to Entity Inventory Search Query Submitted --- .../public/services/telemetry/telemetry_client.ts | 8 +++++--- .../services/telemetry/telemetry_service.test.ts | 12 ++++++------ .../inventory/public/services/telemetry/types.ts | 10 ++++++---- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts index aa2c505a775fc..6f4ca48f2bc9d 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts @@ -11,7 +11,7 @@ import { TelemetryEventTypes, type InventoryAddDataParams, type EntityInventoryViewedParams, - type SearchQuerySubmittedParams, + type EntityInventorySearchQuerySubmittedParams, type EntityViewClickedParams, } from './types'; @@ -26,8 +26,10 @@ export class TelemetryClient implements ITelemetryClient { this.analytics.reportEvent(TelemetryEventTypes.ENTITY_INVENTORY_VIEWED, params); }; - public reportSearchQuerySbmitted = (params: SearchQuerySubmittedParams) => { - this.analytics.reportEvent(TelemetryEventTypes.SEARCH_QUERY_SUBMITTED, params); + public reportEntityInventorySearchQuerySubmitted = ( + params: EntityInventorySearchQuerySubmittedParams + ) => { + this.analytics.reportEvent(TelemetryEventTypes.ENTITY_INVENTORY_SEARCH_QUERY_SUBMITTED, params); }; public reportEntityViewClicked = (params: EntityViewClickedParams) => { this.analytics.reportEvent(TelemetryEventTypes.ENTITY_VIEW_CLICKED, params); diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts index 1c94be2e024a0..e85ca1dd4a0c2 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts @@ -11,7 +11,7 @@ import { TelemetryService } from './telemetry_service'; import { type EntityInventoryViewedParams, type EntityViewClickedParams, - type SearchQuerySubmittedParams, + type EntityInventorySearchQuerySubmittedParams, TelemetryEventTypes, } from './types'; @@ -56,7 +56,7 @@ describe('TelemetryService', () => { const expectedProperties = [ 'reportInventoryAddData', 'reportEntityInventoryViewed', - 'reportSearchQuerySbmitted', + 'reportEntityInventorySearchQuerySubmitted', 'reportEntityViewClicked', ]; expectedProperties.forEach((property) => { @@ -106,22 +106,22 @@ describe('TelemetryService', () => { }); }); - describe('#reportSearchQuerySbmitted', () => { + describe('#reportEntityInventorySearchQuerySubmitted', () => { it('should report search query submitted with properties', async () => { const setupParams = getSetupParams(); service.setup(setupParams); const telemetry = service.start(); - const params: SearchQuerySubmittedParams = { + const params: EntityInventorySearchQuerySubmittedParams = { kuery_fields: ['_index'], timerange: 'now-1y/d - now', action: 'submit', }; - telemetry.reportSearchQuerySbmitted(params); + telemetry.reportEntityInventorySearchQuerySubmitted(params); expect(setupParams.analytics.reportEvent).toHaveBeenCalledTimes(1); expect(setupParams.analytics.reportEvent).toHaveBeenCalledWith( - TelemetryEventTypes.SEARCH_QUERY_SUBMITTED, + TelemetryEventTypes.ENTITY_INVENTORY_SEARCH_QUERY_SUBMITTED, params ); }); diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts index b682cc67fc2e0..0ddca285c1686 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts @@ -20,7 +20,7 @@ export interface EntityInventoryViewedParams { view_state: 'empty' | 'populated' | 'eem_disabled'; } -export interface SearchQuerySubmittedParams { +export interface EntityInventorySearchQuerySubmittedParams { kuery_fields: string[]; timerange: string; action: 'submit' | 'refresh'; @@ -34,20 +34,22 @@ export interface EntityViewClickedParams { export type TelemetryEventParams = | InventoryAddDataParams | EntityInventoryViewedParams - | SearchQuerySubmittedParams + | EntityInventorySearchQuerySubmittedParams | EntityViewClickedParams; export interface ITelemetryClient { reportInventoryAddData(params: InventoryAddDataParams): void; reportEntityInventoryViewed(params: EntityInventoryViewedParams): void; - reportSearchQuerySbmitted(params: SearchQuerySubmittedParams): void; + reportEntityInventorySearchQuerySubmitted( + params: EntityInventorySearchQuerySubmittedParams + ): void; reportEntityViewClicked(params: EntityViewClickedParams): void; } export enum TelemetryEventTypes { INVENTORY_ADD_DATA_CLICKED = 'inventory_add_data_clicked', ENTITY_INVENTORY_VIEWED = 'Entity Inventory Viewed', - SEARCH_QUERY_SUBMITTED = 'Search Query Submitted', + ENTITY_INVENTORY_SEARCH_QUERY_SUBMITTED = 'Entity Inventory Search Query Submitted', ENTITY_VIEW_CLICKED = 'Entity View Clicked', } From 4fee26dd7fa64c976abe6b141980ca1857318a38 Mon Sep 17 00:00:00 2001 From: iblancof Date: Fri, 18 Oct 2024 10:37:49 +0200 Subject: [PATCH 05/36] Add event on entity click --- .../public/components/entities_grid/index.tsx | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx index 697bc3304753e..7bdc9e6f75267 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx @@ -20,13 +20,14 @@ import { ENTITY_LAST_SEEN, ENTITY_TYPE, } from '@kbn/observability-shared-plugin/common'; -import { EntityColumnIds, EntityType } from '../../../common/entities'; +import { Entity, EntityColumnIds, EntityType } from '../../../common/entities'; import { APIReturnType } from '../../api'; import { BadgeFilterWithPopover } from '../badge_filter_with_popover'; import { getColumns } from './grid_columns'; import { AlertsBadge } from '../alerts_badge/alerts_badge'; -import { EntityName } from './entity_name'; import { getEntityTypeLabel } from '../../utils/get_entity_type_label'; +import { useKibana } from '../../hooks/use_kibana'; +import { EntityName } from './entity_name'; type InventoryEntitiesAPIReturnType = APIReturnType<'GET /internal/inventory/entities'>; type LatestEntities = InventoryEntitiesAPIReturnType['entities']; @@ -54,6 +55,10 @@ export function EntitiesGrid({ onChangeSort, onFilterByType, }: Props) { + const { + services: { telemetry }, + } = useKibana(); + const onSort: EuiDataGridSorting['onSort'] = useCallback( (newSortingColumns) => { const lastItem = last(newSortingColumns); @@ -64,6 +69,16 @@ export function EntitiesGrid({ [onChangeSort] ); + const onEntityNameClick = useCallback( + ({ entityType }: { entityType: EntityType }) => { + telemetry.reportEntityViewClicked({ + view_type: 'detail', + entity_type: entityType, + }); + }, + [telemetry] + ); + const showAlertsColumn = useMemo( () => entities?.some((entity) => entity?.alertsCount && entity?.alertsCount > 0), [entities] @@ -79,18 +94,19 @@ export function EntitiesGrid({ const renderCellValue = useCallback( ({ rowIndex, columnId }: EuiDataGridCellValueElementProps) => { - const entity = entities[rowIndex]; + const entity: Entity = entities[rowIndex]; if (entity === undefined) { return null; } const columnEntityTableId = columnId as EntityColumnIds; + const entityType = entity['entity.type']; + switch (columnEntityTableId) { case 'alertsCount': return entity?.alertsCount ? : null; case ENTITY_TYPE: - const entityType = entity[columnEntityTableId]; return ( ); case ENTITY_DISPLAY_NAME: - return ; + return ( + { + onEntityNameClick({ entityType }); + }} + /> + ); default: return entity[columnId as EntityColumnIds] || ''; } }, - [entities, onFilterByType] + [entities, onEntityNameClick, onFilterByType] ); if (loading) { From 21bb570347a8ee2460fdd9d05fb435870920f1e3 Mon Sep 17 00:00:00 2001 From: iblancof Date: Fri, 18 Oct 2024 16:10:51 +0200 Subject: [PATCH 06/36] Add event on inventory viewed --- .../inventory_page_template/index.tsx | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx index 08ff287b58cfd..e962c1c744893 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ import { i18n } from '@kbn/i18n'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiEmptyPrompt, EuiLoadingLogo } from '@elastic/eui'; import { FeatureFeedbackButton, @@ -36,7 +36,7 @@ const INVENTORY_FEEDBACK_LINK = 'https://ela.st/feedback-new-inventory'; export function InventoryPageTemplate({ children }: { children: React.ReactNode }) { const { - services: { observabilityShared, inventoryAPIClient, kibanaEnvironment }, + services: { observabilityShared, inventoryAPIClient, kibanaEnvironment, telemetry }, } = useKibana(); const { PageTemplate: ObservabilityPageTemplate } = observabilityShared.navigation; @@ -62,6 +62,35 @@ export function InventoryPageTemplate({ children }: { children: React.ReactNode [inventoryAPIClient] ); + const [isLoadingComplete, setIsLoadingComplete] = useState(undefined); + + useEffect(() => { + if (isLoadingComplete === undefined && hasDataLoading && isEnablementLoading) { + setIsLoadingComplete(false); + } else if (isLoadingComplete === false && !hasDataLoading && !isEnablementLoading) { + setIsLoadingComplete(true); + } + + if (isLoadingComplete) { + const viewState = isEntityManagerEnabled + ? value.hasData + ? 'populated' + : 'empty' + : 'eem_disabled'; + + telemetry.reportEntityInventoryViewed({ + view_state: viewState, + }); + } + }, [ + isEnablementLoading, + hasDataLoading, + isEntityManagerEnabled, + value.hasData, + telemetry, + isLoadingComplete, + ]); + if (isEnablementLoading || hasDataLoading) { return ( Date: Mon, 21 Oct 2024 11:19:20 +0200 Subject: [PATCH 07/36] Fix eventType --- .../inventory/public/services/telemetry/telemetry_events.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts index 32028cd05511c..3e00ee31d3fcb 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts @@ -38,7 +38,7 @@ const entityInventoryViewedEventType: TelemetryEvent = { }; const searchQuerySubmittedEventType: TelemetryEvent = { - eventType: TelemetryEventTypes.SEARCH_QUERY_SUBMITTED, + eventType: TelemetryEventTypes.ENTITY_INVENTORY_SEARCH_QUERY_SUBMITTED, schema: { kuery_fields: { type: 'array', From ade80e29b622d7146967c8ede27a6a5f2dcf75ae Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 11:27:57 +0200 Subject: [PATCH 08/36] Add event on search query submitted --- .../public/components/search_bar/index.tsx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx index 46ef45cfc195d..e2d7277dcb931 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx @@ -9,6 +9,7 @@ import { SearchBarOwnProps } from '@kbn/unified-search-plugin/public/search_bar' import deepEqual from 'fast-deep-equal'; import React, { useCallback, useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { getKqlFieldNamesFromExpression, Query } from '@kbn/es-query'; import { EntityType } from '../../../common/entities'; import { useInventorySearchBarContext } from '../../context/inventory_search_bar_context_provider'; import { useAdHocInventoryDataView } from '../../hooks/use_adhoc_inventory_data_view'; @@ -25,6 +26,7 @@ export function SearchBar() { data: { query: { queryString: queryStringService }, }, + telemetry, }, } = useKibana(); @@ -51,6 +53,17 @@ export function SearchBar() { syncSearchBarWithUrl(); }, [syncSearchBarWithUrl]); + const registerSearchSubmittedEvent = useCallback( + ({ query, isUpdate }: { query: Query | undefined; isUpdate: boolean | undefined }) => { + telemetry.reportEntityInventorySearchQuerySubmitted({ + kuery_fields: getKqlFieldNamesFromExpression(query?.query as string), + timerange: '', + action: isUpdate ? 'submit' : 'refresh', + }); + }, + [telemetry] + ); + const handleEntityTypesChange = useCallback( (nextEntityTypes: EntityType[]) => { searchBarContentSubject$.next({ kuery, entityTypes: nextEntityTypes, refresh: false }); @@ -65,8 +78,10 @@ export function SearchBar() { entityTypes, refresh: !isUpdate, }); + + registerSearchSubmittedEvent({ query, isUpdate }); }, - [entityTypes, searchBarContentSubject$] + [entityTypes, registerSearchSubmittedEvent, searchBarContentSubject$] ); return ( From 2231a418bfdf2b580f74cefb9aab407d2ef93c27 Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 11:28:49 +0200 Subject: [PATCH 09/36] Remove timerange from search query submitted --- .../inventory/public/components/search_bar/index.tsx | 1 - .../inventory/public/services/telemetry/telemetry_events.ts | 6 ------ .../inventory/public/services/telemetry/types.ts | 1 - 3 files changed, 8 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx index e2d7277dcb931..962bf6fe5b1a2 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx @@ -57,7 +57,6 @@ export function SearchBar() { ({ query, isUpdate }: { query: Query | undefined; isUpdate: boolean | undefined }) => { telemetry.reportEntityInventorySearchQuerySubmitted({ kuery_fields: getKqlFieldNamesFromExpression(query?.query as string), - timerange: '', action: isUpdate ? 'submit' : 'refresh', }); }, diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts index 3e00ee31d3fcb..ec2623fe2a2cc 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts @@ -49,12 +49,6 @@ const searchQuerySubmittedEventType: TelemetryEvent = { }, }, }, - timerange: { - type: 'text', - _meta: { - description: 'Timerange of the search.', - }, - }, action: { type: 'keyword', _meta: { diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts index 0ddca285c1686..725b897d04697 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts @@ -22,7 +22,6 @@ export interface EntityInventoryViewedParams { export interface EntityInventorySearchQuerySubmittedParams { kuery_fields: string[]; - timerange: string; action: 'submit' | 'refresh'; } From 1f7369d2e2bbb4ba18a8dc56b516121aef412bfd Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 12:08:05 +0200 Subject: [PATCH 10/36] Create registerEemEnabledContext --- .../analytics/register_eem_enabled_context.ts | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts diff --git a/x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts b/x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts new file mode 100644 index 0000000000000..f70f7cea5ad13 --- /dev/null +++ b/x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts @@ -0,0 +1,34 @@ +/* + * 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 { AnalyticsServiceSetup } from '@kbn/core/public'; +import { BehaviorSubject } from 'rxjs'; +import { EntityManagerPublicPluginSetup } from '@kbn/entityManager-plugin/public'; + +export let eemEnabled$: BehaviorSubject<{ eemEnabled: boolean }>; + +export function registerEemEnabledContext( + analytics: AnalyticsServiceSetup, + entityManager: EntityManagerPublicPluginSetup +) { + entityManager.entityClient.isManagedEntityDiscoveryEnabled().then(({ enabled }) => { + eemEnabled$ = new BehaviorSubject({ + eemEnabled: enabled, + }); + + analytics.registerContextProvider({ + name: 'eemEnabled', + context$: eemEnabled$, + schema: { + eemEnabled: { + type: 'boolean', + _meta: { description: 'Whether EEM is enabled or not.' }, + }, + }, + }); + }); +} From 0873ae38d3a67133bffb5bb2529bda26a1817610 Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 12:08:34 +0200 Subject: [PATCH 11/36] Update eemEnabled on enablement --- .../public/components/inventory_page_template/index.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx index e962c1c744893..16006b42237a5 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx @@ -18,6 +18,7 @@ import { useEntityManager } from '../../hooks/use_entity_manager'; import { Welcome } from '../entity_enablement/welcome_modal'; import { useInventoryAbortableAsync } from '../../hooks/use_inventory_abortable_async'; import { EmptyState } from '../empty_states/empty_state'; +import { eemEnabled$ } from '../../analytics/register_eem_enabled_context'; const pageTitle = ( @@ -49,6 +50,7 @@ export function InventoryPageTemplate({ children }: { children: React.ReactNode } = useEntityManager(); const handleSuccess = () => { + eemEnabled$.next({ eemEnabled: true }); refresh(); toggleWelcomedModal(); }; From 7ae4e9b60caa0655b40357d533ae0da26dda12e0 Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 12:08:56 +0200 Subject: [PATCH 12/36] Register eemEnabled o plugin setup --- .../plugins/observability_solution/inventory/public/plugin.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugins/observability_solution/inventory/public/plugin.ts b/x-pack/plugins/observability_solution/inventory/public/plugin.ts index b6771d2f95550..bc32bfafa90d9 100644 --- a/x-pack/plugins/observability_solution/inventory/public/plugin.ts +++ b/x-pack/plugins/observability_solution/inventory/public/plugin.ts @@ -28,6 +28,7 @@ import type { InventorySetupDependencies, InventoryStartDependencies, } from './types'; +import { registerEemEnabledContext } from './analytics/register_eem_enabled_context'; export class InventoryPlugin implements @@ -79,6 +80,7 @@ export class InventoryPlugin const sections$ = hideInventory$.pipe( map((hideInventory) => { if (isEntityCentricExperienceSettingEnabled && !hideInventory) { + registerEemEnabledContext(coreSetup.analytics, pluginsSetup.entityManager); return [ { label: '', From ab08ebe315bd3047d4ac1f43275e70c665a3294f Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 12:15:49 +0200 Subject: [PATCH 13/36] Rename eemEnabled to eem_enabled for telemetry --- .../public/analytics/register_eem_enabled_context.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts b/x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts index f70f7cea5ad13..516b26923dbf5 100644 --- a/x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts +++ b/x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts @@ -9,7 +9,7 @@ import { AnalyticsServiceSetup } from '@kbn/core/public'; import { BehaviorSubject } from 'rxjs'; import { EntityManagerPublicPluginSetup } from '@kbn/entityManager-plugin/public'; -export let eemEnabled$: BehaviorSubject<{ eemEnabled: boolean }>; +export let eemEnabled$: BehaviorSubject<{ ['eem_enabled']: boolean }>; export function registerEemEnabledContext( analytics: AnalyticsServiceSetup, @@ -17,14 +17,14 @@ export function registerEemEnabledContext( ) { entityManager.entityClient.isManagedEntityDiscoveryEnabled().then(({ enabled }) => { eemEnabled$ = new BehaviorSubject({ - eemEnabled: enabled, + ['eem_enabled']: enabled, }); analytics.registerContextProvider({ - name: 'eemEnabled', + name: 'eem_enabled', context$: eemEnabled$, schema: { - eemEnabled: { + ['eem_enabled']: { type: 'boolean', _meta: { description: 'Whether EEM is enabled or not.' }, }, From f56717bf8c102760754a4eead1f9c3b04a80ff6c Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 12:40:08 +0200 Subject: [PATCH 14/36] Add event on entity type filtered --- .../public/components/search_bar/index.tsx | 19 +++++++++++++- .../services/telemetry/telemetry_client.ts | 8 ++++++ .../services/telemetry/telemetry_events.ts | 25 +++++++++++++++++++ .../public/services/telemetry/types.ts | 8 ++++++ 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx index 962bf6fe5b1a2..c5fae019ad340 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx @@ -63,11 +63,28 @@ export function SearchBar() { [telemetry] ); + const registerEntityTypeFilteredEvent = useCallback( + ({ + entityTypesFilter, + kueryFilter, + }: { + entityTypesFilter: EntityType[]; + kueryFilter: string | undefined; + }) => { + telemetry.reportEntityInventoryEntityTypeFiltered({ + entity_types: entityTypesFilter, + kuery_fields: kueryFilter ? getKqlFieldNamesFromExpression(kueryFilter) : [], + }); + }, + [telemetry] + ); + const handleEntityTypesChange = useCallback( (nextEntityTypes: EntityType[]) => { searchBarContentSubject$.next({ kuery, entityTypes: nextEntityTypes, refresh: false }); + registerEntityTypeFilteredEvent({ entityTypesFilter: nextEntityTypes, kueryFilter: kuery }); }, - [kuery, searchBarContentSubject$] + [kuery, registerEntityTypeFilteredEvent, searchBarContentSubject$] ); const handleQuerySubmit = useCallback>( diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts index 6f4ca48f2bc9d..d58070d9f6aae 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts @@ -13,6 +13,7 @@ import { type EntityInventoryViewedParams, type EntityInventorySearchQuerySubmittedParams, type EntityViewClickedParams, + EntityInventoryEntityTypeFilteredParams, } from './types'; export class TelemetryClient implements ITelemetryClient { @@ -31,6 +32,13 @@ export class TelemetryClient implements ITelemetryClient { ) => { this.analytics.reportEvent(TelemetryEventTypes.ENTITY_INVENTORY_SEARCH_QUERY_SUBMITTED, params); }; + + public reportEntityInventoryEntityTypeFiltered = ( + params: EntityInventoryEntityTypeFilteredParams + ) => { + this.analytics.reportEvent(TelemetryEventTypes.ENTITY_INVENTORY_ENTITY_TYPE_FILTERED, params); + }; + public reportEntityViewClicked = (params: EntityViewClickedParams) => { this.analytics.reportEvent(TelemetryEventTypes.ENTITY_VIEW_CLICKED, params); }; diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts index ec2623fe2a2cc..16ca6e7dedd4b 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts @@ -58,6 +58,30 @@ const searchQuerySubmittedEventType: TelemetryEvent = { }, }; +const entityInventoryEntityTypeFilteredEventType: TelemetryEvent = { + eventType: TelemetryEventTypes.ENTITY_INVENTORY_ENTITY_TYPE_FILTERED, + schema: { + entity_types: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: 'Entity types used in the filter.', + }, + }, + }, + kuery_fields: { + type: 'array', + items: { + type: 'text', + _meta: { + description: 'Kuery fields used in the filter.', + }, + }, + }, + }, +}; + const entityViewClickedEventType: TelemetryEvent = { eventType: TelemetryEventTypes.ENTITY_VIEW_CLICKED, schema: { @@ -80,5 +104,6 @@ export const inventoryTelemetryEventBasedTypes = [ inventoryAddDataEventType, entityInventoryViewedEventType, searchQuerySubmittedEventType, + entityInventoryEntityTypeFilteredEventType, entityViewClickedEventType, ]; diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts index 725b897d04697..7bb3e300e51d7 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts @@ -25,6 +25,11 @@ export interface EntityInventorySearchQuerySubmittedParams { action: 'submit' | 'refresh'; } +export interface EntityInventoryEntityTypeFilteredParams { + kuery_fields: string[]; + entity_types: Array<'container' | 'host' | 'service'>; +} + export interface EntityViewClickedParams { entity_type: 'container' | 'host' | 'service'; view_type: 'detail' | 'flyout'; @@ -34,6 +39,7 @@ export type TelemetryEventParams = | InventoryAddDataParams | EntityInventoryViewedParams | EntityInventorySearchQuerySubmittedParams + | EntityInventoryEntityTypeFilteredParams | EntityViewClickedParams; export interface ITelemetryClient { @@ -42,6 +48,7 @@ export interface ITelemetryClient { reportEntityInventorySearchQuerySubmitted( params: EntityInventorySearchQuerySubmittedParams ): void; + reportEntityInventoryEntityTypeFiltered(params: EntityInventoryEntityTypeFilteredParams): void; reportEntityViewClicked(params: EntityViewClickedParams): void; } @@ -49,6 +56,7 @@ export enum TelemetryEventTypes { INVENTORY_ADD_DATA_CLICKED = 'inventory_add_data_clicked', ENTITY_INVENTORY_VIEWED = 'Entity Inventory Viewed', ENTITY_INVENTORY_SEARCH_QUERY_SUBMITTED = 'Entity Inventory Search Query Submitted', + ENTITY_INVENTORY_ENTITY_TYPE_FILTERED = 'Entity Inventory Entity Type Filtered', ENTITY_VIEW_CLICKED = 'Entity View Clicked', } From 0533fb317d21d368c0f40fbb86b2b32ce7a1a07f Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 12:45:41 +0200 Subject: [PATCH 15/36] Add entity_types param in search submitted event --- .../public/components/search_bar/index.tsx | 21 +++++++++++++++---- .../services/telemetry/telemetry_events.ts | 9 ++++++++ .../public/services/telemetry/types.ts | 1 + 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx index c5fae019ad340..d5502467adb0f 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx @@ -54,10 +54,19 @@ export function SearchBar() { }, [syncSearchBarWithUrl]); const registerSearchSubmittedEvent = useCallback( - ({ query, isUpdate }: { query: Query | undefined; isUpdate: boolean | undefined }) => { + ({ + searchQuery, + searchIsUpdate, + searchEntityTypes, + }: { + searchQuery: Query | undefined; + searchEntityTypes: EntityType[] | undefined; + searchIsUpdate: boolean | undefined; + }) => { telemetry.reportEntityInventorySearchQuerySubmitted({ - kuery_fields: getKqlFieldNamesFromExpression(query?.query as string), - action: isUpdate ? 'submit' : 'refresh', + kuery_fields: getKqlFieldNamesFromExpression(searchQuery?.query as string), + entity_types: searchEntityTypes || [], + action: searchIsUpdate ? 'submit' : 'refresh', }); }, [telemetry] @@ -95,7 +104,11 @@ export function SearchBar() { refresh: !isUpdate, }); - registerSearchSubmittedEvent({ query, isUpdate }); + registerSearchSubmittedEvent({ + searchQuery: query, + searchEntityTypes: entityTypes, + searchIsUpdate: isUpdate, + }); }, [entityTypes, registerSearchSubmittedEvent, searchBarContentSubject$] ); diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts index 16ca6e7dedd4b..d61a90f7d30ab 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_events.ts @@ -49,6 +49,15 @@ const searchQuerySubmittedEventType: TelemetryEvent = { }, }, }, + entity_types: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: 'Entity types used in the search.', + }, + }, + }, action: { type: 'keyword', _meta: { diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts index 7bb3e300e51d7..d83da1ea5d663 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts @@ -22,6 +22,7 @@ export interface EntityInventoryViewedParams { export interface EntityInventorySearchQuerySubmittedParams { kuery_fields: string[]; + entity_types: Array<'container' | 'host' | 'service'>; action: 'submit' | 'refresh'; } From 2806374038029cefff5200d2aa17875642eafd19 Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 12:46:31 +0200 Subject: [PATCH 16/36] Rename filter event fn params --- .../public/components/search_bar/index.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx index d5502467adb0f..2fe2008ec773a 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx @@ -74,15 +74,15 @@ export function SearchBar() { const registerEntityTypeFilteredEvent = useCallback( ({ - entityTypesFilter, - kueryFilter, + filterEntityTypes, + filterKuery, }: { - entityTypesFilter: EntityType[]; - kueryFilter: string | undefined; + filterEntityTypes: EntityType[]; + filterKuery: string | undefined; }) => { telemetry.reportEntityInventoryEntityTypeFiltered({ - entity_types: entityTypesFilter, - kuery_fields: kueryFilter ? getKqlFieldNamesFromExpression(kueryFilter) : [], + entity_types: filterEntityTypes, + kuery_fields: filterKuery ? getKqlFieldNamesFromExpression(filterKuery) : [], }); }, [telemetry] @@ -91,7 +91,7 @@ export function SearchBar() { const handleEntityTypesChange = useCallback( (nextEntityTypes: EntityType[]) => { searchBarContentSubject$.next({ kuery, entityTypes: nextEntityTypes, refresh: false }); - registerEntityTypeFilteredEvent({ entityTypesFilter: nextEntityTypes, kueryFilter: kuery }); + registerEntityTypeFilteredEvent({ filterEntityTypes: nextEntityTypes, filterKuery: kuery }); }, [kuery, registerEntityTypeFilteredEvent, searchBarContentSubject$] ); From 12acf93c47311cfe600a6206fb231204a07112f4 Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 14:19:54 +0200 Subject: [PATCH 17/36] Rename eemEnabled to eem_enabled --- .../public/components/inventory_page_template/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx index 16006b42237a5..04f9c2358d0c3 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx @@ -50,7 +50,7 @@ export function InventoryPageTemplate({ children }: { children: React.ReactNode } = useEntityManager(); const handleSuccess = () => { - eemEnabled$.next({ eemEnabled: true }); + eemEnabled$.next({ eem_enabled: true }); refresh(); toggleWelcomedModal(); }; From 383e424c0a6f4675ecc9462e9b6f6877c25a99b4 Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 14:21:10 +0200 Subject: [PATCH 18/36] Refactor registerEemEnabledContext --- .../public/analytics/register_eem_enabled_context.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts b/x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts index 516b26923dbf5..062f7f61961e9 100644 --- a/x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts +++ b/x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts @@ -9,7 +9,7 @@ import { AnalyticsServiceSetup } from '@kbn/core/public'; import { BehaviorSubject } from 'rxjs'; import { EntityManagerPublicPluginSetup } from '@kbn/entityManager-plugin/public'; -export let eemEnabled$: BehaviorSubject<{ ['eem_enabled']: boolean }>; +export let eemEnabled$: BehaviorSubject<{ eem_enabled: boolean }>; export function registerEemEnabledContext( analytics: AnalyticsServiceSetup, @@ -17,14 +17,14 @@ export function registerEemEnabledContext( ) { entityManager.entityClient.isManagedEntityDiscoveryEnabled().then(({ enabled }) => { eemEnabled$ = new BehaviorSubject({ - ['eem_enabled']: enabled, + eem_enabled: enabled, }); analytics.registerContextProvider({ name: 'eem_enabled', context$: eemEnabled$, schema: { - ['eem_enabled']: { + eem_enabled: { type: 'boolean', _meta: { description: 'Whether EEM is enabled or not.' }, }, From bf1201329a042841873579a86614cc939bdfd4f6 Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 14:34:59 +0200 Subject: [PATCH 19/36] Create useIsLoadingComplete --- .../hooks/use_is_loading_complete.test.ts | 109 ++++++++++++++++++ .../public/hooks/use_is_loading_complete.ts | 29 +++++ 2 files changed, 138 insertions(+) create mode 100644 x-pack/plugins/observability_solution/inventory/public/hooks/use_is_loading_complete.test.ts create mode 100644 x-pack/plugins/observability_solution/inventory/public/hooks/use_is_loading_complete.ts diff --git a/x-pack/plugins/observability_solution/inventory/public/hooks/use_is_loading_complete.test.ts b/x-pack/plugins/observability_solution/inventory/public/hooks/use_is_loading_complete.test.ts new file mode 100644 index 0000000000000..61306a0b66a3b --- /dev/null +++ b/x-pack/plugins/observability_solution/inventory/public/hooks/use_is_loading_complete.test.ts @@ -0,0 +1,109 @@ +/* + * 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 { renderHook } from '@testing-library/react-hooks'; +import { useIsLoadingComplete } from './use_is_loading_complete'; + +describe('useIsLoadingComplete', () => { + describe('initialization', () => { + it('should initialize with undefined', () => { + const { result } = renderHook(() => useIsLoadingComplete({ loadingStates: [false, false] })); + expect(result.current).toBeUndefined(); + }); + + it('should handle an empty array of loadingStates', () => { + const { result } = renderHook(() => useIsLoadingComplete({ loadingStates: [] })); + expect(result.current).toBeUndefined(); + }); + + it('should handle a single loading state that is false', () => { + const { result } = renderHook(() => useIsLoadingComplete({ loadingStates: [false] })); + expect(result.current).toBeUndefined(); + }); + }); + + describe('loading states', () => { + it('should set isLoadingComplete to false when some loadingStates are true', () => { + const { result } = renderHook(() => useIsLoadingComplete({ loadingStates: [true, false] })); + expect(result.current).toBe(false); + }); + + it('should set isLoadingComplete to false when all loadingStates are true', () => { + const { result } = renderHook(() => useIsLoadingComplete({ loadingStates: [true, true] })); + expect(result.current).toBe(false); + }); + + it('should handle a single loading state that is true', () => { + const { result } = renderHook(() => useIsLoadingComplete({ loadingStates: [true] })); + expect(result.current).toBe(false); + }); + }); + + describe('loading completion', () => { + it('should set isLoadingComplete to true when all loadingStates are false after being true', () => { + const { result, rerender } = renderHook( + ({ loadingStates }) => useIsLoadingComplete({ loadingStates }), + { + initialProps: { loadingStates: [true, false] }, + } + ); + + expect(result.current).toBe(false); + + rerender({ loadingStates: [false, false] }); + + expect(result.current).toBe(true); + }); + + it('should set isLoadingComplete to true when all loadingStates are false after being mixed', () => { + const { result, rerender } = renderHook( + ({ loadingStates }) => useIsLoadingComplete({ loadingStates }), + { + initialProps: { loadingStates: [true, false] }, + } + ); + + expect(result.current).toBe(false); + + rerender({ loadingStates: [false, false] }); + + expect(result.current).toBe(true); + }); + }); + + describe('mixed states', () => { + it('should not change isLoadingComplete if loadingStates are mixed', () => { + const { result, rerender } = renderHook( + ({ loadingStates }) => useIsLoadingComplete({ loadingStates }), + { + initialProps: { loadingStates: [true, true] }, + } + ); + + expect(result.current).toBe(false); + + rerender({ loadingStates: [true, false] }); + + expect(result.current).toBe(false); + }); + + it('should not change isLoadingComplete if loadingStates change from all true to mixed', () => { + const { result, rerender } = renderHook( + ({ loadingStates }) => useIsLoadingComplete({ loadingStates }), + { + initialProps: { loadingStates: [true, true] }, + } + ); + + expect(result.current).toBe(false); + + rerender({ loadingStates: [true, false] }); + + expect(result.current).toBe(false); + }); + }); +}); diff --git a/x-pack/plugins/observability_solution/inventory/public/hooks/use_is_loading_complete.ts b/x-pack/plugins/observability_solution/inventory/public/hooks/use_is_loading_complete.ts new file mode 100644 index 0000000000000..76b863efaeceb --- /dev/null +++ b/x-pack/plugins/observability_solution/inventory/public/hooks/use_is_loading_complete.ts @@ -0,0 +1,29 @@ +/* + * 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 { useState, useEffect } from 'react'; + +interface UseIsLoadingCompleteProps { + loadingStates: boolean[]; +} + +export const useIsLoadingComplete = ({ loadingStates }: UseIsLoadingCompleteProps) => { + const [isLoadingComplete, setIsLoadingComplete] = useState(undefined); + + useEffect(() => { + const someLoading = loadingStates.some((loading) => loading); + const allLoaded = loadingStates.every((loading) => !loading); + + if (isLoadingComplete === undefined && someLoading) { + setIsLoadingComplete(false); + } else if (isLoadingComplete === false && allLoaded) { + setIsLoadingComplete(true); + } + }, [isLoadingComplete, loadingStates]); + + return isLoadingComplete; +}; From 91aa42aa046c2ee94dffef54928102b1fcc82656 Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 14:36:34 +0200 Subject: [PATCH 20/36] Use isLoadingComplete hook in Inventory --- .../inventory_page_template/index.tsx | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx index 04f9c2358d0c3..94fedb01302a7 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ import { i18n } from '@kbn/i18n'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiEmptyPrompt, EuiLoadingLogo } from '@elastic/eui'; import { FeatureFeedbackButton, @@ -19,6 +19,7 @@ import { Welcome } from '../entity_enablement/welcome_modal'; import { useInventoryAbortableAsync } from '../../hooks/use_inventory_abortable_async'; import { EmptyState } from '../empty_states/empty_state'; import { eemEnabled$ } from '../../analytics/register_eem_enabled_context'; +import { useIsLoadingComplete } from '../../hooks/use_is_loading_complete'; const pageTitle = ( @@ -64,34 +65,22 @@ export function InventoryPageTemplate({ children }: { children: React.ReactNode [inventoryAPIClient] ); - const [isLoadingComplete, setIsLoadingComplete] = useState(undefined); + const isLoadingComplete = useIsLoadingComplete({ + loadingStates: [isEnablementLoading, hasDataLoading], + }); useEffect(() => { - if (isLoadingComplete === undefined && hasDataLoading && isEnablementLoading) { - setIsLoadingComplete(false); - } else if (isLoadingComplete === false && !hasDataLoading && !isEnablementLoading) { - setIsLoadingComplete(true); - } - if (isLoadingComplete) { const viewState = isEntityManagerEnabled ? value.hasData ? 'populated' : 'empty' : 'eem_disabled'; - telemetry.reportEntityInventoryViewed({ view_state: viewState, }); } - }, [ - isEnablementLoading, - hasDataLoading, - isEntityManagerEnabled, - value.hasData, - telemetry, - isLoadingComplete, - ]); + }, [isEntityManagerEnabled, value.hasData, telemetry, isLoadingComplete]); if (isEnablementLoading || hasDataLoading) { return ( From d7d2aeecd8e1b89f25b0f984850d29e0e2ee04ec Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 16:49:43 +0200 Subject: [PATCH 21/36] Use isLoadingComplete hook in Inventory --- .../public/services/telemetry/telemetry_service.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts index e85ca1dd4a0c2..30f2292dfcc60 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts @@ -113,8 +113,8 @@ describe('TelemetryService', () => { const telemetry = service.start(); const params: EntityInventorySearchQuerySubmittedParams = { kuery_fields: ['_index'], - timerange: 'now-1y/d - now', action: 'submit', + entity_types: ['container'], }; telemetry.reportEntityInventorySearchQuerySubmitted(params); From 22b34d9c0b2a00089eec889681d2db47c8acfeed Mon Sep 17 00:00:00 2001 From: iblancof Date: Mon, 21 Oct 2024 16:51:10 +0200 Subject: [PATCH 22/36] Add test for reportEntityInventoryEntityTypeFiltered --- .../telemetry/telemetry_service.test.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts index 30f2292dfcc60..415cf0e7d4406 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts @@ -13,6 +13,7 @@ import { type EntityViewClickedParams, type EntityInventorySearchQuerySubmittedParams, TelemetryEventTypes, + type EntityInventoryEntityTypeFilteredParams, } from './types'; describe('TelemetryService', () => { @@ -127,6 +128,26 @@ describe('TelemetryService', () => { }); }); + describe('#reportEntityInventoryEntityTypeFiltered', () => { + it('should report entity type filtered with properties', async () => { + const setupParams = getSetupParams(); + service.setup(setupParams); + const telemetry = service.start(); + const params: EntityInventoryEntityTypeFilteredParams = { + kuery_fields: ['_index'], + entity_types: ['container'], + }; + + telemetry.reportEntityInventoryEntityTypeFiltered(params); + + expect(setupParams.analytics.reportEvent).toHaveBeenCalledTimes(1); + expect(setupParams.analytics.reportEvent).toHaveBeenCalledWith( + TelemetryEventTypes.ENTITY_INVENTORY_ENTITY_TYPE_FILTERED, + params + ); + }); + }); + describe('#reportEntityViewClicked', () => { it('should report entity view clicked with properties', async () => { const setupParams = getSetupParams(); From fd32a16b46172c24ffa44ae676cfcacd65361376 Mon Sep 17 00:00:00 2001 From: iblancof Date: Tue, 22 Oct 2024 10:25:11 +0200 Subject: [PATCH 23/36] Use EntityType in telemetry events --- .../inventory/public/services/telemetry/types.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts index d83da1ea5d663..28e6bf516d424 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts @@ -6,6 +6,7 @@ */ import type { AnalyticsServiceSetup, RootSchema } from '@kbn/core/public'; +import type { EntityType } from '../../../common/entities'; export interface TelemetryServiceSetupParams { analytics: AnalyticsServiceSetup; @@ -22,17 +23,17 @@ export interface EntityInventoryViewedParams { export interface EntityInventorySearchQuerySubmittedParams { kuery_fields: string[]; - entity_types: Array<'container' | 'host' | 'service'>; + entity_types: EntityType[]; action: 'submit' | 'refresh'; } export interface EntityInventoryEntityTypeFilteredParams { kuery_fields: string[]; - entity_types: Array<'container' | 'host' | 'service'>; + entity_types: EntityType[]; } export interface EntityViewClickedParams { - entity_type: 'container' | 'host' | 'service'; + entity_type: EntityType; view_type: 'detail' | 'flyout'; } From 925350f7fa7d4224e7153dbacd15c05213a23a6f Mon Sep 17 00:00:00 2001 From: iblancof Date: Tue, 22 Oct 2024 14:18:29 +0200 Subject: [PATCH 24/36] Refactor search bar component to use optional parameters --- .../inventory/public/components/search_bar/index.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx index 2fe2008ec773a..60f55354b994c 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx @@ -59,9 +59,9 @@ export function SearchBar() { searchIsUpdate, searchEntityTypes, }: { - searchQuery: Query | undefined; - searchEntityTypes: EntityType[] | undefined; - searchIsUpdate: boolean | undefined; + searchQuery?: Query; + searchEntityTypes?: EntityType[]; + searchIsUpdate?: boolean; }) => { telemetry.reportEntityInventorySearchQuerySubmitted({ kuery_fields: getKqlFieldNamesFromExpression(searchQuery?.query as string), @@ -78,7 +78,7 @@ export function SearchBar() { filterKuery, }: { filterEntityTypes: EntityType[]; - filterKuery: string | undefined; + filterKuery?: string; }) => { telemetry.reportEntityInventoryEntityTypeFiltered({ entity_types: filterEntityTypes, From a5926c020a71b3773976dc92e874dec721c0de57 Mon Sep 17 00:00:00 2001 From: iblancof Date: Tue, 22 Oct 2024 14:19:59 +0200 Subject: [PATCH 25/36] Refactor entities_grid component to use constant for entity type --- .../inventory/public/components/entities_grid/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx index 7bdc9e6f75267..e9c1859e1aeea 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx @@ -100,7 +100,7 @@ export function EntitiesGrid({ } const columnEntityTableId = columnId as EntityColumnIds; - const entityType = entity['entity.type']; + const entityType = entity[ENTITY_TYPE]; switch (columnEntityTableId) { case 'alertsCount': From 0851b1ca457c8f22cc6e5c56b1b3e8a25424e219 Mon Sep 17 00:00:00 2001 From: iblancof Date: Tue, 22 Oct 2024 14:53:01 +0200 Subject: [PATCH 26/36] Refactor search bar component to use getKqlFieldsWithFallback --- .../public/components/search_bar/index.tsx | 7 +-- .../get_kql_field_names_with_fallback.test.ts | 44 +++++++++++++++++++ .../get_kql_field_names_with_fallback.ts | 16 +++++++ 3 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/observability_solution/inventory/public/utils/get_kql_field_names_with_fallback.test.ts create mode 100644 x-pack/plugins/observability_solution/inventory/public/utils/get_kql_field_names_with_fallback.ts diff --git a/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx index 60f55354b994c..dcfce8adcb983 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/search_bar/index.tsx @@ -9,7 +9,7 @@ import { SearchBarOwnProps } from '@kbn/unified-search-plugin/public/search_bar' import deepEqual from 'fast-deep-equal'; import React, { useCallback, useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { getKqlFieldNamesFromExpression, Query } from '@kbn/es-query'; +import { Query } from '@kbn/es-query'; import { EntityType } from '../../../common/entities'; import { useInventorySearchBarContext } from '../../context/inventory_search_bar_context_provider'; import { useAdHocInventoryDataView } from '../../hooks/use_adhoc_inventory_data_view'; @@ -17,6 +17,7 @@ import { useInventoryParams } from '../../hooks/use_inventory_params'; import { useKibana } from '../../hooks/use_kibana'; import { EntityTypesControls } from './entity_types_controls'; import { DiscoverButton } from './discover_button'; +import { getKqlFieldsWithFallback } from '../../utils/get_kql_field_names_with_fallback'; export function SearchBar() { const { searchBarContentSubject$ } = useInventorySearchBarContext(); @@ -64,7 +65,7 @@ export function SearchBar() { searchIsUpdate?: boolean; }) => { telemetry.reportEntityInventorySearchQuerySubmitted({ - kuery_fields: getKqlFieldNamesFromExpression(searchQuery?.query as string), + kuery_fields: getKqlFieldsWithFallback(searchQuery?.query as string), entity_types: searchEntityTypes || [], action: searchIsUpdate ? 'submit' : 'refresh', }); @@ -82,7 +83,7 @@ export function SearchBar() { }) => { telemetry.reportEntityInventoryEntityTypeFiltered({ entity_types: filterEntityTypes, - kuery_fields: filterKuery ? getKqlFieldNamesFromExpression(filterKuery) : [], + kuery_fields: filterKuery ? getKqlFieldsWithFallback(filterKuery) : [], }); }, [telemetry] diff --git a/x-pack/plugins/observability_solution/inventory/public/utils/get_kql_field_names_with_fallback.test.ts b/x-pack/plugins/observability_solution/inventory/public/utils/get_kql_field_names_with_fallback.test.ts new file mode 100644 index 0000000000000..89305e2bb08c9 --- /dev/null +++ b/x-pack/plugins/observability_solution/inventory/public/utils/get_kql_field_names_with_fallback.test.ts @@ -0,0 +1,44 @@ +/* + * 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 { getKqlFieldsWithFallback } from './get_kql_field_names_with_fallback'; +import { getKqlFieldNamesFromExpression } from '@kbn/es-query'; + +jest.mock('@kbn/es-query', () => ({ + getKqlFieldNamesFromExpression: jest.fn(), +})); + +describe('getKqlFieldsWithFallback', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should return field names when getKqlFieldNamesFromExpression succeeds', () => { + const mockFieldNames = ['field1', 'field2']; + (getKqlFieldNamesFromExpression as jest.Mock).mockReturnValue(mockFieldNames); + const expectedArg = 'testKuery'; + + const result = getKqlFieldsWithFallback(expectedArg); + expect(result).toEqual(mockFieldNames); + expect(getKqlFieldNamesFromExpression).toHaveBeenCalledWith(expectedArg); + }); + + it('should return an empty array when getKqlFieldNamesFromExpression throws an error', () => { + (getKqlFieldNamesFromExpression as jest.Mock).mockImplementation(() => { + throw new Error('Test error'); + }); + const expectedArg = 'testKuery'; + + const result = getKqlFieldsWithFallback(expectedArg); + expect(result).toEqual([]); + expect(getKqlFieldNamesFromExpression).toHaveBeenCalledWith(expectedArg); + }); +}); diff --git a/x-pack/plugins/observability_solution/inventory/public/utils/get_kql_field_names_with_fallback.ts b/x-pack/plugins/observability_solution/inventory/public/utils/get_kql_field_names_with_fallback.ts new file mode 100644 index 0000000000000..029405b5fc235 --- /dev/null +++ b/x-pack/plugins/observability_solution/inventory/public/utils/get_kql_field_names_with_fallback.ts @@ -0,0 +1,16 @@ +/* + * 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 { getKqlFieldNamesFromExpression } from '@kbn/es-query'; + +export function getKqlFieldsWithFallback(kuery: string): string[] { + try { + return getKqlFieldNamesFromExpression(kuery); + } catch (e) { + return []; + } +} From 52f94cd782bd92974e49729a7c11d5f29c21d8ad Mon Sep 17 00:00:00 2001 From: iblancof Date: Tue, 22 Oct 2024 15:16:32 +0200 Subject: [PATCH 27/36] Move entity click telemetry from EntitiesGrid to EntityName --- .../entities_grid/entity_name/index.tsx | 24 ++++++++++++----- .../public/components/entities_grid/index.tsx | 26 ++----------------- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/entity_name/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/entity_name/index.tsx index a4e60cbb081b1..982a616da8fda 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/entity_name/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/entity_name/index.tsx @@ -22,17 +22,25 @@ import { EntityIcon } from '../../entity_icon'; interface EntityNameProps { entity: Entity; - onClick?: () => void; } -export function EntityName({ entity, onClick }: EntityNameProps) { - const { services } = useKibana(); +export function EntityName({ entity }: EntityNameProps) { + const { + services: { telemetry, share }, + } = useKibana(); const assetDetailsLocator = - services.share?.url.locators.get(ASSET_DETAILS_LOCATOR_ID); + share?.url.locators.get(ASSET_DETAILS_LOCATOR_ID); const serviceOverviewLocator = - services.share?.url.locators.get('serviceOverviewLocator'); + share?.url.locators.get('serviceOverviewLocator'); + + const handleLinkClick = useCallback(() => { + telemetry.reportEntityViewClicked({ + view_type: 'detail', + entity_type: entity['entity.type'], + }); + }, [entity, telemetry]); const getEntityRedirectUrl = useCallback(() => { const type = entity[ENTITY_TYPE]; @@ -60,7 +68,11 @@ export function EntityName({ entity, onClick }: EntityNameProps) { return ( // eslint-disable-next-line @elastic/eui/href-or-on-click - + diff --git a/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx index e9c1859e1aeea..9434c4ca96c3d 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx @@ -26,7 +26,6 @@ import { BadgeFilterWithPopover } from '../badge_filter_with_popover'; import { getColumns } from './grid_columns'; import { AlertsBadge } from '../alerts_badge/alerts_badge'; import { getEntityTypeLabel } from '../../utils/get_entity_type_label'; -import { useKibana } from '../../hooks/use_kibana'; import { EntityName } from './entity_name'; type InventoryEntitiesAPIReturnType = APIReturnType<'GET /internal/inventory/entities'>; @@ -55,10 +54,6 @@ export function EntitiesGrid({ onChangeSort, onFilterByType, }: Props) { - const { - services: { telemetry }, - } = useKibana(); - const onSort: EuiDataGridSorting['onSort'] = useCallback( (newSortingColumns) => { const lastItem = last(newSortingColumns); @@ -69,16 +64,6 @@ export function EntitiesGrid({ [onChangeSort] ); - const onEntityNameClick = useCallback( - ({ entityType }: { entityType: EntityType }) => { - telemetry.reportEntityViewClicked({ - view_type: 'detail', - entity_type: entityType, - }); - }, - [telemetry] - ); - const showAlertsColumn = useMemo( () => entities?.some((entity) => entity?.alertsCount && entity?.alertsCount > 0), [entities] @@ -142,19 +127,12 @@ export function EntitiesGrid({ /> ); case ENTITY_DISPLAY_NAME: - return ( - { - onEntityNameClick({ entityType }); - }} - /> - ); + return ; default: return entity[columnId as EntityColumnIds] || ''; } }, - [entities, onEntityNameClick, onFilterByType] + [entities, onFilterByType] ); if (loading) { From a4bdbb2e60e50423e68cf6c199aa7a7ede801b81 Mon Sep 17 00:00:00 2001 From: iblancof Date: Wed, 23 Oct 2024 12:13:42 +0200 Subject: [PATCH 28/36] Refactor telemetry initialization and update in inventory plugin --- .../inventory_page_template/index.tsx | 3 +- .../inventory/public/plugin.ts | 57 +++++++++++++++---- .../services/telemetry/telemetry_client.ts | 35 +++++++++++- .../services/telemetry/telemetry_service.ts | 10 +++- .../public/services/telemetry/types.ts | 5 ++ .../inventory/public/services/types.ts | 4 +- 6 files changed, 95 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx index 94fedb01302a7..dfd510386636d 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx @@ -18,7 +18,6 @@ import { useEntityManager } from '../../hooks/use_entity_manager'; import { Welcome } from '../entity_enablement/welcome_modal'; import { useInventoryAbortableAsync } from '../../hooks/use_inventory_abortable_async'; import { EmptyState } from '../empty_states/empty_state'; -import { eemEnabled$ } from '../../analytics/register_eem_enabled_context'; import { useIsLoadingComplete } from '../../hooks/use_is_loading_complete'; const pageTitle = ( @@ -51,7 +50,7 @@ export function InventoryPageTemplate({ children }: { children: React.ReactNode } = useEntityManager(); const handleSuccess = () => { - eemEnabled$.next({ eem_enabled: true }); + telemetry.updateEemEnabled(true); refresh(); toggleWelcomedModal(); }; diff --git a/x-pack/plugins/observability_solution/inventory/public/plugin.ts b/x-pack/plugins/observability_solution/inventory/public/plugin.ts index bc32bfafa90d9..409c482b3e13b 100644 --- a/x-pack/plugins/observability_solution/inventory/public/plugin.ts +++ b/x-pack/plugins/observability_solution/inventory/public/plugin.ts @@ -28,7 +28,7 @@ import type { InventorySetupDependencies, InventoryStartDependencies, } from './types'; -import { registerEemEnabledContext } from './analytics/register_eem_enabled_context'; +import { TelemetryClient } from './services/telemetry/telemetry_client'; export class InventoryPlugin implements @@ -50,6 +50,38 @@ export class InventoryPlugin this.kibanaVersion = context.env.packageInfo.version; this.isServerlessEnv = context.env.packageInfo.buildFlavor === 'serverless'; } + + private async initializeTelemetry( + coreStart: CoreStart, + pluginsStart: InventoryStartDependencies, + telemetry: TelemetryClient + ) { + const shouldHideInventory = await this.shouldHideInventory(pluginsStart, coreStart); + + if (!shouldHideInventory) { + telemetry.initialize(); + } + } + + private async shouldHideInventory( + pluginsStart: InventoryStartDependencies, + coreStart: CoreStart + ) { + if (pluginsStart.spaces) { + const space = await pluginsStart.spaces.getActiveSpace(); + return this.isInventoryDisabledByUserOrSpace(space, coreStart); + } + + return !coreStart.application.capabilities.inventory.show; + } + + private isInventoryDisabledByUserOrSpace(space: any, coreStart: CoreStart): boolean { + return ( + space.disabledFeatures.includes(INVENTORY_APP_ID) || + !coreStart.application.capabilities.inventory.show + ); + } + setup( coreSetup: CoreSetup, pluginsSetup: InventorySetupDependencies @@ -59,17 +91,26 @@ export class InventoryPlugin 'observability:entityCentricExperience', true ); + + this.telemetry.setup({ + analytics: coreSetup.analytics, + }); + + const telemetry = this.telemetry.start({ + entityManager: pluginsSetup.entityManager, + }); + const getStartServices = coreSetup.getStartServices(); + getStartServices.then(([coreStart, pluginsStart]) => { + this.initializeTelemetry(coreStart, pluginsStart, telemetry); + }); + const hideInventory$ = from(getStartServices).pipe( mergeMap(([coreStart, pluginsStart]) => { if (pluginsStart.spaces) { return from(pluginsStart.spaces.getActiveSpace()).pipe( - map( - (space) => - space.disabledFeatures.includes(INVENTORY_APP_ID) || - !coreStart.application.capabilities.inventory.show - ) + map((space) => this.isInventoryDisabledByUserOrSpace(space, coreStart)) ); } @@ -80,7 +121,6 @@ export class InventoryPlugin const sections$ = hideInventory$.pipe( map((hideInventory) => { if (isEntityCentricExperienceSettingEnabled && !hideInventory) { - registerEemEnabledContext(coreSetup.analytics, pluginsSetup.entityManager); return [ { label: '', @@ -107,9 +147,6 @@ export class InventoryPlugin pluginsSetup.observabilityShared.navigation.registerSections(sections$); - this.telemetry.setup({ analytics: coreSetup.analytics }); - const telemetry = this.telemetry.start(); - const isCloudEnv = !!pluginsSetup.cloud?.isCloudEnabled; const isServerlessEnv = pluginsSetup.cloud?.isServerlessEnabled || this.isServerlessEnv; diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts index d58070d9f6aae..fd4848b4caecc 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts @@ -6,6 +6,9 @@ */ import { AnalyticsServiceSetup } from '@kbn/core-analytics-browser'; + +import { BehaviorSubject } from 'rxjs'; +import { EntityManagerPublicPluginSetup } from '@kbn/entityManager-plugin/public'; import { type ITelemetryClient, TelemetryEventTypes, @@ -13,11 +16,39 @@ import { type EntityInventoryViewedParams, type EntityInventorySearchQuerySubmittedParams, type EntityViewClickedParams, - EntityInventoryEntityTypeFilteredParams, + type EntityInventoryEntityTypeFilteredParams, } from './types'; export class TelemetryClient implements ITelemetryClient { - constructor(private analytics: AnalyticsServiceSetup) {} + private eemEnabled$: BehaviorSubject<{ eem_enabled: boolean }>; + + constructor( + private analytics: AnalyticsServiceSetup, + private entityManager: EntityManagerPublicPluginSetup + ) { + this.eemEnabled$ = new BehaviorSubject<{ eem_enabled: boolean }>({ eem_enabled: false }); + } + + public initialize = () => { + this.entityManager.entityClient.isManagedEntityDiscoveryEnabled().then(({ enabled }) => { + this.updateEemEnabled(enabled); + + this.analytics.registerContextProvider({ + name: 'eem_enabled', + context$: this.eemEnabled$, + schema: { + eem_enabled: { + type: 'boolean', + _meta: { description: 'Whether EEM is enabled or not.' }, + }, + }, + }); + }); + }; + + public updateEemEnabled = (enabled: boolean) => { + this.eemEnabled$.next({ eem_enabled: enabled }); + }; public reportInventoryAddData = (params: InventoryAddDataParams) => { this.analytics.reportEvent(TelemetryEventTypes.INVENTORY_ADD_DATA_CLICKED, params); diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.ts index fa416f76b3c16..f4d8edeec1d3a 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.ts @@ -5,7 +5,11 @@ * 2.0. */ import type { AnalyticsServiceSetup } from '@kbn/core-analytics-browser'; -import type { TelemetryServiceSetupParams, ITelemetryClient, TelemetryEventParams } from './types'; +import type { + TelemetryServiceSetupParams, + TelemetryEventParams, + TelemetryServiceStartParams, +} from './types'; import { inventoryTelemetryEventBasedTypes } from './telemetry_events'; import { TelemetryClient } from './telemetry_client'; @@ -23,13 +27,13 @@ export class TelemetryService { ); } - public start(): ITelemetryClient { + public start({ entityManager }: TelemetryServiceStartParams): TelemetryClient { if (!this.analytics) { throw new Error( 'The TelemetryService.setup() method has not been invoked, be sure to call it during the plugin setup.' ); } - return new TelemetryClient(this.analytics); + return new TelemetryClient(this.analytics, entityManager); } } diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts index 28e6bf516d424..6031b0a627431 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts @@ -6,12 +6,17 @@ */ import type { AnalyticsServiceSetup, RootSchema } from '@kbn/core/public'; +import { EntityManagerPublicPluginSetup } from '@kbn/entityManager-plugin/public'; import type { EntityType } from '../../../common/entities'; export interface TelemetryServiceSetupParams { analytics: AnalyticsServiceSetup; } +export interface TelemetryServiceStartParams { + entityManager: EntityManagerPublicPluginSetup; +} + export interface InventoryAddDataParams { view: 'add_data_button' | 'empty_state'; journey?: 'add_data' | 'associate_existing_service_logs'; diff --git a/x-pack/plugins/observability_solution/inventory/public/services/types.ts b/x-pack/plugins/observability_solution/inventory/public/services/types.ts index d0cc176e7b53f..a2daabc91e1c9 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/types.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/types.ts @@ -6,9 +6,9 @@ */ import type { InventoryAPIClient } from '../api'; -import type { ITelemetryClient } from './telemetry/types'; +import { TelemetryClient } from './telemetry/telemetry_client'; export interface InventoryServices { inventoryAPIClient: InventoryAPIClient; - telemetry: ITelemetryClient; + telemetry: TelemetryClient; } From af1acc565cbbbc1971d41508dd0bdeeea02d83ed Mon Sep 17 00:00:00 2001 From: iblancof Date: Wed, 23 Oct 2024 12:14:27 +0200 Subject: [PATCH 29/36] Delete registerEemEnabledContext --- .../analytics/register_eem_enabled_context.ts | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts diff --git a/x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts b/x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts deleted file mode 100644 index 062f7f61961e9..0000000000000 --- a/x-pack/plugins/observability_solution/inventory/public/analytics/register_eem_enabled_context.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 { AnalyticsServiceSetup } from '@kbn/core/public'; -import { BehaviorSubject } from 'rxjs'; -import { EntityManagerPublicPluginSetup } from '@kbn/entityManager-plugin/public'; - -export let eemEnabled$: BehaviorSubject<{ eem_enabled: boolean }>; - -export function registerEemEnabledContext( - analytics: AnalyticsServiceSetup, - entityManager: EntityManagerPublicPluginSetup -) { - entityManager.entityClient.isManagedEntityDiscoveryEnabled().then(({ enabled }) => { - eemEnabled$ = new BehaviorSubject({ - eem_enabled: enabled, - }); - - analytics.registerContextProvider({ - name: 'eem_enabled', - context$: eemEnabled$, - schema: { - eem_enabled: { - type: 'boolean', - _meta: { description: 'Whether EEM is enabled or not.' }, - }, - }, - }); - }); -} From 20776d3c42dd7cf36cd8968ecc77057f76bfcc21 Mon Sep 17 00:00:00 2001 From: iblancof Date: Wed, 23 Oct 2024 14:28:06 +0200 Subject: [PATCH 30/36] Fix telemetry service tests --- .../telemetry/telemetry_service.test.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts index 415cf0e7d4406..52f027719e479 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts @@ -15,6 +15,7 @@ import { TelemetryEventTypes, type EntityInventoryEntityTypeFilteredParams, } from './types'; +import { EntityManagerPublicPluginSetup } from '@kbn/entityManager-plugin/public'; describe('TelemetryService', () => { let service: TelemetryService; @@ -30,6 +31,12 @@ describe('TelemetryService', () => { }; }; + const getStartParams = () => { + return { + entityManager: {} as unknown as EntityManagerPublicPluginSetup, + }; + }; + describe('#setup()', () => { it('should register all the custom events', () => { const setupParams = getSetupParams(); @@ -52,7 +59,7 @@ describe('TelemetryService', () => { it('should return all the available tracking methods', () => { const setupParams = getSetupParams(); service.setup(setupParams); - const telemetry = service.start(); + const telemetry = service.start(getStartParams()); const expectedProperties = [ 'reportInventoryAddData', @@ -70,7 +77,7 @@ describe('TelemetryService', () => { it('should report inventory add data clicked with properties', async () => { const setupParams = getSetupParams(); service.setup(setupParams); - const telemetry = service.start(); + const telemetry = service.start(getStartParams()); telemetry.reportInventoryAddData({ view: 'add_data_button', @@ -92,7 +99,7 @@ describe('TelemetryService', () => { it('should report entity inventory viewed with properties', async () => { const setupParams = getSetupParams(); service.setup(setupParams); - const telemetry = service.start(); + const telemetry = service.start(getStartParams()); const params: EntityInventoryViewedParams = { view_state: 'empty', }; @@ -111,7 +118,7 @@ describe('TelemetryService', () => { it('should report search query submitted with properties', async () => { const setupParams = getSetupParams(); service.setup(setupParams); - const telemetry = service.start(); + const telemetry = service.start(getStartParams()); const params: EntityInventorySearchQuerySubmittedParams = { kuery_fields: ['_index'], action: 'submit', @@ -132,7 +139,7 @@ describe('TelemetryService', () => { it('should report entity type filtered with properties', async () => { const setupParams = getSetupParams(); service.setup(setupParams); - const telemetry = service.start(); + const telemetry = service.start(getStartParams()); const params: EntityInventoryEntityTypeFilteredParams = { kuery_fields: ['_index'], entity_types: ['container'], @@ -152,7 +159,7 @@ describe('TelemetryService', () => { it('should report entity view clicked with properties', async () => { const setupParams = getSetupParams(); service.setup(setupParams); - const telemetry = service.start(); + const telemetry = service.start(getStartParams()); const params: EntityViewClickedParams = { entity_type: 'container', view_type: 'detail', From f7a6bee0b96d51349764c69d060ade0a31e1eb13 Mon Sep 17 00:00:00 2001 From: iblancof Date: Wed, 23 Oct 2024 14:28:32 +0200 Subject: [PATCH 31/36] Fix type in getMockInventoryContext --- .../inventory/.storybook/get_mock_inventory_context.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/.storybook/get_mock_inventory_context.tsx b/x-pack/plugins/observability_solution/inventory/.storybook/get_mock_inventory_context.tsx index 9c2ea13cf753e..2755c6cbf4d10 100644 --- a/x-pack/plugins/observability_solution/inventory/.storybook/get_mock_inventory_context.tsx +++ b/x-pack/plugins/observability_solution/inventory/.storybook/get_mock_inventory_context.tsx @@ -17,7 +17,7 @@ import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import type { HttpStart } from '@kbn/core-http-browser'; import { action } from '@storybook/addon-actions'; import type { InventoryKibanaContext } from '../public/hooks/use_kibana'; -import type { ITelemetryClient } from '../public/services/telemetry/types'; +import { TelemetryClient } from '../public/services/telemetry/telemetry_client'; export function getMockInventoryContext(): InventoryKibanaContext { const coreStart = coreMock.createStart(); @@ -42,7 +42,7 @@ export function getMockInventoryContext(): InventoryKibanaContext { }, }, } as unknown as SharePluginStart, - telemetry: {} as unknown as ITelemetryClient, + telemetry: {} as unknown as TelemetryClient, unifiedSearch: {} as unknown as UnifiedSearchPublicPluginStart, dataViews: {} as unknown as DataViewsPublicPluginStart, data: {} as unknown as DataPublicPluginStart, From 9fe837f8f75f00d54ae6b5d9f269a6ff7426f2c5 Mon Sep 17 00:00:00 2001 From: iblancof Date: Thu, 24 Oct 2024 11:20:38 +0200 Subject: [PATCH 32/36] Remove unnecessary type annotation --- .../inventory/public/components/entities_grid/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx index 9434c4ca96c3d..aeb87c11bde5b 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/entities_grid/index.tsx @@ -20,7 +20,7 @@ import { ENTITY_LAST_SEEN, ENTITY_TYPE, } from '@kbn/observability-shared-plugin/common'; -import { Entity, EntityColumnIds, EntityType } from '../../../common/entities'; +import { EntityColumnIds, EntityType } from '../../../common/entities'; import { APIReturnType } from '../../api'; import { BadgeFilterWithPopover } from '../badge_filter_with_popover'; import { getColumns } from './grid_columns'; @@ -79,7 +79,7 @@ export function EntitiesGrid({ const renderCellValue = useCallback( ({ rowIndex, columnId }: EuiDataGridCellValueElementProps) => { - const entity: Entity = entities[rowIndex]; + const entity = entities[rowIndex]; if (entity === undefined) { return null; } From 7bc59bd16a5a263971e9a0c711510ce25a985eed Mon Sep 17 00:00:00 2001 From: iblancof Date: Thu, 24 Oct 2024 14:47:39 +0200 Subject: [PATCH 33/36] Remove registerContextProvider in Inventory plugin --- .../inventory_page_template/index.tsx | 1 - .../inventory/public/plugin.ts | 46 +++---------------- .../services/telemetry/telemetry_client.ts | 32 +------------ .../services/telemetry/telemetry_service.ts | 10 ++-- 4 files changed, 10 insertions(+), 79 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx b/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx index dfd510386636d..476451370fa12 100644 --- a/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx +++ b/x-pack/plugins/observability_solution/inventory/public/components/inventory_page_template/index.tsx @@ -50,7 +50,6 @@ export function InventoryPageTemplate({ children }: { children: React.ReactNode } = useEntityManager(); const handleSuccess = () => { - telemetry.updateEemEnabled(true); refresh(); toggleWelcomedModal(); }; diff --git a/x-pack/plugins/observability_solution/inventory/public/plugin.ts b/x-pack/plugins/observability_solution/inventory/public/plugin.ts index 409c482b3e13b..109123859d4ca 100644 --- a/x-pack/plugins/observability_solution/inventory/public/plugin.ts +++ b/x-pack/plugins/observability_solution/inventory/public/plugin.ts @@ -28,7 +28,6 @@ import type { InventorySetupDependencies, InventoryStartDependencies, } from './types'; -import { TelemetryClient } from './services/telemetry/telemetry_client'; export class InventoryPlugin implements @@ -51,37 +50,6 @@ export class InventoryPlugin this.isServerlessEnv = context.env.packageInfo.buildFlavor === 'serverless'; } - private async initializeTelemetry( - coreStart: CoreStart, - pluginsStart: InventoryStartDependencies, - telemetry: TelemetryClient - ) { - const shouldHideInventory = await this.shouldHideInventory(pluginsStart, coreStart); - - if (!shouldHideInventory) { - telemetry.initialize(); - } - } - - private async shouldHideInventory( - pluginsStart: InventoryStartDependencies, - coreStart: CoreStart - ) { - if (pluginsStart.spaces) { - const space = await pluginsStart.spaces.getActiveSpace(); - return this.isInventoryDisabledByUserOrSpace(space, coreStart); - } - - return !coreStart.application.capabilities.inventory.show; - } - - private isInventoryDisabledByUserOrSpace(space: any, coreStart: CoreStart): boolean { - return ( - space.disabledFeatures.includes(INVENTORY_APP_ID) || - !coreStart.application.capabilities.inventory.show - ); - } - setup( coreSetup: CoreSetup, pluginsSetup: InventorySetupDependencies @@ -96,21 +64,19 @@ export class InventoryPlugin analytics: coreSetup.analytics, }); - const telemetry = this.telemetry.start({ - entityManager: pluginsSetup.entityManager, - }); + const telemetry = this.telemetry.start(); const getStartServices = coreSetup.getStartServices(); - getStartServices.then(([coreStart, pluginsStart]) => { - this.initializeTelemetry(coreStart, pluginsStart, telemetry); - }); - const hideInventory$ = from(getStartServices).pipe( mergeMap(([coreStart, pluginsStart]) => { if (pluginsStart.spaces) { return from(pluginsStart.spaces.getActiveSpace()).pipe( - map((space) => this.isInventoryDisabledByUserOrSpace(space, coreStart)) + map( + (space) => + space.disabledFeatures.includes(INVENTORY_APP_ID) || + !coreStart.application.capabilities.inventory.show + ) ); } diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts index fd4848b4caecc..54d20ea324b11 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_client.ts @@ -7,8 +7,6 @@ import { AnalyticsServiceSetup } from '@kbn/core-analytics-browser'; -import { BehaviorSubject } from 'rxjs'; -import { EntityManagerPublicPluginSetup } from '@kbn/entityManager-plugin/public'; import { type ITelemetryClient, TelemetryEventTypes, @@ -20,35 +18,7 @@ import { } from './types'; export class TelemetryClient implements ITelemetryClient { - private eemEnabled$: BehaviorSubject<{ eem_enabled: boolean }>; - - constructor( - private analytics: AnalyticsServiceSetup, - private entityManager: EntityManagerPublicPluginSetup - ) { - this.eemEnabled$ = new BehaviorSubject<{ eem_enabled: boolean }>({ eem_enabled: false }); - } - - public initialize = () => { - this.entityManager.entityClient.isManagedEntityDiscoveryEnabled().then(({ enabled }) => { - this.updateEemEnabled(enabled); - - this.analytics.registerContextProvider({ - name: 'eem_enabled', - context$: this.eemEnabled$, - schema: { - eem_enabled: { - type: 'boolean', - _meta: { description: 'Whether EEM is enabled or not.' }, - }, - }, - }); - }); - }; - - public updateEemEnabled = (enabled: boolean) => { - this.eemEnabled$.next({ eem_enabled: enabled }); - }; + constructor(private analytics: AnalyticsServiceSetup) {} public reportInventoryAddData = (params: InventoryAddDataParams) => { this.analytics.reportEvent(TelemetryEventTypes.INVENTORY_ADD_DATA_CLICKED, params); diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.ts index f4d8edeec1d3a..b81aff39672bb 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.ts @@ -5,11 +5,7 @@ * 2.0. */ import type { AnalyticsServiceSetup } from '@kbn/core-analytics-browser'; -import type { - TelemetryServiceSetupParams, - TelemetryEventParams, - TelemetryServiceStartParams, -} from './types'; +import type { TelemetryServiceSetupParams, TelemetryEventParams } from './types'; import { inventoryTelemetryEventBasedTypes } from './telemetry_events'; import { TelemetryClient } from './telemetry_client'; @@ -27,13 +23,13 @@ export class TelemetryService { ); } - public start({ entityManager }: TelemetryServiceStartParams): TelemetryClient { + public start(): TelemetryClient { if (!this.analytics) { throw new Error( 'The TelemetryService.setup() method has not been invoked, be sure to call it during the plugin setup.' ); } - return new TelemetryClient(this.analytics, entityManager); + return new TelemetryClient(this.analytics); } } From 3a6dbfa64b06753a87cecb8ef9e57560d72ac895 Mon Sep 17 00:00:00 2001 From: iblancof Date: Fri, 25 Oct 2024 09:26:19 +0200 Subject: [PATCH 34/36] Fix tests --- .../telemetry/telemetry_service.test.ts | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts index 52f027719e479..415cf0e7d4406 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/telemetry_service.test.ts @@ -15,7 +15,6 @@ import { TelemetryEventTypes, type EntityInventoryEntityTypeFilteredParams, } from './types'; -import { EntityManagerPublicPluginSetup } from '@kbn/entityManager-plugin/public'; describe('TelemetryService', () => { let service: TelemetryService; @@ -31,12 +30,6 @@ describe('TelemetryService', () => { }; }; - const getStartParams = () => { - return { - entityManager: {} as unknown as EntityManagerPublicPluginSetup, - }; - }; - describe('#setup()', () => { it('should register all the custom events', () => { const setupParams = getSetupParams(); @@ -59,7 +52,7 @@ describe('TelemetryService', () => { it('should return all the available tracking methods', () => { const setupParams = getSetupParams(); service.setup(setupParams); - const telemetry = service.start(getStartParams()); + const telemetry = service.start(); const expectedProperties = [ 'reportInventoryAddData', @@ -77,7 +70,7 @@ describe('TelemetryService', () => { it('should report inventory add data clicked with properties', async () => { const setupParams = getSetupParams(); service.setup(setupParams); - const telemetry = service.start(getStartParams()); + const telemetry = service.start(); telemetry.reportInventoryAddData({ view: 'add_data_button', @@ -99,7 +92,7 @@ describe('TelemetryService', () => { it('should report entity inventory viewed with properties', async () => { const setupParams = getSetupParams(); service.setup(setupParams); - const telemetry = service.start(getStartParams()); + const telemetry = service.start(); const params: EntityInventoryViewedParams = { view_state: 'empty', }; @@ -118,7 +111,7 @@ describe('TelemetryService', () => { it('should report search query submitted with properties', async () => { const setupParams = getSetupParams(); service.setup(setupParams); - const telemetry = service.start(getStartParams()); + const telemetry = service.start(); const params: EntityInventorySearchQuerySubmittedParams = { kuery_fields: ['_index'], action: 'submit', @@ -139,7 +132,7 @@ describe('TelemetryService', () => { it('should report entity type filtered with properties', async () => { const setupParams = getSetupParams(); service.setup(setupParams); - const telemetry = service.start(getStartParams()); + const telemetry = service.start(); const params: EntityInventoryEntityTypeFilteredParams = { kuery_fields: ['_index'], entity_types: ['container'], @@ -159,7 +152,7 @@ describe('TelemetryService', () => { it('should report entity view clicked with properties', async () => { const setupParams = getSetupParams(); service.setup(setupParams); - const telemetry = service.start(getStartParams()); + const telemetry = service.start(); const params: EntityViewClickedParams = { entity_type: 'container', view_type: 'detail', From 7a98daa2fe621e03e52d59f3cb43bb03fc826c7f Mon Sep 17 00:00:00 2001 From: iblancof Date: Fri, 25 Oct 2024 10:05:01 +0200 Subject: [PATCH 35/36] Fix types --- .../inventory/.storybook/get_mock_inventory_context.tsx | 4 ++-- .../observability_solution/inventory/public/services/types.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/.storybook/get_mock_inventory_context.tsx b/x-pack/plugins/observability_solution/inventory/.storybook/get_mock_inventory_context.tsx index 2755c6cbf4d10..d3d28fe040198 100644 --- a/x-pack/plugins/observability_solution/inventory/.storybook/get_mock_inventory_context.tsx +++ b/x-pack/plugins/observability_solution/inventory/.storybook/get_mock_inventory_context.tsx @@ -17,7 +17,7 @@ import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import type { HttpStart } from '@kbn/core-http-browser'; import { action } from '@storybook/addon-actions'; import type { InventoryKibanaContext } from '../public/hooks/use_kibana'; -import { TelemetryClient } from '../public/services/telemetry/telemetry_client'; +import { ITelemetryClient } from '../public/services/telemetry/types'; export function getMockInventoryContext(): InventoryKibanaContext { const coreStart = coreMock.createStart(); @@ -42,7 +42,7 @@ export function getMockInventoryContext(): InventoryKibanaContext { }, }, } as unknown as SharePluginStart, - telemetry: {} as unknown as TelemetryClient, + telemetry: {} as unknown as ITelemetryClient, unifiedSearch: {} as unknown as UnifiedSearchPublicPluginStart, dataViews: {} as unknown as DataViewsPublicPluginStart, data: {} as unknown as DataPublicPluginStart, diff --git a/x-pack/plugins/observability_solution/inventory/public/services/types.ts b/x-pack/plugins/observability_solution/inventory/public/services/types.ts index a2daabc91e1c9..b498a1fd49079 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/types.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/types.ts @@ -6,9 +6,9 @@ */ import type { InventoryAPIClient } from '../api'; -import { TelemetryClient } from './telemetry/telemetry_client'; +import { ITelemetryClient } from './telemetry/types'; export interface InventoryServices { inventoryAPIClient: InventoryAPIClient; - telemetry: TelemetryClient; + telemetry: ITelemetryClient; } From 5f5dba06b8a9c2e9c849aeb35e575752294fa183 Mon Sep 17 00:00:00 2001 From: iblancof Date: Fri, 25 Oct 2024 12:13:44 +0200 Subject: [PATCH 36/36] Remove EntityType usage --- .../inventory/public/services/telemetry/types.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts index 6031b0a627431..0e52d115d4597 100644 --- a/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts +++ b/x-pack/plugins/observability_solution/inventory/public/services/telemetry/types.ts @@ -7,7 +7,6 @@ import type { AnalyticsServiceSetup, RootSchema } from '@kbn/core/public'; import { EntityManagerPublicPluginSetup } from '@kbn/entityManager-plugin/public'; -import type { EntityType } from '../../../common/entities'; export interface TelemetryServiceSetupParams { analytics: AnalyticsServiceSetup; @@ -28,17 +27,17 @@ export interface EntityInventoryViewedParams { export interface EntityInventorySearchQuerySubmittedParams { kuery_fields: string[]; - entity_types: EntityType[]; + entity_types: string[]; action: 'submit' | 'refresh'; } export interface EntityInventoryEntityTypeFilteredParams { kuery_fields: string[]; - entity_types: EntityType[]; + entity_types: string[]; } export interface EntityViewClickedParams { - entity_type: EntityType; + entity_type: string; view_type: 'detail' | 'flyout'; }