diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/constants.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/constants.ts index 1753c87c9d005..d6201deff5fec 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/constants.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/constants.ts @@ -35,3 +35,23 @@ export const MONITOR_EVENT_LOOP_DELAYS_START = 1 * 60 * 1000; * Event loop monitoring sampling rate in milliseconds. */ export const MONITOR_EVENT_LOOP_DELAYS_RESOLUTION = 10; + +/** + * Mean event loop delay threshold for logging a warning. + */ +export const MONITOR_EVENT_LOOP_WARN_THRESHOLD = 350; + +/** + * Start monitoring the event loop threshold after 1 minute + */ +export const MONITOR_EVENT_LOOP_THRESHOLD_START = 1 * 60 * 1000; + +/** + * Check the event loop utilization every 30 seconds + */ +export const MONITOR_EVENT_LOOP_THRESHOLD_INTERVAL = 30 * 1000; + +/** + * Nanosecond to milisecond conversion unit + */ +export const ONE_MILLISECOND_AS_NANOSECONDS = 1000000; diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.mocks.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.mocks.ts index 6b03d3cc5cbd1..f266a27a7034f 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.mocks.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.mocks.ts @@ -17,6 +17,7 @@ export const monitorEventLoopDelay = jest.fn().mockReturnValue({ percentile: mockMonitorPercentile, disable: mockMonitorDisable, reset: mockMonitorReset, + ...createMockHistogram(), }); jest.doMock('perf_hooks', () => ({ diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.test.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.test.ts index d03236a9756b3..b40030e210176 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.test.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.test.ts @@ -6,8 +6,6 @@ * Side Public License, v 1. */ -import { Subject } from 'rxjs'; - import { mockMonitorEnable, mockMonitorPercentile, @@ -15,8 +13,7 @@ import { mockMonitorReset, mockMonitorDisable, } from './event_loop_delays.mocks'; -import { savedObjectsRepositoryMock } from '../../../../../core/server/mocks'; -import { startTrackingEventLoopDelaysUsage, EventLoopDelaysCollector } from './event_loop_delays'; +import { EventLoopDelaysCollector } from './event_loop_delays'; describe('EventLoopDelaysCollector', () => { jest.useFakeTimers('modern'); @@ -64,72 +61,3 @@ describe('EventLoopDelaysCollector', () => { expect(mockMonitorDisable).toBeCalledTimes(1); }); }); - -describe('startTrackingEventLoopDelaysUsage', () => { - const mockInternalRepository = savedObjectsRepositoryMock.create(); - const stopMonitoringEventLoop$ = new Subject(); - - beforeAll(() => jest.useFakeTimers('modern')); - beforeEach(() => jest.clearAllMocks()); - afterEach(() => stopMonitoringEventLoop$.next()); - - it('initializes EventLoopDelaysCollector and starts timer', () => { - const collectionStartDelay = 1000; - startTrackingEventLoopDelaysUsage( - mockInternalRepository, - stopMonitoringEventLoop$, - collectionStartDelay - ); - - expect(monitorEventLoopDelay).toBeCalledTimes(1); - expect(mockMonitorPercentile).toBeCalledTimes(0); - jest.advanceTimersByTime(collectionStartDelay); - expect(mockMonitorPercentile).toBeCalled(); - }); - - it('stores event loop delays every collectionInterval duration', () => { - const collectionStartDelay = 100; - const collectionInterval = 1000; - startTrackingEventLoopDelaysUsage( - mockInternalRepository, - stopMonitoringEventLoop$, - collectionStartDelay, - collectionInterval - ); - - expect(mockInternalRepository.create).toBeCalledTimes(0); - jest.advanceTimersByTime(collectionStartDelay); - expect(mockInternalRepository.create).toBeCalledTimes(1); - jest.advanceTimersByTime(collectionInterval); - expect(mockInternalRepository.create).toBeCalledTimes(2); - jest.advanceTimersByTime(collectionInterval); - expect(mockInternalRepository.create).toBeCalledTimes(3); - }); - - it('resets histogram every histogramReset duration', () => { - const collectionStartDelay = 0; - const collectionInterval = 1000; - const histogramReset = 5000; - startTrackingEventLoopDelaysUsage( - mockInternalRepository, - stopMonitoringEventLoop$, - collectionStartDelay, - collectionInterval, - histogramReset - ); - - expect(mockMonitorReset).toBeCalledTimes(0); - jest.advanceTimersByTime(collectionInterval * 5); - expect(mockMonitorReset).toBeCalledTimes(1); - jest.advanceTimersByTime(collectionInterval * 5); - expect(mockMonitorReset).toBeCalledTimes(2); - }); - - it('stops monitoring event loop delays once stopMonitoringEventLoop$.next is called', () => { - startTrackingEventLoopDelaysUsage(mockInternalRepository, stopMonitoringEventLoop$); - - expect(mockMonitorDisable).toBeCalledTimes(0); - stopMonitoringEventLoop$.next(); - expect(mockMonitorDisable).toBeCalledTimes(1); - }); -}); diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.ts index 655cba580fc5d..f5de44a061d5a 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.ts @@ -8,16 +8,7 @@ import type { EventLoopDelayMonitor } from 'perf_hooks'; import { monitorEventLoopDelay } from 'perf_hooks'; -import { takeUntil, finalize, map } from 'rxjs/operators'; -import { Observable, timer } from 'rxjs'; -import type { ISavedObjectsRepository } from 'kibana/server'; -import { - MONITOR_EVENT_LOOP_DELAYS_START, - MONITOR_EVENT_LOOP_DELAYS_INTERVAL, - MONITOR_EVENT_LOOP_DELAYS_RESET, - MONITOR_EVENT_LOOP_DELAYS_RESOLUTION, -} from './constants'; -import { storeHistogram } from './saved_objects'; +import { MONITOR_EVENT_LOOP_DELAYS_RESOLUTION } from './constants'; export interface IntervalHistogram { fromTimestamp: string; @@ -77,33 +68,3 @@ export class EventLoopDelaysCollector { this.loopMonitor.disable(); } } - -/** - * The monitoring of the event loop starts immediately. - * The first collection of the histogram happens after 1 minute. - * The daily histogram data is updated every 1 hour. - */ -export function startTrackingEventLoopDelaysUsage( - internalRepository: ISavedObjectsRepository, - stopMonitoringEventLoop$: Observable, - collectionStartDelay = MONITOR_EVENT_LOOP_DELAYS_START, - collectionInterval = MONITOR_EVENT_LOOP_DELAYS_INTERVAL, - histogramReset = MONITOR_EVENT_LOOP_DELAYS_RESET -) { - const eventLoopDelaysCollector = new EventLoopDelaysCollector(); - - const resetOnCount = Math.ceil(histogramReset / collectionInterval); - timer(collectionStartDelay, collectionInterval) - .pipe( - map((i) => (i + 1) % resetOnCount === 0), - takeUntil(stopMonitoringEventLoop$), - finalize(() => eventLoopDelaysCollector.stop()) - ) - .subscribe(async (shouldReset) => { - const histogram = eventLoopDelaysCollector.collect(); - if (shouldReset) { - eventLoopDelaysCollector.reset(); - } - await storeHistogram(histogram, internalRepository); - }); -} diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/index.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/index.ts index 693b173c2759e..17b23e723c804 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/index.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/index.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ -export { startTrackingEventLoopDelaysUsage } from './event_loop_delays'; export { registerEventLoopDelaysCollector } from './event_loop_delays_usage_collector'; +export { startTrackingEventLoopDelaysThreshold } from './track_threshold'; +export { startTrackingEventLoopDelaysUsage } from './track_delays'; export { SAVED_OBJECTS_DAILY_TYPE } from './saved_objects'; diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_delays.test.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_delays.test.ts new file mode 100644 index 0000000000000..e0d8c20ead75a --- /dev/null +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_delays.test.ts @@ -0,0 +1,81 @@ +/* + * 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 { Subject } from 'rxjs'; + +import { + mockMonitorPercentile, + monitorEventLoopDelay, + mockMonitorReset, + mockMonitorDisable, +} from './event_loop_delays.mocks'; +import { savedObjectsRepositoryMock } from '../../../../../core/server/mocks'; +import { startTrackingEventLoopDelaysUsage } from './track_delays'; + +describe('startTrackingEventLoopDelaysUsage', () => { + const mockInternalRepository = savedObjectsRepositoryMock.create(); + const stopMonitoringEventLoop$ = new Subject(); + + beforeAll(() => jest.useFakeTimers('modern')); + beforeEach(() => jest.clearAllMocks()); + afterEach(() => stopMonitoringEventLoop$.next()); + + it('initializes EventLoopDelaysCollector and starts timer', () => { + const collectionStartDelay = 1000; + startTrackingEventLoopDelaysUsage(mockInternalRepository, stopMonitoringEventLoop$, { + collectionStartDelay, + }); + + expect(monitorEventLoopDelay).toBeCalledTimes(1); + expect(mockMonitorPercentile).toBeCalledTimes(0); + jest.advanceTimersByTime(collectionStartDelay); + expect(mockMonitorPercentile).toBeCalled(); + }); + + it('stores event loop delays every collectionInterval duration', () => { + const collectionStartDelay = 100; + const collectionInterval = 1000; + startTrackingEventLoopDelaysUsage(mockInternalRepository, stopMonitoringEventLoop$, { + collectionStartDelay, + collectionInterval, + }); + + expect(mockInternalRepository.create).toBeCalledTimes(0); + jest.advanceTimersByTime(collectionStartDelay); + expect(mockInternalRepository.create).toBeCalledTimes(1); + jest.advanceTimersByTime(collectionInterval); + expect(mockInternalRepository.create).toBeCalledTimes(2); + jest.advanceTimersByTime(collectionInterval); + expect(mockInternalRepository.create).toBeCalledTimes(3); + }); + + it('resets histogram every histogramReset duration', () => { + const collectionStartDelay = 0; + const collectionInterval = 1000; + const histogramReset = 5000; + startTrackingEventLoopDelaysUsage(mockInternalRepository, stopMonitoringEventLoop$, { + collectionStartDelay, + collectionInterval, + histogramReset, + }); + + expect(mockMonitorReset).toBeCalledTimes(0); + jest.advanceTimersByTime(collectionInterval * 5); + expect(mockMonitorReset).toBeCalledTimes(1); + jest.advanceTimersByTime(collectionInterval * 5); + expect(mockMonitorReset).toBeCalledTimes(2); + }); + + it('stops monitoring event loop delays once stopMonitoringEventLoop$.next is called', () => { + startTrackingEventLoopDelaysUsage(mockInternalRepository, stopMonitoringEventLoop$); + + expect(mockMonitorDisable).toBeCalledTimes(0); + stopMonitoringEventLoop$.next(); + expect(mockMonitorDisable).toBeCalledTimes(1); + }); +}); diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_delays.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_delays.ts new file mode 100644 index 0000000000000..70638d3b07cbc --- /dev/null +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_delays.ts @@ -0,0 +1,56 @@ +/* + * 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 { takeUntil, finalize, map } from 'rxjs/operators'; +import { Observable, timer } from 'rxjs'; +import type { ISavedObjectsRepository } from 'kibana/server'; +import { + MONITOR_EVENT_LOOP_DELAYS_START, + MONITOR_EVENT_LOOP_DELAYS_INTERVAL, + MONITOR_EVENT_LOOP_DELAYS_RESET, +} from './constants'; +import { storeHistogram } from './saved_objects'; +import { EventLoopDelaysCollector } from './event_loop_delays'; + +/** + * The monitoring of the event loop starts immediately. + * The first collection of the histogram happens after 1 minute. + * The daily histogram data is updated every 1 hour. + */ +export function startTrackingEventLoopDelaysUsage( + internalRepository: ISavedObjectsRepository, + stopMonitoringEventLoop$: Observable, + configs: { + collectionStartDelay?: number; + collectionInterval?: number; + histogramReset?: number; + } = {} +) { + const { + collectionStartDelay = MONITOR_EVENT_LOOP_DELAYS_START, + collectionInterval = MONITOR_EVENT_LOOP_DELAYS_INTERVAL, + histogramReset = MONITOR_EVENT_LOOP_DELAYS_RESET, + } = configs; + + const eventLoopDelaysCollector = new EventLoopDelaysCollector(); + const resetOnCount = Math.ceil(histogramReset / collectionInterval); + + timer(collectionStartDelay, collectionInterval) + .pipe( + map((i) => (i + 1) % resetOnCount === 0), + takeUntil(stopMonitoringEventLoop$), + finalize(() => eventLoopDelaysCollector.stop()) + ) + .subscribe(async (shouldReset) => { + const histogram = eventLoopDelaysCollector.collect(); + if (shouldReset) { + eventLoopDelaysCollector.reset(); + } + await storeHistogram(histogram, internalRepository); + }); +} diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_threshold.test.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_threshold.test.ts new file mode 100644 index 0000000000000..1ff49a735a775 --- /dev/null +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_threshold.test.ts @@ -0,0 +1,92 @@ +/* + * 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 { Subject } from 'rxjs'; +import { + mockMonitorPercentile, + monitorEventLoopDelay, + mockMonitorReset, +} from './event_loop_delays.mocks'; +import { startTrackingEventLoopDelaysThreshold } from './track_threshold'; +import { loggingSystemMock } from '../../../../../core/server/mocks'; +import { usageCountersServiceMock } from '../../../../usage_collection/server/usage_counters/usage_counters_service.mock'; + +describe('startTrackingEventLoopDelaysThreshold', () => { + const logger = loggingSystemMock.createLogger(); + const stopMonitoringEventLoop$ = new Subject(); + const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); + const mockEventLoopCounter = mockUsageCountersSetup.createUsageCounter('testCounter'); + + beforeAll(() => jest.useFakeTimers('modern')); + beforeEach(() => jest.clearAllMocks()); + afterEach(() => stopMonitoringEventLoop$.next()); + + it('initializes EventLoopDelaysCollector and starts timer', () => { + const collectionStartDelay = 1000; + const warnThreshold = 1000; + startTrackingEventLoopDelaysThreshold(mockEventLoopCounter, logger, stopMonitoringEventLoop$, { + warnThreshold, + collectionStartDelay, + }); + + expect(monitorEventLoopDelay).toBeCalledTimes(1); + expect(mockMonitorPercentile).toBeCalledTimes(0); + jest.advanceTimersByTime(collectionStartDelay); + expect(mockMonitorPercentile).toBeCalled(); + }); + + it('logs a warning and increments usage counter when the mean delay exceeds the threshold', () => { + const collectionStartDelay = 100; + const collectionInterval = 1000; + const warnThreshold = 10; + + startTrackingEventLoopDelaysThreshold(mockEventLoopCounter, logger, stopMonitoringEventLoop$, { + warnThreshold, + collectionStartDelay, + collectionInterval, + }); + + expect(logger.warn).toBeCalledTimes(0); + expect(mockEventLoopCounter.incrementCounter).toBeCalledTimes(0); + expect(mockMonitorReset).toBeCalledTimes(0); + + jest.advanceTimersByTime(collectionStartDelay); + expect(logger.warn).toBeCalledTimes(1); + expect(mockEventLoopCounter.incrementCounter).toBeCalledTimes(1); + expect(mockMonitorReset).toBeCalledTimes(1); + + jest.advanceTimersByTime(collectionInterval); + expect(logger.warn).toBeCalledTimes(2); + expect(mockEventLoopCounter.incrementCounter).toBeCalledTimes(2); + expect(mockMonitorReset).toBeCalledTimes(2); + + jest.advanceTimersByTime(collectionInterval); + expect(mockEventLoopCounter.incrementCounter).toBeCalledTimes(3); + expect(logger.warn).toBeCalledTimes(3); + expect(mockMonitorReset).toBeCalledTimes(3); + }); + + it('does not log warning or increment usage if threshold did not exceed mean delay', () => { + const collectionStartDelay = 100; + const warnThreshold = 15; + + startTrackingEventLoopDelaysThreshold(mockEventLoopCounter, logger, stopMonitoringEventLoop$, { + warnThreshold, + collectionStartDelay, + }); + + expect(logger.warn).toBeCalledTimes(0); + expect(mockEventLoopCounter.incrementCounter).toBeCalledTimes(0); + expect(mockMonitorReset).toBeCalledTimes(0); + + jest.advanceTimersByTime(collectionStartDelay); + expect(logger.warn).toBeCalledTimes(0); + expect(mockEventLoopCounter.incrementCounter).toBeCalledTimes(0); + expect(mockMonitorReset).toBeCalledTimes(1); + }); +}); diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_threshold.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_threshold.ts new file mode 100644 index 0000000000000..246d88496a158 --- /dev/null +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_threshold.ts @@ -0,0 +1,69 @@ +/* + * 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 { takeUntil, finalize } from 'rxjs/operators'; +import { Observable, timer } from 'rxjs'; +import type { Logger } from 'kibana/server'; +import moment from 'moment'; +import type { UsageCounter } from '../../../../usage_collection/server'; +import { + MONITOR_EVENT_LOOP_THRESHOLD_START, + MONITOR_EVENT_LOOP_THRESHOLD_INTERVAL, + MONITOR_EVENT_LOOP_WARN_THRESHOLD, + ONE_MILLISECOND_AS_NANOSECONDS, +} from './constants'; +import { EventLoopDelaysCollector } from './event_loop_delays'; + +/** + * The monitoring of the event loop starts immediately. + * The first collection happens after 1 minute. + * The histogram is collected and reset every 20 seconds. + * logs a warning when threshold is exceeded (350ms) and increments a usage counter. + */ +export function startTrackingEventLoopDelaysThreshold( + eventLoopCounter: UsageCounter, + logger: Logger, + stopMonitoringEventLoop$: Observable, + configs: { + warnThreshold?: number; + collectionStartDelay?: number; + collectionInterval?: number; + } = {} +) { + const { + warnThreshold = MONITOR_EVENT_LOOP_WARN_THRESHOLD, + collectionStartDelay = MONITOR_EVENT_LOOP_THRESHOLD_START, + collectionInterval = MONITOR_EVENT_LOOP_THRESHOLD_INTERVAL, + } = configs; + + const eventLoopDelaysCollector = new EventLoopDelaysCollector(); + timer(collectionStartDelay, collectionInterval) + .pipe( + takeUntil(stopMonitoringEventLoop$), + finalize(() => eventLoopDelaysCollector.stop()) + ) + .subscribe(async () => { + const { mean } = eventLoopDelaysCollector.collect(); + const meanDurationMs = moment + .duration(mean / ONE_MILLISECOND_AS_NANOSECONDS) + .asMilliseconds(); + + if (meanDurationMs > warnThreshold) { + logger.warn( + `Average event loop delay threshold exceeded ${warnThreshold}ms. Received ${meanDurationMs}ms. ` + + `See https://ela.st/kibana-scaling-considerations for more information about scaling Kibana.` + ); + + eventLoopCounter.incrementCounter({ + counterName: 'delay_threshold_exceeded', + }); + } + + eventLoopDelaysCollector.reset(); + }); +} diff --git a/src/plugins/kibana_usage_collection/server/plugin.ts b/src/plugins/kibana_usage_collection/server/plugin.ts index 4ec717c48610e..dadb4283e84a7 100644 --- a/src/plugins/kibana_usage_collection/server/plugin.ts +++ b/src/plugins/kibana_usage_collection/server/plugin.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; +import type { UsageCollectionSetup, UsageCounter } from 'src/plugins/usage_collection/server'; import { Subject, Observable } from 'rxjs'; import type { PluginInitializerContext, @@ -24,6 +24,7 @@ import type { import { SavedObjectsClient } from '../../../core/server'; import { startTrackingEventLoopDelaysUsage, + startTrackingEventLoopDelaysThreshold, SAVED_OBJECTS_DAILY_TYPE, } from './collectors/event_loop_delays'; import { @@ -59,6 +60,7 @@ export class KibanaUsageCollectionPlugin implements Plugin { private uiSettingsClient?: IUiSettingsClient; private metric$: Subject; private coreUsageData?: CoreUsageDataStart; + private eventLoopUsageCounter?: UsageCounter; private pluginStop$: Subject; constructor(initializerContext: PluginInitializerContext) { @@ -70,6 +72,7 @@ export class KibanaUsageCollectionPlugin implements Plugin { public setup(coreSetup: CoreSetup, { usageCollection }: KibanaUsageCollectionPluginsDepsSetup) { usageCollection.createUsageCounter('uiCounters'); + this.eventLoopUsageCounter = usageCollection.createUsageCounter('eventLoop'); this.registerUsageCollectors( usageCollection, coreSetup, @@ -80,6 +83,9 @@ export class KibanaUsageCollectionPlugin implements Plugin { } public start(core: CoreStart) { + if (!this.eventLoopUsageCounter) { + throw new Error('#setup must be called first'); + } const { savedObjects, uiSettings } = core; this.savedObjectsClient = savedObjects.createInternalRepository([SAVED_OBJECTS_DAILY_TYPE]); const savedObjectsClient = new SavedObjectsClient(this.savedObjectsClient); @@ -87,6 +93,11 @@ export class KibanaUsageCollectionPlugin implements Plugin { core.metrics.getOpsMetrics$().subscribe(this.metric$); this.coreUsageData = core.coreUsageData; startTrackingEventLoopDelaysUsage(this.savedObjectsClient, this.pluginStop$.asObservable()); + startTrackingEventLoopDelaysThreshold( + this.eventLoopUsageCounter, + this.logger, + this.pluginStop$.asObservable() + ); } public stop() { diff --git a/src/plugins/usage_collection/server/mocks.ts b/src/plugins/usage_collection/server/mocks.ts index ab7e53a7ad69b..ca3bdfe1e7522 100644 --- a/src/plugins/usage_collection/server/mocks.ts +++ b/src/plugins/usage_collection/server/mocks.ts @@ -16,7 +16,7 @@ import { import { CollectorOptions, CollectorSet } from './collector'; import { Collector } from './collector/collector'; import { UsageCollectionSetup, CollectorFetchContext } from './index'; - +import { usageCountersServiceMock } from './usage_counters/usage_counters_service.mock'; export type { CollectorOptions }; export { Collector }; @@ -25,10 +25,14 @@ export const createUsageCollectionSetupMock = () => { logger: loggingSystemMock.createLogger(), maximumWaitTimeForAllCollectorsInS: 1, }); + const { + createUsageCounter, + getUsageCounterByType, + } = usageCountersServiceMock.createSetupContract(); const usageCollectionSetupMock: jest.Mocked = { - createUsageCounter: jest.fn(), - getUsageCounterByType: jest.fn(), + createUsageCounter, + getUsageCounterByType, areAllCollectorsReady: jest.fn().mockImplementation(collectorSet.areAllCollectorsReady), bulkFetch: jest.fn().mockImplementation(collectorSet.bulkFetch), getCollectorByType: jest.fn().mockImplementation(collectorSet.getCollectorByType),