mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[EBT] Call optIn(false)
if the telemetry plugin is disabled (#132748)
This commit is contained in:
parent
5798664add
commit
003474c5b4
12 changed files with 292 additions and 126 deletions
|
@ -935,7 +935,7 @@ describe('AnalyticsClient', () => {
|
|||
|
||||
test('Discards events from the internal queue when there are shippers and an opt-in response is false', async () => {
|
||||
const telemetryCounterPromise = lastValueFrom(
|
||||
analyticsClient.telemetryCounter$.pipe(take(3), toArray()) // Waiting for 3 enqueued
|
||||
analyticsClient.telemetryCounter$.pipe(take(4), toArray()) // Waiting for 4 enqueued
|
||||
);
|
||||
|
||||
// Send multiple events of 1 type to test the grouping logic as well
|
||||
|
@ -947,9 +947,12 @@ describe('AnalyticsClient', () => {
|
|||
analyticsClient.registerShipper(MockedShipper1, { reportEventsMock });
|
||||
analyticsClient.optIn({ global: { enabled: false } });
|
||||
|
||||
// Report event after opted-out
|
||||
analyticsClient.reportEvent('event-type-a', { a_field: 'c' });
|
||||
|
||||
expect(reportEventsMock).toHaveBeenCalledTimes(0);
|
||||
|
||||
// Expect 2 enqueued, but not shipped
|
||||
// Expect 4 enqueued, but not shipped
|
||||
await expect(telemetryCounterPromise).resolves.toEqual([
|
||||
{
|
||||
type: 'enqueued',
|
||||
|
@ -972,7 +975,68 @@ describe('AnalyticsClient', () => {
|
|||
code: 'enqueued',
|
||||
count: 1,
|
||||
},
|
||||
{
|
||||
type: 'enqueued',
|
||||
source: 'client',
|
||||
event_type: 'event-type-a',
|
||||
code: 'enqueued',
|
||||
count: 1,
|
||||
},
|
||||
]);
|
||||
|
||||
// eslint-disable-next-line dot-notation
|
||||
expect(analyticsClient['internalEventQueue$'].observed).toBe(false);
|
||||
});
|
||||
|
||||
test('Discards events from the internal queue when there are no shippers and an opt-in response is false', async () => {
|
||||
const telemetryCounterPromise = lastValueFrom(
|
||||
analyticsClient.telemetryCounter$.pipe(take(4), toArray()) // Waiting for 4 enqueued
|
||||
);
|
||||
|
||||
// Send multiple events of 1 type to test the grouping logic as well
|
||||
analyticsClient.reportEvent('event-type-a', { a_field: 'a' });
|
||||
analyticsClient.reportEvent('event-type-b', { b_field: 100 });
|
||||
analyticsClient.reportEvent('event-type-a', { a_field: 'b' });
|
||||
|
||||
analyticsClient.optIn({ global: { enabled: false } });
|
||||
|
||||
// Report event after opted-out
|
||||
analyticsClient.reportEvent('event-type-a', { a_field: 'c' });
|
||||
|
||||
// Expect 4 enqueued, but not shipped
|
||||
await expect(telemetryCounterPromise).resolves.toEqual([
|
||||
{
|
||||
type: 'enqueued',
|
||||
source: 'client',
|
||||
event_type: 'event-type-a',
|
||||
code: 'enqueued',
|
||||
count: 1,
|
||||
},
|
||||
{
|
||||
type: 'enqueued',
|
||||
source: 'client',
|
||||
event_type: 'event-type-b',
|
||||
code: 'enqueued',
|
||||
count: 1,
|
||||
},
|
||||
{
|
||||
type: 'enqueued',
|
||||
source: 'client',
|
||||
event_type: 'event-type-a',
|
||||
code: 'enqueued',
|
||||
count: 1,
|
||||
},
|
||||
{
|
||||
type: 'enqueued',
|
||||
source: 'client',
|
||||
event_type: 'event-type-a',
|
||||
code: 'enqueued',
|
||||
count: 1,
|
||||
},
|
||||
]);
|
||||
|
||||
// eslint-disable-next-line dot-notation
|
||||
expect(analyticsClient['internalEventQueue$'].observed).toBe(false);
|
||||
});
|
||||
|
||||
test(
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import type { Observable } from 'rxjs';
|
||||
import { BehaviorSubject, Subject, combineLatest, from } from 'rxjs';
|
||||
import { BehaviorSubject, Subject, combineLatest, from, merge } from 'rxjs';
|
||||
import {
|
||||
buffer,
|
||||
bufferCount,
|
||||
|
@ -267,7 +267,11 @@ export class AnalyticsClient implements IAnalyticsClient {
|
|||
// Observer that will emit when both events occur: the OptInConfig is set + a shipper has been registered
|
||||
const configReceivedAndShipperReceivedObserver$ = combineLatest([
|
||||
this.optInConfigWithReplay$,
|
||||
this.shipperRegistered$,
|
||||
merge([
|
||||
this.shipperRegistered$,
|
||||
// Merging shipperRegistered$ with the optInConfigWithReplay$ when optedIn is false, so that we don't need to wait for the shipper if opted-in === false
|
||||
this.optInConfigWithReplay$.pipe(filter((cfg) => cfg?.isOptedIn() === false)),
|
||||
]),
|
||||
]);
|
||||
|
||||
// Flush the internal queue when we get any optInConfig and, at least, 1 shipper
|
||||
|
|
|
@ -10,5 +10,7 @@
|
|||
"requiredPlugins": [
|
||||
"usageCollection"
|
||||
],
|
||||
"optionalPlugins": []
|
||||
"optionalPlugins": [
|
||||
"telemetry"
|
||||
]
|
||||
}
|
||||
|
|
39
src/plugins/kibana_usage_collection/public/plugin.test.ts
Normal file
39
src/plugins/kibana_usage_collection/public/plugin.test.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { coreMock } from '@kbn/core/public/mocks';
|
||||
import { usageCollectionPluginMock } from '@kbn/usage-collection-plugin/public/mocks';
|
||||
import { telemetryPluginMock } from '@kbn/telemetry-plugin/public/mocks';
|
||||
import { plugin } from '.';
|
||||
|
||||
describe('kibana_usage_collection/public', () => {
|
||||
const pluginInstance = plugin();
|
||||
|
||||
describe('optIn fallback from telemetry', () => {
|
||||
test('should call optIn(false) when telemetry is disabled', () => {
|
||||
const coreSetup = coreMock.createSetup();
|
||||
const usageCollectionMock = usageCollectionPluginMock.createSetupContract();
|
||||
|
||||
expect(pluginInstance.setup(coreSetup, { usageCollection: usageCollectionMock })).toBe(
|
||||
undefined
|
||||
);
|
||||
expect(coreSetup.analytics.optIn).toHaveBeenCalledWith({ global: { enabled: false } });
|
||||
});
|
||||
|
||||
test('should NOT call optIn(false) when telemetry is enabled', () => {
|
||||
const coreSetup = coreMock.createSetup();
|
||||
const usageCollectionMock = usageCollectionPluginMock.createSetupContract();
|
||||
const telemetry = telemetryPluginMock.createSetupContract();
|
||||
|
||||
expect(
|
||||
pluginInstance.setup(coreSetup, { usageCollection: usageCollectionMock, telemetry })
|
||||
).toBe(undefined);
|
||||
expect(coreSetup.analytics.optIn).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -8,14 +8,23 @@
|
|||
|
||||
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
||||
import type { CoreSetup, Plugin } from '@kbn/core/public';
|
||||
import type { TelemetryPluginSetup } from '@kbn/telemetry-plugin/public';
|
||||
import { registerEbtCounters } from './ebt_counters';
|
||||
|
||||
interface KibanaUsageCollectionPluginsDepsSetup {
|
||||
usageCollection: UsageCollectionSetup;
|
||||
telemetry?: TelemetryPluginSetup;
|
||||
}
|
||||
|
||||
export class KibanaUsageCollectionPlugin implements Plugin {
|
||||
public setup(coreSetup: CoreSetup, { usageCollection }: KibanaUsageCollectionPluginsDepsSetup) {
|
||||
public setup(
|
||||
coreSetup: CoreSetup,
|
||||
{ usageCollection, telemetry }: KibanaUsageCollectionPluginsDepsSetup
|
||||
) {
|
||||
if (!telemetry) {
|
||||
// If the telemetry plugin is disabled, let's set optIn false to flush the queues.
|
||||
coreSetup.analytics.optIn({ global: { enabled: false } });
|
||||
}
|
||||
registerEbtCounters(coreSetup.analytics, usageCollection);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,11 +15,13 @@ import {
|
|||
CollectorOptions,
|
||||
createUsageCollectionSetupMock,
|
||||
} from '@kbn/usage-collection-plugin/server/mocks';
|
||||
import { telemetryPluginMock } from '@kbn/telemetry-plugin/server/mocks';
|
||||
import { cloudDetailsMock, registerEbtCountersMock } from './plugin.test.mocks';
|
||||
import { plugin } from '.';
|
||||
|
||||
describe('kibana_usage_collection', () => {
|
||||
const pluginInstance = plugin(coreMock.createPluginInitializerContext({}));
|
||||
const telemetry = telemetryPluginMock.createSetupContract();
|
||||
|
||||
const usageCollectors: CollectorOptions[] = [];
|
||||
|
||||
|
@ -141,4 +143,26 @@ describe('kibana_usage_collection', () => {
|
|||
test('Runs the stop method without issues', () => {
|
||||
expect(pluginInstance.stop()).toBe(undefined);
|
||||
});
|
||||
|
||||
describe('optIn fallback from telemetry', () => {
|
||||
test('should call optIn(false) when telemetry is disabled', () => {
|
||||
const coreSetup = coreMock.createSetup();
|
||||
const usageCollectionMock = createUsageCollectionSetupMock();
|
||||
|
||||
expect(pluginInstance.setup(coreSetup, { usageCollection: usageCollectionMock })).toBe(
|
||||
undefined
|
||||
);
|
||||
expect(coreSetup.analytics.optIn).toHaveBeenCalledWith({ global: { enabled: false } });
|
||||
});
|
||||
|
||||
test('should NOT call optIn(false) when telemetry is enabled', () => {
|
||||
const coreSetup = coreMock.createSetup();
|
||||
const usageCollectionMock = createUsageCollectionSetupMock();
|
||||
|
||||
expect(
|
||||
pluginInstance.setup(coreSetup, { usageCollection: usageCollectionMock, telemetry })
|
||||
).toBe(undefined);
|
||||
expect(coreSetup.analytics.optIn).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
import type { UsageCollectionSetup, UsageCounter } from '@kbn/usage-collection-plugin/server';
|
||||
import type { TelemetryPluginSetup } from '@kbn/telemetry-plugin/server';
|
||||
import { Subject } from 'rxjs';
|
||||
import type {
|
||||
PluginInitializerContext,
|
||||
|
@ -47,6 +48,7 @@ import {
|
|||
|
||||
interface KibanaUsageCollectionPluginsDepsSetup {
|
||||
usageCollection: UsageCollectionSetup;
|
||||
telemetry?: TelemetryPluginSetup;
|
||||
}
|
||||
|
||||
type SavedObjectsRegisterType = SavedObjectsServiceSetup['registerType'];
|
||||
|
@ -68,7 +70,14 @@ export class KibanaUsageCollectionPlugin implements Plugin {
|
|||
this.instanceUuid = initializerContext.env.instanceUuid;
|
||||
}
|
||||
|
||||
public setup(coreSetup: CoreSetup, { usageCollection }: KibanaUsageCollectionPluginsDepsSetup) {
|
||||
public setup(
|
||||
coreSetup: CoreSetup,
|
||||
{ usageCollection, telemetry }: KibanaUsageCollectionPluginsDepsSetup
|
||||
) {
|
||||
if (!telemetry) {
|
||||
// If the telemetry plugin is disabled, let's set optIn false to flush the queues.
|
||||
coreSetup.analytics.optIn({ global: { enabled: false } });
|
||||
}
|
||||
registerEbtCounters(coreSetup.analytics, usageCollection);
|
||||
usageCollection.createUsageCounter('uiCounters');
|
||||
this.eventLoopUsageCounter = usageCollection.createUsageCounter('eventLoop');
|
||||
|
|
|
@ -16,5 +16,6 @@
|
|||
"references": [
|
||||
{ "path": "../../core/tsconfig.json" },
|
||||
{ "path": "../../plugins/usage_collection/tsconfig.json" },
|
||||
{ "path": "../../plugins/telemetry/tsconfig.json" },
|
||||
]
|
||||
}
|
||||
|
|
|
@ -70,7 +70,11 @@ export class AnalyticsPluginAPlugin implements Plugin {
|
|||
|
||||
return res.ok({
|
||||
body: stats
|
||||
.filter((counter) => counter.event_type === eventType)
|
||||
.filter(
|
||||
(counter) =>
|
||||
counter.event_type === eventType &&
|
||||
['client', 'FTR-shipper'].includes(counter.source)
|
||||
)
|
||||
.slice(-takeNumberOfCounters),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -34,8 +34,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
...functionalConfig.get('kbnTestServer'),
|
||||
serverArgs: [
|
||||
...functionalConfig.get('kbnTestServer.serverArgs'),
|
||||
// Disabling telemetry, so it doesn't call opt-in before the tests run.
|
||||
'--telemetry.enabled=false',
|
||||
'--telemetry.optIn=true',
|
||||
`--plugin-path=${path.resolve(__dirname, './__fixtures__/plugins/analytics_plugin_a')}`,
|
||||
`--plugin-path=${path.resolve(__dirname, './__fixtures__/plugins/analytics_ftr_helpers')}`,
|
||||
],
|
||||
|
|
|
@ -24,7 +24,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
return await browser.execute(
|
||||
({ takeNumberOfCounters }) =>
|
||||
window.__analyticsPluginA__.stats
|
||||
.filter((counter) => counter.event_type === 'test-plugin-lifecycle')
|
||||
.filter(
|
||||
(counter) =>
|
||||
counter.event_type === 'test-plugin-lifecycle' &&
|
||||
['client', 'FTR-shipper'].includes(counter.source)
|
||||
)
|
||||
.slice(-takeNumberOfCounters),
|
||||
{ takeNumberOfCounters: _takeNumberOfCounters }
|
||||
);
|
||||
|
@ -36,13 +40,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
);
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
before(async () => {
|
||||
await common.navigateToApp('home');
|
||||
});
|
||||
|
||||
// this test should run first because it depends on optInConfig being undefined
|
||||
it('should have internally enqueued the "lifecycle" events but not handed over to the shipper yet', async () => {
|
||||
const telemetryCounters = await getTelemetryCounters(2);
|
||||
it('should see both events enqueued and sent to the shipper', async () => {
|
||||
const telemetryCounters = await getTelemetryCounters(5);
|
||||
expect(telemetryCounters).to.eql([
|
||||
{
|
||||
type: 'enqueued',
|
||||
|
@ -58,83 +61,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
code: 'enqueued',
|
||||
count: 1,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('after setting opt-in, it should extend the contexts and send the events', async () => {
|
||||
await ebtUIHelper.setOptIn(true);
|
||||
|
||||
const actions = await getActions();
|
||||
|
||||
const [_, extendContextAction, ...reportEventsActions] = actions;
|
||||
|
||||
// Validating the remote user_agent because that's the only field that it's added by the FTR plugin.
|
||||
const context = extendContextAction.meta;
|
||||
expect(context).to.have.property('user_agent');
|
||||
expect(context.user_agent).to.be.a('string');
|
||||
|
||||
reportEventsActions.forEach((reportEventAction) => {
|
||||
expect(reportEventAction.action).to.eql('reportEvents');
|
||||
// Get the first event type
|
||||
const initiallyBatchedEventType = reportEventAction.meta[0].event_type;
|
||||
// Check that all event types in this batch are the same.
|
||||
reportEventAction.meta.forEach((event: Event) => {
|
||||
expect(event.event_type).to.eql(initiallyBatchedEventType);
|
||||
});
|
||||
});
|
||||
|
||||
// Find the action calling to report test-plugin-lifecycle events.
|
||||
const reportTestPluginLifecycleEventsAction = reportEventsActions.find(
|
||||
(reportEventAction) => {
|
||||
return (
|
||||
reportEventAction.action === 'reportEvents' &&
|
||||
reportEventAction.meta[0].event_type === 'test-plugin-lifecycle'
|
||||
);
|
||||
}
|
||||
);
|
||||
// Some context providers emit very early. We are OK with that.
|
||||
const initialContext = reportTestPluginLifecycleEventsAction!.meta[0].context;
|
||||
|
||||
const reportEventContext = reportTestPluginLifecycleEventsAction!.meta[1].context;
|
||||
|
||||
const setupEvent = reportTestPluginLifecycleEventsAction!.meta.findIndex(
|
||||
(event: Event) =>
|
||||
event.event_type === 'test-plugin-lifecycle' &&
|
||||
event.properties.plugin === 'analyticsPluginA' &&
|
||||
event.properties.step === 'setup'
|
||||
);
|
||||
|
||||
const startEvent = reportTestPluginLifecycleEventsAction!.meta.findIndex(
|
||||
(event: Event) =>
|
||||
event.event_type === 'test-plugin-lifecycle' &&
|
||||
event.properties.plugin === 'analyticsPluginA' &&
|
||||
event.properties.step === 'start'
|
||||
);
|
||||
|
||||
expect(setupEvent).to.be.greaterThan(-1);
|
||||
expect(startEvent).to.be.greaterThan(setupEvent);
|
||||
|
||||
expect(reportEventContext).to.have.property('user_agent');
|
||||
expect(reportEventContext.user_agent).to.be.a('string');
|
||||
|
||||
// Testing the FTR helper as well
|
||||
expect(await ebtUIHelper.getLastEvents(2, ['test-plugin-lifecycle'])).to.eql([
|
||||
{
|
||||
timestamp: reportTestPluginLifecycleEventsAction!.meta[setupEvent].timestamp,
|
||||
event_type: 'test-plugin-lifecycle',
|
||||
context: initialContext,
|
||||
properties: { plugin: 'analyticsPluginA', step: 'setup' },
|
||||
},
|
||||
{
|
||||
timestamp: reportTestPluginLifecycleEventsAction!.meta[startEvent].timestamp,
|
||||
event_type: 'test-plugin-lifecycle',
|
||||
context: reportEventContext,
|
||||
properties: { plugin: 'analyticsPluginA', step: 'start' },
|
||||
},
|
||||
]);
|
||||
|
||||
const telemetryCounters = await getTelemetryCounters(3);
|
||||
expect(telemetryCounters).to.eql([
|
||||
{
|
||||
type: 'succeeded',
|
||||
event_type: 'test-plugin-lifecycle',
|
||||
|
@ -158,5 +84,95 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
},
|
||||
]);
|
||||
});
|
||||
|
||||
describe('after setting opt-in', () => {
|
||||
let actions: Action[];
|
||||
let context: Action['meta'];
|
||||
|
||||
before(async () => {
|
||||
actions = await getActions();
|
||||
context = actions[1].meta;
|
||||
});
|
||||
|
||||
it('it should extend the contexts with pid injected by "analytics_plugin_a"', () => {
|
||||
// Validating the remote user_agent because that's the only field that it's added by the FTR plugin.
|
||||
expect(context).to.have.property('user_agent');
|
||||
expect(context.user_agent).to.be.a('string');
|
||||
});
|
||||
|
||||
it('it calls optIn first, then extendContext, followed by reportEvents', async () => {
|
||||
const [optInAction, extendContextAction, ...reportEventsAction] = actions;
|
||||
expect(optInAction).to.eql({ action: 'optIn', meta: true });
|
||||
expect(extendContextAction).to.eql({ action: 'extendContext', meta: context });
|
||||
while (reportEventsAction[0].action === 'extendContext') {
|
||||
// it could happen that a context provider emits a bit delayed
|
||||
reportEventsAction.shift();
|
||||
}
|
||||
reportEventsAction.forEach((entry) => expect(entry.action).to.eql('reportEvents'));
|
||||
});
|
||||
|
||||
it('Initial calls to reportEvents from cached events group the requests by event_type', async () => {
|
||||
// We know that after opting-in, the client will send the events in batches, grouped by event-type.
|
||||
const reportEventsActions = actions.filter(({ action }) => action === 'reportEvents');
|
||||
reportEventsActions.forEach((reportEventAction) => {
|
||||
// Get the first event type
|
||||
const initiallyBatchedEventType = reportEventAction.meta[0].event_type;
|
||||
// Check that all event types in this batch are the same.
|
||||
reportEventAction.meta.forEach((event: Event) => {
|
||||
expect(event.event_type).to.eql(initiallyBatchedEventType);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('"test-plugin-lifecycle" is received in the expected order of "setup" first, then "start"', async () => {
|
||||
// We know that after opting-in, the client will send the events in batches, grouped by event-type.
|
||||
const reportEventsActions = actions.filter(({ action }) => action === 'reportEvents');
|
||||
// Find the action calling to report test-plugin-lifecycle events.
|
||||
const reportTestPluginLifecycleEventsAction = reportEventsActions.find(
|
||||
(reportEventAction) => {
|
||||
return (
|
||||
reportEventAction.action === 'reportEvents' &&
|
||||
reportEventAction.meta[0].event_type === 'test-plugin-lifecycle'
|
||||
);
|
||||
}
|
||||
);
|
||||
// Find the setup and start events and validate that they are sent in the correct order.
|
||||
const initialContext = reportTestPluginLifecycleEventsAction!.meta[0].context; // read this from the reportTestPlugin
|
||||
const reportEventContext = reportTestPluginLifecycleEventsAction!.meta[1].context;
|
||||
const setupEvent = reportTestPluginLifecycleEventsAction!.meta.findIndex(
|
||||
(event: Event) =>
|
||||
event.event_type === 'test-plugin-lifecycle' &&
|
||||
event.properties.plugin === 'analyticsPluginA' &&
|
||||
event.properties.step === 'setup'
|
||||
);
|
||||
|
||||
const startEvent = reportTestPluginLifecycleEventsAction!.meta.findIndex(
|
||||
(event: Event) =>
|
||||
event.event_type === 'test-plugin-lifecycle' &&
|
||||
event.properties.plugin === 'analyticsPluginA' &&
|
||||
event.properties.step === 'start'
|
||||
);
|
||||
|
||||
expect(setupEvent).to.be.greaterThan(-1);
|
||||
expect(startEvent).to.be.greaterThan(setupEvent);
|
||||
|
||||
// This helps us to also test the helpers
|
||||
const events = await ebtUIHelper.getLastEvents(2, ['test-plugin-lifecycle']);
|
||||
expect(events).to.eql([
|
||||
{
|
||||
timestamp: reportTestPluginLifecycleEventsAction!.meta[setupEvent].timestamp,
|
||||
event_type: 'test-plugin-lifecycle',
|
||||
context: initialContext,
|
||||
properties: { plugin: 'analyticsPluginA', step: 'setup' },
|
||||
},
|
||||
{
|
||||
timestamp: reportTestPluginLifecycleEventsAction!.meta[startEvent].timestamp,
|
||||
event_type: 'test-plugin-lifecycle',
|
||||
context: reportEventContext,
|
||||
properties: { plugin: 'analyticsPluginA', step: 'start' },
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -37,9 +37,8 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
};
|
||||
|
||||
describe('analytics service: server side', () => {
|
||||
// this test should run first because it depends on optInConfig being undefined
|
||||
it('should have internally enqueued the "lifecycle" events but not handed over to the shipper yet', async () => {
|
||||
const telemetryCounters = await getTelemetryCounters(2);
|
||||
it('should see both events enqueued and sent to the shipper', async () => {
|
||||
const telemetryCounters = await getTelemetryCounters(5);
|
||||
expect(telemetryCounters).to.eql([
|
||||
{
|
||||
type: 'enqueued',
|
||||
|
@ -55,6 +54,27 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
code: 'enqueued',
|
||||
count: 1,
|
||||
},
|
||||
{
|
||||
type: 'succeeded',
|
||||
event_type: 'test-plugin-lifecycle',
|
||||
source: 'FTR-shipper',
|
||||
code: '200',
|
||||
count: 1,
|
||||
},
|
||||
{
|
||||
type: 'succeeded',
|
||||
event_type: 'test-plugin-lifecycle',
|
||||
source: 'FTR-shipper',
|
||||
code: '200',
|
||||
count: 1,
|
||||
},
|
||||
{
|
||||
type: 'sent_to_shipper',
|
||||
event_type: 'test-plugin-lifecycle',
|
||||
source: 'client',
|
||||
code: 'OK',
|
||||
count: 2,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
|
@ -63,7 +83,6 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
let context: Action['meta'];
|
||||
|
||||
before(async () => {
|
||||
await ebtServerHelper.setOptIn(true);
|
||||
actions = await getActions();
|
||||
context = actions[1].meta;
|
||||
});
|
||||
|
@ -78,14 +97,17 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
const [optInAction, extendContextAction, ...reportEventsAction] = actions;
|
||||
expect(optInAction).to.eql({ action: 'optIn', meta: true });
|
||||
expect(extendContextAction).to.eql({ action: 'extendContext', meta: context });
|
||||
while (reportEventsAction[0].action === 'extendContext') {
|
||||
// it could happen that a context provider emits a bit delayed
|
||||
reportEventsAction.shift();
|
||||
}
|
||||
reportEventsAction.forEach((entry) => expect(entry.action).to.eql('reportEvents'));
|
||||
});
|
||||
|
||||
it('Initial calls to reportEvents from cached events group the requests by event_type', async () => {
|
||||
// We know that after opting-in, the client will send the events in batches, grouped by event-type.
|
||||
const [, , ...reportEventsActions] = actions;
|
||||
const reportEventsActions = actions.filter(({ action }) => action === 'reportEvents');
|
||||
reportEventsActions.forEach((reportEventAction) => {
|
||||
expect(reportEventAction.action).to.eql('reportEvents');
|
||||
// Get the first event type
|
||||
const initiallyBatchedEventType = reportEventAction.meta[0].event_type;
|
||||
// Check that all event types in this batch are the same.
|
||||
|
@ -97,7 +119,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
|
||||
it('"test-plugin-lifecycle" is received in the expected order of "setup" first, then "start"', async () => {
|
||||
// We know that after opting-in, the client will send the events in batches, grouped by event-type.
|
||||
const [, , ...reportEventsActions] = actions;
|
||||
const reportEventsActions = actions.filter(({ action }) => action === 'reportEvents');
|
||||
// Find the action calling to report test-plugin-lifecycle events.
|
||||
const reportTestPluginLifecycleEventsAction = reportEventsActions.find(
|
||||
(reportEventAction) => {
|
||||
|
@ -144,33 +166,6 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should report the plugin lifecycle events as telemetry counters', async () => {
|
||||
const telemetryCounters = await getTelemetryCounters(3);
|
||||
expect(telemetryCounters).to.eql([
|
||||
{
|
||||
type: 'succeeded',
|
||||
event_type: 'test-plugin-lifecycle',
|
||||
source: 'FTR-shipper',
|
||||
code: '200',
|
||||
count: 1,
|
||||
},
|
||||
{
|
||||
type: 'succeeded',
|
||||
event_type: 'test-plugin-lifecycle',
|
||||
source: 'FTR-shipper',
|
||||
code: '200',
|
||||
count: 1,
|
||||
},
|
||||
{
|
||||
type: 'sent_to_shipper',
|
||||
event_type: 'test-plugin-lifecycle',
|
||||
source: 'client',
|
||||
code: 'OK',
|
||||
count: 2,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue