diff --git a/src/plugins/discover/public/context_awareness/profiles_manager.test.ts b/src/plugins/discover/public/context_awareness/profiles_manager.test.ts index 006b1c9e0da3..d12b56de911b 100644 --- a/src/plugins/discover/public/context_awareness/profiles_manager.test.ts +++ b/src/plugins/discover/public/context_awareness/profiles_manager.test.ts @@ -26,6 +26,7 @@ describe('ProfilesManager', () => { jest.clearAllMocks(); mocks = createContextAwarenessMocks(); jest.spyOn(mocks.ebtManagerMock, 'updateProfilesContextWith'); + jest.spyOn(mocks.ebtManagerMock, 'trackContextualProfileResolvedEvent'); }); it('should return default profiles', () => { @@ -74,6 +75,15 @@ describe('ProfilesManager', () => { 'root-profile', 'data-source-profile', ]); + + expect(mocks.ebtManagerMock.trackContextualProfileResolvedEvent).toHaveBeenNthCalledWith(1, { + profileId: 'root-profile', + contextLevel: 'rootLevel', + }); + expect(mocks.ebtManagerMock.trackContextualProfileResolvedEvent).toHaveBeenNthCalledWith(2, { + profileId: 'data-source-profile', + contextLevel: 'dataSourceLevel', + }); }); it('should expose profiles as an observable', async () => { @@ -152,7 +162,7 @@ describe('ProfilesManager', () => { resolveSpy.mockRejectedValue(new Error('Failed to resolve')); await mocks.profilesManagerMock.resolveRootProfile({ solutionNavId: 'newSolutionNavId' }); expect(addLog).toHaveBeenCalledWith( - '[ProfilesManager] root context resolution failed with params: {\n "solutionNavId": "newSolutionNavId"\n}', + '[ProfilesManager] rootLevel context resolution failed with params: {\n "solutionNavId": "newSolutionNavId"\n}', new Error('Failed to resolve') ); profiles = mocks.profilesManagerMock.getProfiles(); @@ -177,7 +187,7 @@ describe('ProfilesManager', () => { query: { esql: 'from logs-*' }, }); expect(addLog).toHaveBeenCalledWith( - '[ProfilesManager] data source context resolution failed with params: {\n "esqlQuery": "from logs-*"\n}', + '[ProfilesManager] dataSourceLevel context resolution failed with params: {\n "esqlQuery": "from logs-*"\n}', new Error('Failed to resolve') ); profiles = mocks.profilesManagerMock.getProfiles(); @@ -199,10 +209,14 @@ describe('ProfilesManager', () => { }); profiles = mocks.profilesManagerMock.getProfiles({ record: record2 }); expect(addLog).toHaveBeenCalledWith( - '[ProfilesManager] document context resolution failed with params: {\n "recordId": "logstash-2014.09.09::388::"\n}', + '[ProfilesManager] documentLevel context resolution failed with params: {\n "recordId": "logstash-2014.09.09::388::"\n}', new Error('Failed to resolve') ); expect(profiles).toEqual([{}, {}, {}]); + expect(mocks.ebtManagerMock.trackContextualProfileResolvedEvent).toHaveBeenCalledWith({ + profileId: 'document-profile', + contextLevel: 'documentLevel', + }); }); it('should cancel existing root profile resolution when another is triggered', async () => { diff --git a/src/plugins/discover/public/context_awareness/profiles_manager.ts b/src/plugins/discover/public/context_awareness/profiles_manager.ts index d5714565dacd..fefbe7b5c08f 100644 --- a/src/plugins/discover/public/context_awareness/profiles_manager.ts +++ b/src/plugins/discover/public/context_awareness/profiles_manager.ts @@ -51,6 +51,12 @@ export interface GetProfilesOptions { record?: DataTableRecord; } +export enum ContextualProfileLevel { + rootLevel = 'rootLevel', + dataSourceLevel = 'dataSourceLevel', + documentLevel = 'documentLevel', +} + export class ProfilesManager { private readonly rootContext$: BehaviorSubject>; private readonly dataSourceContext$: BehaviorSubject>; @@ -104,7 +110,7 @@ export class ProfilesManager { try { context = await this.rootProfileService.resolve(params); } catch (e) { - logResolutionError(ContextType.Root, serializedParams, e); + logResolutionError(ContextualProfileLevel.rootLevel, serializedParams, e); } if (abortController.signal.aborted) { @@ -142,7 +148,7 @@ export class ProfilesManager { rootContext: this.rootContext$.getValue(), }); } catch (e) { - logResolutionError(ContextType.DataSource, serializedParams, e); + logResolutionError(ContextualProfileLevel.dataSourceLevel, serializedParams, e); } if (abortController.signal.aborted) { @@ -179,11 +185,20 @@ export class ProfilesManager { dataSourceContext: this.dataSourceContext$.getValue(), }); } catch (e) { - logResolutionError(ContextType.Document, { recordId: params.record.id }, e); + logResolutionError( + ContextualProfileLevel.documentLevel, + { recordId: params.record.id }, + e + ); context = this.documentProfileService.defaultContext; } } + this.ebtManager.trackContextualProfileResolvedEvent({ + contextLevel: ContextualProfileLevel.documentLevel, + profileId: context.profileId, + }); + return context; }, }); @@ -223,6 +238,15 @@ export class ProfilesManager { private trackActiveProfiles(rootContextProfileId: string, dataSourceContextProfileId: string) { const dscProfiles = [rootContextProfileId, dataSourceContextProfileId]; + this.ebtManager.trackContextualProfileResolvedEvent({ + contextLevel: ContextualProfileLevel.rootLevel, + profileId: rootContextProfileId, + }); + this.ebtManager.trackContextualProfileResolvedEvent({ + contextLevel: ContextualProfileLevel.dataSourceLevel, + profileId: dataSourceContextProfileId, + }); + this.ebtManager.updateProfilesContextWith(dscProfiles); } } @@ -256,19 +280,13 @@ const recordHasContext = ( return Boolean(record && 'context' in record); }; -enum ContextType { - Root = 'root', - DataSource = 'data source', - Document = 'document', -} - const logResolutionError = ( - profileType: ContextType, + profileLevel: ContextualProfileLevel, params: TParams, error: TError ) => { addLog( - `[ProfilesManager] ${profileType} context resolution failed with params: ${JSON.stringify( + `[ProfilesManager] ${profileLevel} context resolution failed with params: ${JSON.stringify( params, null, 2 diff --git a/src/plugins/discover/public/plugin.tsx b/src/plugins/discover/public/plugin.tsx index d0b40869a7c2..fb58e1def508 100644 --- a/src/plugins/discover/public/plugin.tsx +++ b/src/plugins/discover/public/plugin.tsx @@ -180,7 +180,7 @@ export class DiscoverPlugin window.dispatchEvent(new HashChangeEvent('hashchange')); }); - ebtManager.enableContext(); + ebtManager.onDiscoverAppMounted(); const services = buildServices({ core: coreStart, @@ -229,7 +229,7 @@ export class DiscoverPlugin }); return () => { - ebtManager.disableAndResetContext(); + ebtManager.onDiscoverAppUnmounted(); unlistenParentHistory(); unmount(); appUnMounted(); diff --git a/src/plugins/discover/public/services/discover_ebt_manager.test.ts b/src/plugins/discover/public/services/discover_ebt_manager.test.ts index 0ed20dacdb0c..cfc5fa9fbc24 100644 --- a/src/plugins/discover/public/services/discover_ebt_manager.test.ts +++ b/src/plugins/discover/public/services/discover_ebt_manager.test.ts @@ -11,6 +11,7 @@ import { BehaviorSubject } from 'rxjs'; import { coreMock } from '@kbn/core/public/mocks'; import { DiscoverEBTManager } from './discover_ebt_manager'; import { FieldsMetadataPublicStart } from '@kbn/fields-metadata-plugin/public'; +import { ContextualProfileLevel } from '../context_awareness/profiles_manager'; describe('DiscoverEBTManager', () => { let discoverEBTContextManager: DiscoverEBTManager; @@ -31,6 +32,7 @@ describe('DiscoverEBTManager', () => { beforeEach(() => { discoverEBTContextManager = new DiscoverEBTManager(); + (coreSetupMock.analytics.reportEvent as jest.Mock).mockClear(); }); describe('register', () => { @@ -95,7 +97,7 @@ describe('DiscoverEBTManager', () => { shouldInitializeCustomContext: true, shouldInitializeCustomEvents: false, }); - discoverEBTContextManager.enableContext(); + discoverEBTContextManager.onDiscoverAppMounted(); discoverEBTContextManager.updateProfilesContextWith(dscProfiles); expect(discoverEBTContextManager.getProfilesContext()).toBe(dscProfiles); @@ -112,7 +114,7 @@ describe('DiscoverEBTManager', () => { shouldInitializeCustomContext: true, shouldInitializeCustomEvents: false, }); - discoverEBTContextManager.enableContext(); + discoverEBTContextManager.onDiscoverAppMounted(); discoverEBTContextManager.updateProfilesContextWith(dscProfiles); expect(discoverEBTContextManager.getProfilesContext()).toBe(dscProfiles); @@ -140,14 +142,14 @@ describe('DiscoverEBTManager', () => { shouldInitializeCustomContext: true, shouldInitializeCustomEvents: false, }); - discoverEBTContextManager.enableContext(); + discoverEBTContextManager.onDiscoverAppMounted(); discoverEBTContextManager.updateProfilesContextWith(dscProfiles); expect(discoverEBTContextManager.getProfilesContext()).toBe(dscProfiles); - discoverEBTContextManager.disableAndResetContext(); + discoverEBTContextManager.onDiscoverAppUnmounted(); expect(discoverEBTContextManager.getProfilesContext()).toEqual([]); discoverEBTContextManager.updateProfilesContextWith(dscProfiles); expect(discoverEBTContextManager.getProfilesContext()).toEqual([]); - discoverEBTContextManager.enableContext(); + discoverEBTContextManager.onDiscoverAppMounted(); discoverEBTContextManager.updateProfilesContextWith(dscProfiles); expect(discoverEBTContextManager.getProfilesContext()).toBe(dscProfiles); }); @@ -239,4 +241,117 @@ describe('DiscoverEBTManager', () => { }); }); }); + + describe('trackContextualProfileResolvedEvent', () => { + it('should track the event when a next contextual profile is resolved', async () => { + discoverEBTContextManager.initialize({ + core: coreSetupMock, + shouldInitializeCustomContext: false, + shouldInitializeCustomEvents: true, + }); + + discoverEBTContextManager.trackContextualProfileResolvedEvent({ + contextLevel: ContextualProfileLevel.rootLevel, + profileId: 'test', + }); + + expect(coreSetupMock.analytics.reportEvent).toHaveBeenNthCalledWith( + 1, + 'discover_profile_resolved', + { + contextLevel: 'rootLevel', + profileId: 'test', + } + ); + + discoverEBTContextManager.trackContextualProfileResolvedEvent({ + contextLevel: ContextualProfileLevel.dataSourceLevel, + profileId: 'data-source-test', + }); + + expect(coreSetupMock.analytics.reportEvent).toHaveBeenNthCalledWith( + 2, + 'discover_profile_resolved', + { + contextLevel: 'dataSourceLevel', + profileId: 'data-source-test', + } + ); + + discoverEBTContextManager.trackContextualProfileResolvedEvent({ + contextLevel: ContextualProfileLevel.documentLevel, + profileId: 'document-test', + }); + + expect(coreSetupMock.analytics.reportEvent).toHaveBeenNthCalledWith( + 3, + 'discover_profile_resolved', + { + contextLevel: 'documentLevel', + profileId: 'document-test', + } + ); + }); + + it('should not trigger duplicate requests', async () => { + discoverEBTContextManager.initialize({ + core: coreSetupMock, + shouldInitializeCustomContext: false, + shouldInitializeCustomEvents: true, + }); + + discoverEBTContextManager.trackContextualProfileResolvedEvent({ + contextLevel: ContextualProfileLevel.rootLevel, + profileId: 'test1', + }); + + expect(coreSetupMock.analytics.reportEvent).toHaveBeenCalledTimes(1); + + discoverEBTContextManager.trackContextualProfileResolvedEvent({ + contextLevel: ContextualProfileLevel.rootLevel, + profileId: 'test1', + }); + + expect(coreSetupMock.analytics.reportEvent).toHaveBeenCalledTimes(1); + + discoverEBTContextManager.trackContextualProfileResolvedEvent({ + contextLevel: ContextualProfileLevel.rootLevel, + profileId: 'test2', + }); + + expect(coreSetupMock.analytics.reportEvent).toHaveBeenCalledTimes(2); + }); + + it('should trigger similar requests after remount', async () => { + discoverEBTContextManager.initialize({ + core: coreSetupMock, + shouldInitializeCustomContext: false, + shouldInitializeCustomEvents: true, + }); + + discoverEBTContextManager.trackContextualProfileResolvedEvent({ + contextLevel: ContextualProfileLevel.rootLevel, + profileId: 'test1', + }); + + expect(coreSetupMock.analytics.reportEvent).toHaveBeenCalledTimes(1); + + discoverEBTContextManager.trackContextualProfileResolvedEvent({ + contextLevel: ContextualProfileLevel.rootLevel, + profileId: 'test1', + }); + + expect(coreSetupMock.analytics.reportEvent).toHaveBeenCalledTimes(1); + + discoverEBTContextManager.onDiscoverAppUnmounted(); + discoverEBTContextManager.onDiscoverAppMounted(); + + discoverEBTContextManager.trackContextualProfileResolvedEvent({ + contextLevel: ContextualProfileLevel.rootLevel, + profileId: 'test1', + }); + + expect(coreSetupMock.analytics.reportEvent).toHaveBeenCalledTimes(2); + }); + }); }); diff --git a/src/plugins/discover/public/services/discover_ebt_manager.ts b/src/plugins/discover/public/services/discover_ebt_manager.ts index 420eb6c24444..afa93f4d5574 100644 --- a/src/plugins/discover/public/services/discover_ebt_manager.ts +++ b/src/plugins/discover/public/services/discover_ebt_manager.ts @@ -11,7 +11,11 @@ import { BehaviorSubject } from 'rxjs'; import { isEqual } from 'lodash'; import type { CoreSetup } from '@kbn/core-lifecycle-browser'; import type { FieldsMetadataPublicStart } from '@kbn/fields-metadata-plugin/public'; +import { ContextualProfileLevel } from '../context_awareness/profiles_manager'; +/** + * Field usage events i.e. when a field is selected in the data table, removed from the data table, or a filter is added + */ const FIELD_USAGE_EVENT_TYPE = 'discover_field_usage'; const FIELD_USAGE_EVENT_NAME = 'eventName'; const FIELD_USAGE_FIELD_NAME = 'fieldName'; @@ -30,6 +34,19 @@ interface FieldUsageEventData { [FIELD_USAGE_FILTER_OPERATION]?: FilterOperation; } +/** + * Contextual profile resolved event i.e. when a different contextual profile is resolved at root, data source, or document level + * Duplicated events for the same profile level will not be sent. + */ +const CONTEXTUAL_PROFILE_RESOLVED_EVENT_TYPE = 'discover_profile_resolved'; +const CONTEXTUAL_PROFILE_LEVEL = 'contextLevel'; +const CONTEXTUAL_PROFILE_ID = 'profileId'; + +interface ContextualProfileResolvedEventData { + [CONTEXTUAL_PROFILE_LEVEL]: ContextualProfileLevel; + [CONTEXTUAL_PROFILE_ID]: string; +} + export interface DiscoverEBTContextProps { discoverProfiles: string[]; // Discover Context Awareness Profiles } @@ -39,8 +56,19 @@ export class DiscoverEBTManager { private isCustomContextEnabled: boolean = false; private customContext$: DiscoverEBTContext | undefined; private reportEvent: CoreSetup['analytics']['reportEvent'] | undefined; + private lastResolvedContextProfiles: { + [ContextualProfileLevel.rootLevel]: string | undefined; + [ContextualProfileLevel.dataSourceLevel]: string | undefined; + [ContextualProfileLevel.documentLevel]: string | undefined; + }; - constructor() {} + constructor() { + this.lastResolvedContextProfiles = { + [ContextualProfileLevel.rootLevel]: undefined, + [ContextualProfileLevel.dataSourceLevel]: undefined, + [ContextualProfileLevel.documentLevel]: undefined, + }; + } // https://docs.elastic.dev/telemetry/collection/event-based-telemetry public initialize({ @@ -104,17 +132,40 @@ export class DiscoverEBTManager { }, }, }); + core.analytics.registerEventType({ + eventType: CONTEXTUAL_PROFILE_RESOLVED_EVENT_TYPE, + schema: { + [CONTEXTUAL_PROFILE_LEVEL]: { + type: 'keyword', + _meta: { + description: + 'The context level at which it was resolved i.e. rootLevel, dataSourceLevel, documentLevel', + }, + }, + [CONTEXTUAL_PROFILE_ID]: { + type: 'keyword', + _meta: { + description: 'The resolved name of the active profile', + }, + }, + }, + }); this.reportEvent = core.analytics.reportEvent; } } - public enableContext() { + public onDiscoverAppMounted() { this.isCustomContextEnabled = true; } - public disableAndResetContext() { + public onDiscoverAppUnmounted() { this.updateProfilesContextWith([]); this.isCustomContextEnabled = false; + this.lastResolvedContextProfiles = { + [ContextualProfileLevel.rootLevel]: undefined, + [ContextualProfileLevel.dataSourceLevel]: undefined, + [ContextualProfileLevel.documentLevel]: undefined, + }; } public updateProfilesContextWith(discoverProfiles: DiscoverEBTContextProps['discoverProfiles']) { @@ -216,4 +267,30 @@ export class DiscoverEBTManager { filterOperation, }); } + + public trackContextualProfileResolvedEvent({ + contextLevel, + profileId, + }: { + contextLevel: ContextualProfileLevel; + profileId: string; + }) { + if (!this.reportEvent) { + return; + } + + if (this.lastResolvedContextProfiles[contextLevel] === profileId) { + // avoid sending duplicate events to EBT + return; + } + + this.lastResolvedContextProfiles[contextLevel] = profileId; + + const eventData: ContextualProfileResolvedEventData = { + [CONTEXTUAL_PROFILE_LEVEL]: contextLevel, + [CONTEXTUAL_PROFILE_ID]: profileId, + }; + + this.reportEvent(CONTEXTUAL_PROFILE_RESOLVED_EVENT_TYPE, eventData); + } } diff --git a/test/functional/apps/discover/context_awareness/_telemetry.ts b/test/functional/apps/discover/context_awareness/_telemetry.ts index 587de698f933..ba3294c3dd25 100644 --- a/test/functional/apps/discover/context_awareness/_telemetry.ts +++ b/test/functional/apps/discover/context_awareness/_telemetry.ts @@ -121,7 +121,99 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - describe('events', () => { + describe('contextual profiles', () => { + before(async () => { + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover'); + }); + + after(async () => { + await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover'); + }); + + it('should send EBT events when a different data source profile gets resolved', async () => { + await common.navigateToApp('discover'); + await discover.selectTextBaseLang(); + await discover.waitUntilSearchingHasFinished(); + await monacoEditor.setCodeEditorValue('from my-example-logs | sort @timestamp desc'); + await ebtUIHelper.setOptIn(true); // starts the recording of events from this moment + await testSubjects.click('querySubmitButton'); + await header.waitUntilLoadingHasFinished(); + await discover.waitUntilSearchingHasFinished(); + + let events = await ebtUIHelper.getEvents(Number.MAX_SAFE_INTEGER, { + eventTypes: ['discover_profile_resolved'], + withTimeoutMs: 500, + }); + + // root profile stays the same as it's not changing after switching to ES|QL mode + + // but the data source profile should change because of the different data source + expect(events[0].properties).to.eql({ + contextLevel: 'dataSourceLevel', + profileId: 'example-data-source-profile', + }); + + // should not trigger any new events after a simple refresh + await testSubjects.click('querySubmitButton'); + await header.waitUntilLoadingHasFinished(); + await discover.waitUntilSearchingHasFinished(); + + events = await ebtUIHelper.getEvents(Number.MAX_SAFE_INTEGER, { + eventTypes: ['discover_profile_resolved'], + withTimeoutMs: 500, + }); + + expect(events.length).to.be(1); + + // should detect a new data source profile when switching to a different data source + await monacoEditor.setCodeEditorValue('from my-example-* | sort @timestamp desc'); + await testSubjects.click('querySubmitButton'); + await header.waitUntilLoadingHasFinished(); + await discover.waitUntilSearchingHasFinished(); + + events = await ebtUIHelper.getEvents(Number.MAX_SAFE_INTEGER, { + eventTypes: ['discover_profile_resolved'], + withTimeoutMs: 500, + }); + + expect(events[1].properties).to.eql({ + contextLevel: 'dataSourceLevel', + profileId: 'default-data-source-profile', + }); + + expect(events.length).to.be(2); + }); + + it('should send EBT events when a different document profile gets resolved', async () => { + await common.navigateToApp('discover'); + await discover.selectTextBaseLang(); + await monacoEditor.setCodeEditorValue('from my-example-* | sort @timestamp desc'); + await testSubjects.click('querySubmitButton'); + await header.waitUntilLoadingHasFinished(); + await discover.waitUntilSearchingHasFinished(); + + await ebtUIHelper.setOptIn(true); // starts the recording of events from this moment + + // should trigger a new event after opening the doc viewer + await dataGrid.clickRowToggle(); + await discover.isShowingDocViewer(); + + const events = await ebtUIHelper.getEvents(Number.MAX_SAFE_INTEGER, { + eventTypes: ['discover_profile_resolved'], + withTimeoutMs: 500, + }); + + expect(events.length).to.be(1); + + expect(events[0].properties).to.eql({ + contextLevel: 'documentLevel', + profileId: 'default-document-profile', + }); + }); + }); + + describe('field usage events', () => { beforeEach(async () => { await common.navigateToApp('discover'); await header.waitUntilLoadingHasFinished(); diff --git a/x-pack/test_serverless/functional/test_suites/observability/discover/context_awareness/telemetry/_telemetry.ts b/x-pack/test_serverless/functional/test_suites/observability/discover/context_awareness/telemetry/_telemetry.ts index cc0b7c25abb3..56e900e87f58 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/discover/context_awareness/telemetry/_telemetry.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/discover/context_awareness/telemetry/_telemetry.ts @@ -123,6 +123,111 @@ export default function ({ getService, getPageObjects }: ObservabilityTelemetryF }); }); + describe('contextual profiles', () => { + before(async () => { + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover'); + }); + + after(async () => { + await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover'); + }); + + it('should send EBT events when a different data source profile gets resolved', async () => { + await common.navigateToApp('discover'); + await discover.selectTextBaseLang(); + await discover.waitUntilSearchingHasFinished(); + await monacoEditor.setCodeEditorValue('from my-example-logs | sort @timestamp desc'); + await ebtUIHelper.setOptIn(true); // starts the recording of events from this moment + await testSubjects.click('querySubmitButton'); + await header.waitUntilLoadingHasFinished(); + await discover.waitUntilSearchingHasFinished(); + + let events = await ebtUIHelper.getEvents(Number.MAX_SAFE_INTEGER, { + eventTypes: ['discover_profile_resolved'], + withTimeoutMs: 500, + }); + + expect(events[0].properties).to.eql({ + contextLevel: 'rootLevel', + profileId: 'observability-root-profile', + }); + + expect(events[1].properties).to.eql({ + contextLevel: 'dataSourceLevel', + profileId: 'default-data-source-profile', + }); + + expect(events[2].properties).to.eql({ + contextLevel: 'dataSourceLevel', + profileId: 'observability-logs-data-source-profile', + }); + + // should not trigger any new events after a simple refresh + await testSubjects.click('querySubmitButton'); + await header.waitUntilLoadingHasFinished(); + await discover.waitUntilSearchingHasFinished(); + + events = await ebtUIHelper.getEvents(Number.MAX_SAFE_INTEGER, { + eventTypes: ['discover_profile_resolved'], + withTimeoutMs: 500, + }); + + expect(events.length).to.be(3); + + // should detect a new data source profile when switching to a different data source + await monacoEditor.setCodeEditorValue('from my-example-* | sort @timestamp desc'); + await testSubjects.click('querySubmitButton'); + await header.waitUntilLoadingHasFinished(); + await discover.waitUntilSearchingHasFinished(); + + events = await ebtUIHelper.getEvents(Number.MAX_SAFE_INTEGER, { + eventTypes: ['discover_profile_resolved'], + withTimeoutMs: 500, + }); + + expect(events[3].properties).to.eql({ + contextLevel: 'dataSourceLevel', + profileId: 'default-data-source-profile', + }); + + expect(events.length).to.be(4); + }); + + it('should send EBT events when a different document profile gets resolved', async () => { + await common.navigateToApp('discover'); + await discover.selectTextBaseLang(); + await monacoEditor.setCodeEditorValue('from my-example-logs | sort @timestamp desc'); + await ebtUIHelper.setOptIn(true); // starts the recording of events from this moment + await testSubjects.click('querySubmitButton'); + await header.waitUntilLoadingHasFinished(); + await discover.waitUntilSearchingHasFinished(); + + let events = await ebtUIHelper.getEvents(Number.MAX_SAFE_INTEGER, { + eventTypes: ['discover_profile_resolved'], + withTimeoutMs: 500, + }); + + expect(events.length).to.be(3); + + // should trigger a new event after opening the doc viewer + await dataGrid.clickRowToggle(); + await discover.isShowingDocViewer(); + + events = await ebtUIHelper.getEvents(Number.MAX_SAFE_INTEGER, { + eventTypes: ['discover_profile_resolved'], + withTimeoutMs: 500, + }); + + expect(events.length).to.be(4); + + expect(events[events.length - 1].properties).to.eql({ + contextLevel: 'documentLevel', + profileId: 'observability-log-document-profile', + }); + }); + }); + describe('events', () => { beforeEach(async () => { await common.navigateToApp('discover');