From 939031b7067397bfdc5eaf304cb20ad01d728fce Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 24 Aug 2021 14:48:37 +0300 Subject: [PATCH] rebase changes from #107900 --- ...er.eventloopdelaysmonitor._constructor_.md | 13 +++ ...e-server.eventloopdelaysmonitor.collect.md | 15 ++++ ...ugin-core-server.eventloopdelaysmonitor.md | 26 ++++++ ...ore-server.eventloopdelaysmonitor.reset.md | 15 ++++ ...core-server.eventloopdelaysmonitor.stop.md | 15 ++++ ...n-core-server.intervalhistogram.exceeds.md | 11 +++ ...-server.intervalhistogram.fromtimestamp.md | 11 +++ ...-server.intervalhistogram.lastupdatedat.md | 11 +++ ...lugin-core-server.intervalhistogram.max.md | 11 +++ ...na-plugin-core-server.intervalhistogram.md | 25 ++++++ ...ugin-core-server.intervalhistogram.mean.md | 11 +++ ...lugin-core-server.intervalhistogram.min.md | 11 +++ ...re-server.intervalhistogram.percentiles.md | 16 ++++ ...in-core-server.intervalhistogram.stddev.md | 11 +++ .../core/server/kibana-plugin-core-server.md | 2 + .../kibana-plugin-core-server.opsmetrics.md | 3 +- ...a-plugin-core-server.opsmetrics.process.md | 6 +- ...plugin-core-server.opsmetrics.processes.md | 13 +++ ...rver.opsprocessmetrics.event_loop_delay.md | 2 +- ...ocessmetrics.event_loop_delay_histogram.md | 13 +++ ...na-plugin-core-server.opsprocessmetrics.md | 4 +- ...ugin-core-server.opsprocessmetrics.name.md | 13 +++ .../core_app/status/lib/load_status.test.ts | 22 ++++- src/core/server/index.ts | 2 + .../metrics/collectors/collector.mock.ts | 6 +- src/core/server/metrics/collectors/mocks.ts | 4 +- .../metrics/collectors/process.mocks.ts | 25 ++++++ .../server/metrics/collectors/process.test.ts | 40 +++++---- src/core/server/metrics/collectors/process.ts | 36 ++++---- src/core/server/metrics/collectors/types.ts | 13 ++- .../event_loop_delays/__mocks__/perf_hooks.ts | 21 +++++ .../event_loop_delays_monitor.mocks.ts} | 35 ++++---- .../event_loop_delays_monitor.test.ts | 65 ++++++++++++++ .../event_loop_delays_monitor.ts} | 16 ++-- .../server/metrics/event_loop_delays/index.ts | 10 +++ src/core/server/metrics/index.ts | 2 + .../logging/get_ops_metrics_log.test.ts | 14 ++- .../server/metrics/metrics_service.mock.ts | 18 ++-- .../metrics/ops_metrics_collector.test.ts | 3 +- .../server/metrics/ops_metrics_collector.ts | 6 +- src/core/server/metrics/types.ts | 9 +- src/core/server/server.api.md | 44 +++++++++ src/core/server/status/routes/status.ts | 1 + .../collectors/event_loop_delays/constants.ts | 5 -- .../event_loop_delays.test.ts | 63 ------------- .../integration_tests/daily_rollups.test.ts | 11 ++- .../event_loop_delays/saved_objects.test.ts | 7 +- .../event_loop_delays/saved_objects.ts | 3 +- .../event_loop_delays/track_delays.test.ts | 76 +++++++++------- .../event_loop_delays/track_delays.ts | 10 +-- .../event_loop_delays/track_threshold.test.ts | 69 ++++++++------ .../event_loop_delays/track_threshold.ts | 10 +-- .../__snapshots__/index.test.ts.snap | 43 --------- .../ops_stats_collector.test.ts.snap | 61 +++++++++++++ ...ex.test.ts => ops_stats_collector.test.ts} | 89 +++---------------- .../ops_stats/ops_stats_collector.ts | 5 ++ .../kibana_usage_collection/server/plugin.ts | 11 ++- 57 files changed, 749 insertions(+), 364 deletions(-) create mode 100644 docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor._constructor_.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.collect.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.reset.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.stop.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.intervalhistogram.exceeds.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.intervalhistogram.fromtimestamp.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.intervalhistogram.lastupdatedat.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.intervalhistogram.max.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.intervalhistogram.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.intervalhistogram.mean.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.intervalhistogram.min.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.intervalhistogram.percentiles.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.intervalhistogram.stddev.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.opsmetrics.processes.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.event_loop_delay_histogram.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.name.md create mode 100644 src/core/server/metrics/collectors/process.mocks.ts create mode 100644 src/core/server/metrics/event_loop_delays/__mocks__/perf_hooks.ts rename src/{plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.mocks.ts => core/server/metrics/event_loop_delays/event_loop_delays_monitor.mocks.ts} (61%) create mode 100644 src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.test.ts rename src/{plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.ts => core/server/metrics/event_loop_delays/event_loop_delays_monitor.ts} (83%) create mode 100644 src/core/server/metrics/event_loop_delays/index.ts delete mode 100644 src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.test.ts delete mode 100644 src/plugins/kibana_usage_collection/server/collectors/ops_stats/__snapshots__/index.test.ts.snap create mode 100644 src/plugins/kibana_usage_collection/server/collectors/ops_stats/__snapshots__/ops_stats_collector.test.ts.snap rename src/plugins/kibana_usage_collection/server/collectors/ops_stats/{index.test.ts => ops_stats_collector.test.ts} (50%) diff --git a/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor._constructor_.md b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor._constructor_.md new file mode 100644 index 0000000000000..3a9efc0eacdb6 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor._constructor_.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [EventLoopDelaysMonitor](./kibana-plugin-core-server.eventloopdelaysmonitor.md) > [(constructor)](./kibana-plugin-core-server.eventloopdelaysmonitor._constructor_.md) + +## EventLoopDelaysMonitor.(constructor) + +Constructs a new instance of the `EventLoopDelaysMonitor` class + +Signature: + +```typescript +constructor(); +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.collect.md b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.collect.md new file mode 100644 index 0000000000000..6277f59067239 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.collect.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [EventLoopDelaysMonitor](./kibana-plugin-core-server.eventloopdelaysmonitor.md) > [collect](./kibana-plugin-core-server.eventloopdelaysmonitor.collect.md) + +## EventLoopDelaysMonitor.collect() method + +Signature: + +```typescript +collect(): IntervalHistogram; +``` +Returns: + +`IntervalHistogram` + diff --git a/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.md b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.md new file mode 100644 index 0000000000000..15d02ecd5f25d --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [EventLoopDelaysMonitor](./kibana-plugin-core-server.eventloopdelaysmonitor.md) + +## EventLoopDelaysMonitor class + +Signature: + +```typescript +export declare class EventLoopDelaysMonitor +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)()](./kibana-plugin-core-server.eventloopdelaysmonitor._constructor_.md) | | Constructs a new instance of the EventLoopDelaysMonitor class | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [collect()](./kibana-plugin-core-server.eventloopdelaysmonitor.collect.md) | | | +| [reset()](./kibana-plugin-core-server.eventloopdelaysmonitor.reset.md) | | | +| [stop()](./kibana-plugin-core-server.eventloopdelaysmonitor.stop.md) | | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.reset.md b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.reset.md new file mode 100644 index 0000000000000..c593d0341bbed --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.reset.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [EventLoopDelaysMonitor](./kibana-plugin-core-server.eventloopdelaysmonitor.md) > [reset](./kibana-plugin-core-server.eventloopdelaysmonitor.reset.md) + +## EventLoopDelaysMonitor.reset() method + +Signature: + +```typescript +reset(): void; +``` +Returns: + +`void` + diff --git a/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.stop.md b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.stop.md new file mode 100644 index 0000000000000..86e76d0c6fba4 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.stop.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [EventLoopDelaysMonitor](./kibana-plugin-core-server.eventloopdelaysmonitor.md) > [stop](./kibana-plugin-core-server.eventloopdelaysmonitor.stop.md) + +## EventLoopDelaysMonitor.stop() method + +Signature: + +```typescript +stop(): void; +``` +Returns: + +`void` + diff --git a/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.exceeds.md b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.exceeds.md new file mode 100644 index 0000000000000..664bdb8f24d7b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.exceeds.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IntervalHistogram](./kibana-plugin-core-server.intervalhistogram.md) > [exceeds](./kibana-plugin-core-server.intervalhistogram.exceeds.md) + +## IntervalHistogram.exceeds property + +Signature: + +```typescript +exceeds: number; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.fromtimestamp.md b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.fromtimestamp.md new file mode 100644 index 0000000000000..00fa8dcb84430 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.fromtimestamp.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IntervalHistogram](./kibana-plugin-core-server.intervalhistogram.md) > [fromTimestamp](./kibana-plugin-core-server.intervalhistogram.fromtimestamp.md) + +## IntervalHistogram.fromTimestamp property + +Signature: + +```typescript +fromTimestamp: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.lastupdatedat.md b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.lastupdatedat.md new file mode 100644 index 0000000000000..58e75fc2ba437 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.lastupdatedat.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IntervalHistogram](./kibana-plugin-core-server.intervalhistogram.md) > [lastUpdatedAt](./kibana-plugin-core-server.intervalhistogram.lastupdatedat.md) + +## IntervalHistogram.lastUpdatedAt property + +Signature: + +```typescript +lastUpdatedAt: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.max.md b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.max.md new file mode 100644 index 0000000000000..14d7fe6b68c4b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.max.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IntervalHistogram](./kibana-plugin-core-server.intervalhistogram.md) > [max](./kibana-plugin-core-server.intervalhistogram.max.md) + +## IntervalHistogram.max property + +Signature: + +```typescript +max: number; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.md b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.md new file mode 100644 index 0000000000000..20f71420a0d88 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IntervalHistogram](./kibana-plugin-core-server.intervalhistogram.md) + +## IntervalHistogram interface + +Signature: + +```typescript +export interface IntervalHistogram +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [exceeds](./kibana-plugin-core-server.intervalhistogram.exceeds.md) | number | | +| [fromTimestamp](./kibana-plugin-core-server.intervalhistogram.fromtimestamp.md) | string | | +| [lastUpdatedAt](./kibana-plugin-core-server.intervalhistogram.lastupdatedat.md) | string | | +| [max](./kibana-plugin-core-server.intervalhistogram.max.md) | number | | +| [mean](./kibana-plugin-core-server.intervalhistogram.mean.md) | number | | +| [min](./kibana-plugin-core-server.intervalhistogram.min.md) | number | | +| [percentiles](./kibana-plugin-core-server.intervalhistogram.percentiles.md) | {
50: number;
75: number;
95: number;
99: number;
} | | +| [stddev](./kibana-plugin-core-server.intervalhistogram.stddev.md) | number | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.mean.md b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.mean.md new file mode 100644 index 0000000000000..e6794bfa5fe52 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.mean.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IntervalHistogram](./kibana-plugin-core-server.intervalhistogram.md) > [mean](./kibana-plugin-core-server.intervalhistogram.mean.md) + +## IntervalHistogram.mean property + +Signature: + +```typescript +mean: number; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.min.md b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.min.md new file mode 100644 index 0000000000000..d0eb929601f18 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.min.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IntervalHistogram](./kibana-plugin-core-server.intervalhistogram.md) > [min](./kibana-plugin-core-server.intervalhistogram.min.md) + +## IntervalHistogram.min property + +Signature: + +```typescript +min: number; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.percentiles.md b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.percentiles.md new file mode 100644 index 0000000000000..b0adc9531c0b1 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.percentiles.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IntervalHistogram](./kibana-plugin-core-server.intervalhistogram.md) > [percentiles](./kibana-plugin-core-server.intervalhistogram.percentiles.md) + +## IntervalHistogram.percentiles property + +Signature: + +```typescript +percentiles: { + 50: number; + 75: number; + 95: number; + 99: number; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.stddev.md b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.stddev.md new file mode 100644 index 0000000000000..bca5ab56cb237 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.stddev.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IntervalHistogram](./kibana-plugin-core-server.intervalhistogram.md) > [stddev](./kibana-plugin-core-server.intervalhistogram.stddev.md) + +## IntervalHistogram.stddev property + +Signature: + +```typescript +stddev: number; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index 96bb82c8968df..a702c5fe7b97b 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -19,6 +19,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [BasePath](./kibana-plugin-core-server.basepath.md) | Access or manipulate the Kibana base path | | [CspConfig](./kibana-plugin-core-server.cspconfig.md) | CSP configuration for use in Kibana. | | [ElasticsearchConfig](./kibana-plugin-core-server.elasticsearchconfig.md) | Wrapper of config schema. | +| [EventLoopDelaysMonitor](./kibana-plugin-core-server.eventloopdelaysmonitor.md) | | | [KibanaRequest](./kibana-plugin-core-server.kibanarequest.md) | Kibana specific abstraction for an incoming request. | | [RouteValidationError](./kibana-plugin-core-server.routevalidationerror.md) | Error to return when the validation is not successful. | | [SavedObjectsClient](./kibana-plugin-core-server.savedobjectsclient.md) | | @@ -97,6 +98,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [IExternalUrlPolicy](./kibana-plugin-core-server.iexternalurlpolicy.md) | A policy describing whether access to an external destination is allowed. | | [IKibanaResponse](./kibana-plugin-core-server.ikibanaresponse.md) | A response data object, expected to returned as a result of [RequestHandler](./kibana-plugin-core-server.requesthandler.md) execution | | [IKibanaSocket](./kibana-plugin-core-server.ikibanasocket.md) | A tiny abstraction for TCP socket. | +| [IntervalHistogram](./kibana-plugin-core-server.intervalhistogram.md) | | | [IRenderOptions](./kibana-plugin-core-server.irenderoptions.md) | | | [IRouter](./kibana-plugin-core-server.irouter.md) | Registers route handlers for specified resource path and method. See [RouteConfig](./kibana-plugin-core-server.routeconfig.md) and [RequestHandler](./kibana-plugin-core-server.requesthandler.md) for more information about arguments to route registrations. | | [ISavedObjectsPointInTimeFinder](./kibana-plugin-core-server.isavedobjectspointintimefinder.md) | | diff --git a/docs/development/core/server/kibana-plugin-core-server.opsmetrics.md b/docs/development/core/server/kibana-plugin-core-server.opsmetrics.md index 9803c0fbd53cc..1572c1ae3131e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.opsmetrics.md +++ b/docs/development/core/server/kibana-plugin-core-server.opsmetrics.md @@ -19,7 +19,8 @@ export interface OpsMetrics | [collected\_at](./kibana-plugin-core-server.opsmetrics.collected_at.md) | Date | Time metrics were recorded at. | | [concurrent\_connections](./kibana-plugin-core-server.opsmetrics.concurrent_connections.md) | OpsServerMetrics['concurrent_connections'] | number of current concurrent connections to the server | | [os](./kibana-plugin-core-server.opsmetrics.os.md) | OpsOsMetrics | OS related metrics | -| [process](./kibana-plugin-core-server.opsmetrics.process.md) | OpsProcessMetrics | Process related metrics | +| [process](./kibana-plugin-core-server.opsmetrics.process.md) | OpsProcessMetrics | Process related metrics. Deprecated in favor of processes field. | +| [processes](./kibana-plugin-core-server.opsmetrics.processes.md) | OpsProcessMetrics[] | Process related metrics. Reports an array of objects for each kibana pid. | | [requests](./kibana-plugin-core-server.opsmetrics.requests.md) | OpsServerMetrics['requests'] | server requests stats | | [response\_times](./kibana-plugin-core-server.opsmetrics.response_times.md) | OpsServerMetrics['response_times'] | server response time stats | diff --git a/docs/development/core/server/kibana-plugin-core-server.opsmetrics.process.md b/docs/development/core/server/kibana-plugin-core-server.opsmetrics.process.md index b3759fadafc0a..9da2c0644dc84 100644 --- a/docs/development/core/server/kibana-plugin-core-server.opsmetrics.process.md +++ b/docs/development/core/server/kibana-plugin-core-server.opsmetrics.process.md @@ -4,7 +4,11 @@ ## OpsMetrics.process property -Process related metrics +> Warning: This API is now obsolete. +> +> + +Process related metrics. Deprecated in favor of processes field. Signature: diff --git a/docs/development/core/server/kibana-plugin-core-server.opsmetrics.processes.md b/docs/development/core/server/kibana-plugin-core-server.opsmetrics.processes.md new file mode 100644 index 0000000000000..cf1f0a7c54475 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.opsmetrics.processes.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [OpsMetrics](./kibana-plugin-core-server.opsmetrics.md) > [processes](./kibana-plugin-core-server.opsmetrics.processes.md) + +## OpsMetrics.processes property + +Process related metrics. Reports an array of objects for each kibana pid. + +Signature: + +```typescript +processes: OpsProcessMetrics[]; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.event_loop_delay.md b/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.event_loop_delay.md index 239f94e37d00e..d626b9cf8f98c 100644 --- a/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.event_loop_delay.md +++ b/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.event_loop_delay.md @@ -4,7 +4,7 @@ ## OpsProcessMetrics.event\_loop\_delay property -node event loop delay +mean event loop delay since last collection Signature: diff --git a/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.event_loop_delay_histogram.md b/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.event_loop_delay_histogram.md new file mode 100644 index 0000000000000..1d870b19f2d1f --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.event_loop_delay_histogram.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [OpsProcessMetrics](./kibana-plugin-core-server.opsprocessmetrics.md) > [event\_loop\_delay\_histogram](./kibana-plugin-core-server.opsprocessmetrics.event_loop_delay_histogram.md) + +## OpsProcessMetrics.event\_loop\_delay\_histogram property + +node event loop delay histogram since last collection + +Signature: + +```typescript +event_loop_delay_histogram: IntervalHistogram; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.md b/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.md index 79763b783470e..fdaaf594232fd 100644 --- a/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.md +++ b/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.md @@ -16,8 +16,10 @@ export interface OpsProcessMetrics | Property | Type | Description | | --- | --- | --- | -| [event\_loop\_delay](./kibana-plugin-core-server.opsprocessmetrics.event_loop_delay.md) | number | node event loop delay | +| [event\_loop\_delay\_histogram](./kibana-plugin-core-server.opsprocessmetrics.event_loop_delay_histogram.md) | IntervalHistogram | node event loop delay histogram since last collection | +| [event\_loop\_delay](./kibana-plugin-core-server.opsprocessmetrics.event_loop_delay.md) | number | mean event loop delay since last collection | | [memory](./kibana-plugin-core-server.opsprocessmetrics.memory.md) | {
heap: {
total_in_bytes: number;
used_in_bytes: number;
size_limit: number;
};
resident_set_size_in_bytes: number;
} | process memory usage | +| [name](./kibana-plugin-core-server.opsprocessmetrics.name.md) | 'coordinator' | 'server_worker' | name of process (example: 'coordinator' \| 'server\_worker' \| 'task\_worker' \| 'reporting\_worker') | | [pid](./kibana-plugin-core-server.opsprocessmetrics.pid.md) | number | pid of the kibana process | | [uptime\_in\_millis](./kibana-plugin-core-server.opsprocessmetrics.uptime_in_millis.md) | number | uptime of the kibana process | diff --git a/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.name.md b/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.name.md new file mode 100644 index 0000000000000..72f98fb7e717d --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.name.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [OpsProcessMetrics](./kibana-plugin-core-server.opsprocessmetrics.md) > [name](./kibana-plugin-core-server.opsprocessmetrics.name.md) + +## OpsProcessMetrics.name property + +name of process (example: 'coordinator' \| 'server\_worker' \| 'task\_worker' \| 'reporting\_worker') + +Signature: + +```typescript +name: 'coordinator' | 'server_worker'; +``` diff --git a/src/core/public/core_app/status/lib/load_status.test.ts b/src/core/public/core_app/status/lib/load_status.test.ts index e412192ea00ee..7411cab5892ac 100644 --- a/src/core/public/core_app/status/lib/load_status.test.ts +++ b/src/core/public/core_app/status/lib/load_status.test.ts @@ -9,6 +9,7 @@ import { StatusResponse } from '../../../../types/status'; import { httpServiceMock } from '../../../http/http_service.mock'; import { notificationServiceMock } from '../../../notifications/notifications_service.mock'; +import { mocked } from '../../../../server/metrics/event_loop_delays/event_loop_delays_monitor.mocks'; import { loadStatus } from './load_status'; const mockedResponse: StatusResponse = { @@ -61,6 +62,8 @@ const mockedResponse: StatusResponse = { }, }, process: { + name: 'server_worker' as const, + pid: 1, memory: { heap: { size_limit: 1000000, @@ -70,9 +73,26 @@ const mockedResponse: StatusResponse = { resident_set_size_in_bytes: 1, }, event_loop_delay: 1, - pid: 1, + event_loop_delay_histogram: mocked.createHistogram(), uptime_in_millis: 1, }, + processes: [ + { + name: 'server_worker' as const, + pid: 1, + memory: { + heap: { + size_limit: 1000000, + used_in_bytes: 100, + total_in_bytes: 0, + }, + resident_set_size_in_bytes: 1, + }, + event_loop_delay: 1, + event_loop_delay_histogram: mocked.createHistogram(), + uptime_in_millis: 1, + }, + ], response_times: { avg_in_millis: 4000, max_in_millis: 8000, diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 1c3a0850d3b79..f2eb7ccd3a253 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -378,7 +378,9 @@ export type { OpsProcessMetrics, MetricsServiceSetup, MetricsServiceStart, + IntervalHistogram, } from './metrics'; +export { EventLoopDelaysMonitor } from './metrics'; export type { I18nServiceSetup } from './i18n'; export type { diff --git a/src/core/server/metrics/collectors/collector.mock.ts b/src/core/server/metrics/collectors/collector.mock.ts index bf45925bf583f..088156fa2ff5e 100644 --- a/src/core/server/metrics/collectors/collector.mock.ts +++ b/src/core/server/metrics/collectors/collector.mock.ts @@ -8,8 +8,10 @@ import { MetricsCollector } from './types'; -const createCollector = (collectReturnValue: any = {}): jest.Mocked> => { - const collector: jest.Mocked> = { +const createCollector = ( + collectReturnValue: any = {} +): jest.Mocked> => { + const collector: jest.Mocked> = { collect: jest.fn().mockResolvedValue(collectReturnValue), reset: jest.fn(), }; diff --git a/src/core/server/metrics/collectors/mocks.ts b/src/core/server/metrics/collectors/mocks.ts index ad8dd9fa57966..425751899ddc9 100644 --- a/src/core/server/metrics/collectors/mocks.ts +++ b/src/core/server/metrics/collectors/mocks.ts @@ -6,7 +6,8 @@ * Side Public License, v 1. */ -import { MetricsCollector } from './types'; +import type { MetricsCollector } from './types'; +import { createMockOpsProcessMetrics } from './process.mocks'; const createMock = () => { const mocked: jest.Mocked> = { @@ -21,4 +22,5 @@ const createMock = () => { export const collectorMock = { create: createMock, + createOpsProcessMetrics: createMockOpsProcessMetrics, }; diff --git a/src/core/server/metrics/collectors/process.mocks.ts b/src/core/server/metrics/collectors/process.mocks.ts new file mode 100644 index 0000000000000..e9c002f320fb5 --- /dev/null +++ b/src/core/server/metrics/collectors/process.mocks.ts @@ -0,0 +1,25 @@ +/* + * 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 { mocked } from '../event_loop_delays/event_loop_delays_monitor.mocks'; +import type { OpsProcessMetrics } from './types'; + +export function createMockOpsProcessMetrics(): OpsProcessMetrics { + const histogram = mocked.createHistogram(); + + return { + name: 'server_worker' as const, + memory: { + heap: { total_in_bytes: 1, used_in_bytes: 1, size_limit: 1 }, + resident_set_size_in_bytes: 1, + }, + event_loop_delay: 1, + event_loop_delay_histogram: histogram, + pid: 1, + uptime_in_millis: 1, + }; +} diff --git a/src/core/server/metrics/collectors/process.test.ts b/src/core/server/metrics/collectors/process.test.ts index 0395cd8d597fd..ff861d5c8bef1 100644 --- a/src/core/server/metrics/collectors/process.test.ts +++ b/src/core/server/metrics/collectors/process.test.ts @@ -9,6 +9,7 @@ import v8, { HeapInfo } from 'v8'; import { ProcessMetricsCollector } from './process'; +/* eslint-disable dot-notation */ describe('ProcessMetricsCollector', () => { let collector: ProcessMetricsCollector; @@ -20,28 +21,34 @@ describe('ProcessMetricsCollector', () => { jest.restoreAllMocks(); }); - it('collects pid from the process', async () => { - const metrics = await collector.collect(); + it('collects pid from the process', () => { + const metrics = collector.collect(); - expect(metrics.pid).toEqual(process.pid); + expect(metrics).toHaveLength(1); + expect(metrics[0].pid).toEqual(process.pid); }); - it('collects event loop delay', async () => { - const metrics = await collector.collect(); - - expect(metrics.event_loop_delay).toBeGreaterThan(0); + it('collects event loop delay', () => { + const mockEventLoopDelayMonitor = { collect: jest.fn().mockReturnValue({ mean: 13 }) }; + // @ts-expect-error-next-line readonly private method. + collector['eventLoopDelayMonitor'] = mockEventLoopDelayMonitor; + const metrics = collector.collect(); + expect(metrics).toHaveLength(1); + expect(metrics[0].event_loop_delay).toBe(13); + expect(mockEventLoopDelayMonitor.collect).toBeCalledTimes(1); }); - it('collects uptime info from the process', async () => { + it('collects uptime info from the process', () => { const uptime = 58986; jest.spyOn(process, 'uptime').mockImplementation(() => uptime); - const metrics = await collector.collect(); + const metrics = collector.collect(); - expect(metrics.uptime_in_millis).toEqual(uptime * 1000); + expect(metrics).toHaveLength(1); + expect(metrics[0].uptime_in_millis).toEqual(uptime * 1000); }); - it('collects memory info from the process', async () => { + it('collects memory info from the process', () => { const heapTotal = 58986; const heapUsed = 4688; const heapSizeLimit = 5788; @@ -61,11 +68,12 @@ describe('ProcessMetricsCollector', () => { } as HeapInfo) ); - const metrics = await collector.collect(); + const metrics = collector.collect(); - expect(metrics.memory.heap.total_in_bytes).toEqual(heapTotal); - expect(metrics.memory.heap.used_in_bytes).toEqual(heapUsed); - expect(metrics.memory.heap.size_limit).toEqual(heapSizeLimit); - expect(metrics.memory.resident_set_size_in_bytes).toEqual(rss); + expect(metrics).toHaveLength(1); + expect(metrics[0].memory.heap.total_in_bytes).toEqual(heapTotal); + expect(metrics[0].memory.heap.used_in_bytes).toEqual(heapUsed); + expect(metrics[0].memory.heap.size_limit).toEqual(heapSizeLimit); + expect(metrics[0].memory.resident_set_size_in_bytes).toEqual(rss); }); }); diff --git a/src/core/server/metrics/collectors/process.ts b/src/core/server/metrics/collectors/process.ts index d7ff967114f00..8205de65a6b78 100644 --- a/src/core/server/metrics/collectors/process.ts +++ b/src/core/server/metrics/collectors/process.ts @@ -7,15 +7,23 @@ */ import v8 from 'v8'; -import { Bench } from '@hapi/hoek'; import { OpsProcessMetrics, MetricsCollector } from './types'; +import { EventLoopDelaysMonitor } from '../event_loop_delays'; -export class ProcessMetricsCollector implements MetricsCollector { - public async collect(): Promise { +export class ProcessMetricsCollector implements MetricsCollector { + static getMainThreadMetrics(processes: OpsProcessMetrics[]): undefined | OpsProcessMetrics { + return processes.find(({ name }) => name === 'server_worker'); + } + + private readonly eventLoopDelayMonitor = new EventLoopDelaysMonitor(); + + private getCurrentPidMetrics(): OpsProcessMetrics { + const eventLoopDelayHistogram = this.eventLoopDelayMonitor.collect(); const heapStats = v8.getHeapStatistics(); const memoryUsage = process.memoryUsage(); - const [eventLoopDelay] = await Promise.all([getEventLoopDelay()]); + return { + name: 'server_worker' as const, memory: { heap: { total_in_bytes: memoryUsage.heapTotal, @@ -25,19 +33,17 @@ export class ProcessMetricsCollector implements MetricsCollector => { - const bench = new Bench(); - return new Promise((resolve) => { - setImmediate(() => { - return resolve(bench.elapsed()); - }); - }); -}; + public reset() { + this.eventLoopDelayMonitor.reset(); + } +} diff --git a/src/core/server/metrics/collectors/types.ts b/src/core/server/metrics/collectors/types.ts index ec9746aaae769..597b5cafccd1e 100644 --- a/src/core/server/metrics/collectors/types.ts +++ b/src/core/server/metrics/collectors/types.ts @@ -5,11 +5,12 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ +import type { IntervalHistogram } from '../event_loop_delays'; /** Base interface for all metrics gatherers */ export interface MetricsCollector { /** collect the data currently gathered by the collector */ - collect(): Promise; + collect(): Promise | T; /** reset the internal state of the collector */ reset(): void; } @@ -19,6 +20,10 @@ export interface MetricsCollector { * @public */ export interface OpsProcessMetrics { + /** pid of the kibana process */ + pid: number; + /** name of process (example: 'coordinator' | 'server_worker' | 'task_worker' | 'reporting_worker') */ + name: 'coordinator' | 'server_worker'; /** process memory usage */ memory: { /** heap memory usage */ @@ -33,10 +38,10 @@ export interface OpsProcessMetrics { /** node rss */ resident_set_size_in_bytes: number; }; - /** node event loop delay */ + /** mean event loop delay since last collection*/ event_loop_delay: number; - /** pid of the kibana process */ - pid: number; + /** node event loop delay histogram since last collection */ + event_loop_delay_histogram: IntervalHistogram; /** uptime of the kibana process */ uptime_in_millis: number; } diff --git a/src/core/server/metrics/event_loop_delays/__mocks__/perf_hooks.ts b/src/core/server/metrics/event_loop_delays/__mocks__/perf_hooks.ts new file mode 100644 index 0000000000000..7ebc926713617 --- /dev/null +++ b/src/core/server/metrics/event_loop_delays/__mocks__/perf_hooks.ts @@ -0,0 +1,21 @@ +/* + * 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 { mocked } from '../event_loop_delays_monitor.mocks'; + +export const mockMonitor = { + enable: jest.fn(), + percentile: jest.fn(), + disable: jest.fn(), + reset: jest.fn(), +}; + +export const monitorEventLoopDelay = jest.fn().mockReturnValue({ + ...mockMonitor, + ...mocked.createHistogram(), +}); diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.mocks.ts b/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.mocks.ts similarity index 61% rename from src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.mocks.ts rename to src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.mocks.ts index f266a27a7034f..66daf8fce3f5b 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.mocks.ts +++ b/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.mocks.ts @@ -6,23 +6,8 @@ * Side Public License, v 1. */ import moment from 'moment'; -import type { IntervalHistogram } from './event_loop_delays'; - -export const mockMonitorEnable = jest.fn(); -export const mockMonitorPercentile = jest.fn(); -export const mockMonitorReset = jest.fn(); -export const mockMonitorDisable = jest.fn(); -export const monitorEventLoopDelay = jest.fn().mockReturnValue({ - enable: mockMonitorEnable, - percentile: mockMonitorPercentile, - disable: mockMonitorDisable, - reset: mockMonitorReset, - ...createMockHistogram(), -}); - -jest.doMock('perf_hooks', () => ({ - monitorEventLoopDelay, -})); +import type { IntervalHistogram } from 'kibana/server'; +import type { EventLoopDelaysMonitor } from './event_loop_delays_monitor'; function createMockHistogram(overwrites: Partial = {}): IntervalHistogram { const now = moment(); @@ -45,6 +30,22 @@ function createMockHistogram(overwrites: Partial = {}): Inter }; } +function createMockEventLoopDelaysMonitor() { + const mockCollect = jest.fn(); + const MockEventLoopDelaysMonitor: jest.MockedClass< + typeof EventLoopDelaysMonitor + > = jest.fn().mockReturnValue({ + collect: mockCollect, + reset: jest.fn(), + stop: jest.fn(), + }); + + mockCollect.mockReturnValue(createMockHistogram()); + + return new MockEventLoopDelaysMonitor(); +} + export const mocked = { createHistogram: createMockHistogram, + createEventLoopDelaysMonitor: createMockEventLoopDelaysMonitor, }; diff --git a/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.test.ts b/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.test.ts new file mode 100644 index 0000000000000..fbb1fbba617a6 --- /dev/null +++ b/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.test.ts @@ -0,0 +1,65 @@ +/* + * 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. + */ + +/* eslint-disable dot-notation */ +jest.mock('perf_hooks'); +import { monitorEventLoopDelay } from 'perf_hooks'; +import { EventLoopDelaysMonitor } from './event_loop_delays_monitor'; + +describe('EventLoopDelaysMonitor', () => { + beforeAll(() => { + jest.useFakeTimers('modern'); + const mockNow = jest.getRealSystemTime(); + jest.setSystemTime(mockNow); + }); + afterEach(() => jest.clearAllMocks()); + afterAll(() => jest.useRealTimers()); + + test('#constructor enables monitoring', () => { + const eventLoopDelaysMonitor = new EventLoopDelaysMonitor(); + expect(monitorEventLoopDelay).toBeCalledTimes(1); + expect(eventLoopDelaysMonitor['loopMonitor'].enable).toBeCalledTimes(1); + }); + + test('#collect returns event loop delays histogram', () => { + const eventLoopDelaysMonitor = new EventLoopDelaysMonitor(); + expect(eventLoopDelaysMonitor['loopMonitor'].disable).toBeCalledTimes(0); + expect(eventLoopDelaysMonitor['loopMonitor'].enable).toBeCalledTimes(1); + const histogramData = eventLoopDelaysMonitor.collect(); + expect(eventLoopDelaysMonitor['loopMonitor'].disable).toBeCalledTimes(1); + expect(eventLoopDelaysMonitor['loopMonitor'].enable).toBeCalledTimes(2); + expect(eventLoopDelaysMonitor['loopMonitor'].percentile).toHaveBeenNthCalledWith(1, 50); + expect(eventLoopDelaysMonitor['loopMonitor'].percentile).toHaveBeenNthCalledWith(2, 75); + expect(eventLoopDelaysMonitor['loopMonitor'].percentile).toHaveBeenNthCalledWith(3, 95); + expect(eventLoopDelaysMonitor['loopMonitor'].percentile).toHaveBeenNthCalledWith(4, 99); + + expect(Object.keys(histogramData)).toMatchInlineSnapshot(` + Array [ + "min", + "max", + "mean", + "exceeds", + "stddev", + "fromTimestamp", + "lastUpdatedAt", + "percentiles", + ] + `); + }); + test('#reset resets histogram data', () => { + const eventLoopDelaysMonitor = new EventLoopDelaysMonitor(); + eventLoopDelaysMonitor.reset(); + expect(eventLoopDelaysMonitor['loopMonitor'].reset).toBeCalledTimes(1); + }); + test('#stop disables monitoring event loop delays', () => { + const eventLoopDelaysMonitor = new EventLoopDelaysMonitor(); + expect(eventLoopDelaysMonitor['loopMonitor'].disable).toBeCalledTimes(0); + eventLoopDelaysMonitor.stop(); + expect(eventLoopDelaysMonitor['loopMonitor'].disable).toBeCalledTimes(1); + }); +}); diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.ts b/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.ts similarity index 83% rename from src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.ts rename to src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.ts index f5de44a061d5a..cf8f9e780e48f 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.ts +++ b/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.ts @@ -8,7 +8,6 @@ import type { EventLoopDelayMonitor } from 'perf_hooks'; import { monitorEventLoopDelay } from 'perf_hooks'; -import { MONITOR_EVENT_LOOP_DELAYS_RESOLUTION } from './constants'; export interface IntervalHistogram { fromTimestamp: string; @@ -26,30 +25,30 @@ export interface IntervalHistogram { }; } -export class EventLoopDelaysCollector { +export class EventLoopDelaysMonitor { private readonly loopMonitor: EventLoopDelayMonitor; private fromTimestamp: Date; constructor() { - const monitor = monitorEventLoopDelay({ - resolution: MONITOR_EVENT_LOOP_DELAYS_RESOLUTION, - }); + const monitor = monitorEventLoopDelay(); monitor.enable(); this.fromTimestamp = new Date(); this.loopMonitor = monitor; } public collect(): IntervalHistogram { + const lastUpdated = new Date(); + this.loopMonitor.disable(); const { min, max, mean, exceeds, stddev } = this.loopMonitor; - return { + const collectedData: IntervalHistogram = { min, max, mean, exceeds, stddev, fromTimestamp: this.fromTimestamp.toISOString(), - lastUpdatedAt: new Date().toISOString(), + lastUpdatedAt: lastUpdated.toISOString(), percentiles: { 50: this.loopMonitor.percentile(50), 75: this.loopMonitor.percentile(75), @@ -57,6 +56,9 @@ export class EventLoopDelaysCollector { 99: this.loopMonitor.percentile(99), }, }; + + this.loopMonitor.enable(); + return collectedData; } public reset() { diff --git a/src/core/server/metrics/event_loop_delays/index.ts b/src/core/server/metrics/event_loop_delays/index.ts new file mode 100644 index 0000000000000..50d2e35e388e3 --- /dev/null +++ b/src/core/server/metrics/event_loop_delays/index.ts @@ -0,0 +1,10 @@ +/* + * 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. + */ + +export { EventLoopDelaysMonitor } from './event_loop_delays_monitor'; +export type { IntervalHistogram } from './event_loop_delays_monitor'; diff --git a/src/core/server/metrics/index.ts b/src/core/server/metrics/index.ts index 0631bb2b35801..63e475a25918d 100644 --- a/src/core/server/metrics/index.ts +++ b/src/core/server/metrics/index.ts @@ -17,3 +17,5 @@ export type { OpsProcessMetrics, OpsServerMetrics, OpsOsMetrics } from './collec export { MetricsService } from './metrics_service'; export { opsConfig } from './ops_config'; export type { OpsConfigType } from './ops_config'; +export { EventLoopDelaysMonitor } from './event_loop_delays'; +export type { IntervalHistogram } from './event_loop_delays'; diff --git a/src/core/server/metrics/logging/get_ops_metrics_log.test.ts b/src/core/server/metrics/logging/get_ops_metrics_log.test.ts index e535b9babf92b..2d7a6bebf255e 100644 --- a/src/core/server/metrics/logging/get_ops_metrics_log.test.ts +++ b/src/core/server/metrics/logging/get_ops_metrics_log.test.ts @@ -8,19 +8,15 @@ import { OpsMetrics } from '..'; import { getEcsOpsMetricsLog } from './get_ops_metrics_log'; +import { collectorMock } from '../collectors/mocks'; function createBaseOpsMetrics(): OpsMetrics { + const mockProcess = collectorMock.createOpsProcessMetrics(); + return { collected_at: new Date('2020-01-01 01:00:00'), - process: { - memory: { - heap: { total_in_bytes: 1, used_in_bytes: 1, size_limit: 1 }, - resident_set_size_in_bytes: 1, - }, - event_loop_delay: 1, - pid: 1, - uptime_in_millis: 1, - }, + process: mockProcess, + processes: [mockProcess], os: { platform: 'darwin' as const, platformRelease: 'test', diff --git a/src/core/server/metrics/metrics_service.mock.ts b/src/core/server/metrics/metrics_service.mock.ts index b023824df64d3..5c41e78d8efcb 100644 --- a/src/core/server/metrics/metrics_service.mock.ts +++ b/src/core/server/metrics/metrics_service.mock.ts @@ -8,8 +8,9 @@ import { BehaviorSubject } from 'rxjs'; import type { PublicMethodsOf } from '@kbn/utility-types'; - import type { MetricsService } from './metrics_service'; +import { collectorMock } from './collectors/mocks'; +import { mocked as eventLoopDelaysMonitorMock } from './event_loop_delays/event_loop_delays_monitor.mocks'; import { InternalMetricsServiceSetup, InternalMetricsServiceStart, @@ -22,18 +23,14 @@ const createInternalSetupContractMock = () => { collectionInterval: 30000, getOpsMetrics$: jest.fn(), }; + + const processMock = collectorMock.createOpsProcessMetrics(); + setupContract.getOpsMetrics$.mockReturnValue( new BehaviorSubject({ collected_at: new Date('2020-01-01 01:00:00'), - process: { - memory: { - heap: { total_in_bytes: 1, used_in_bytes: 1, size_limit: 1 }, - resident_set_size_in_bytes: 1, - }, - event_loop_delay: 1, - pid: 1, - uptime_in_millis: 1, - }, + process: processMock, + processes: [processMock], os: { platform: 'darwin' as const, platformRelease: 'test', @@ -81,4 +78,5 @@ export const metricsServiceMock = { createStartContract: createStartContractMock, createInternalSetupContract: createInternalSetupContractMock, createInternalStartContract: createInternalStartContractMock, + createEventLoopDelaysMonitor: eventLoopDelaysMonitorMock.createEventLoopDelaysMonitor, }; diff --git a/src/core/server/metrics/ops_metrics_collector.test.ts b/src/core/server/metrics/ops_metrics_collector.test.ts index 3faa771db1dae..7d263d8b7d6af 100644 --- a/src/core/server/metrics/ops_metrics_collector.test.ts +++ b/src/core/server/metrics/ops_metrics_collector.test.ts @@ -28,7 +28,7 @@ describe('OpsMetricsCollector', () => { describe('#collect', () => { it('gathers metrics from the underlying collectors', async () => { mockOsCollector.collect.mockResolvedValue('osMetrics'); - mockProcessCollector.collect.mockResolvedValue('processMetrics'); + mockProcessCollector.collect.mockResolvedValue(['processMetrics']); mockServerCollector.collect.mockResolvedValue({ requests: 'serverRequestsMetrics', response_times: 'serverTimingMetrics', @@ -43,6 +43,7 @@ describe('OpsMetricsCollector', () => { expect(metrics).toEqual({ collected_at: expect.any(Date), process: 'processMetrics', + processes: ['processMetrics'], os: 'osMetrics', requests: 'serverRequestsMetrics', response_times: 'serverTimingMetrics', diff --git a/src/core/server/metrics/ops_metrics_collector.ts b/src/core/server/metrics/ops_metrics_collector.ts index 74e8b8246d83c..98f78e4b12180 100644 --- a/src/core/server/metrics/ops_metrics_collector.ts +++ b/src/core/server/metrics/ops_metrics_collector.ts @@ -28,14 +28,16 @@ export class OpsMetricsCollector implements MetricsCollector { } public async collect(): Promise { - const [process, os, server] = await Promise.all([ + const [processes, os, server] = await Promise.all([ this.processCollector.collect(), this.osCollector.collect(), this.serverCollector.collect(), ]); + return { collected_at: new Date(), - process, + process: processes[0], + processes, os, ...server, }; diff --git a/src/core/server/metrics/types.ts b/src/core/server/metrics/types.ts index d70b8c9ff4208..8beeae2ff7adf 100644 --- a/src/core/server/metrics/types.ts +++ b/src/core/server/metrics/types.ts @@ -7,7 +7,7 @@ */ import { Observable } from 'rxjs'; -import { OpsProcessMetrics, OpsOsMetrics, OpsServerMetrics } from './collectors'; +import type { OpsProcessMetrics, OpsOsMetrics, OpsServerMetrics } from './collectors'; /** * APIs to retrieves metrics gathered and exposed by the core platform. @@ -51,8 +51,13 @@ export type InternalMetricsServiceStart = MetricsServiceStart; export interface OpsMetrics { /** Time metrics were recorded at. */ collected_at: Date; - /** Process related metrics */ + /** + * Process related metrics. Deprecated in favor of processes field. + * @deprecated + */ process: OpsProcessMetrics; + /** Process related metrics. Reports an array of objects for each kibana pid.*/ + processes: OpsProcessMetrics[]; /** OS related metrics */ os: OpsOsMetrics; /** server response time stats */ diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 67b08f4c0d9b7..248e115cddcb4 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -883,6 +883,19 @@ export interface ErrorHttpResponseOptions { headers?: ResponseHeaders; } +// Warning: (ae-missing-release-tag) "EventLoopDelaysMonitor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class EventLoopDelaysMonitor { + constructor(); + // (undocumented) + collect(): IntervalHistogram; + // (undocumented) + reset(): void; + // (undocumented) + stop(): void; +} + // @public (undocumented) export interface ExecutionContextSetup { withContext(context: KibanaExecutionContext | undefined, fn: (...args: any[]) => R): R; @@ -1116,6 +1129,33 @@ export interface IKibanaSocket { }): Promise; } +// Warning: (ae-missing-release-tag) "IntervalHistogram" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface IntervalHistogram { + // (undocumented) + exceeds: number; + // (undocumented) + fromTimestamp: string; + // (undocumented) + lastUpdatedAt: string; + // (undocumented) + max: number; + // (undocumented) + mean: number; + // (undocumented) + min: number; + // (undocumented) + percentiles: { + 50: number; + 75: number; + 95: number; + 99: number; + }; + // (undocumented) + stddev: number; +} + // @public (undocumented) export interface IRenderOptions { includeUserSettings?: boolean; @@ -1401,7 +1441,9 @@ export interface OpsMetrics { collected_at: Date; concurrent_connections: OpsServerMetrics['concurrent_connections']; os: OpsOsMetrics; + // @deprecated process: OpsProcessMetrics; + processes: OpsProcessMetrics[]; requests: OpsServerMetrics['requests']; response_times: OpsServerMetrics['response_times']; } @@ -1442,6 +1484,7 @@ export interface OpsOsMetrics { // @public export interface OpsProcessMetrics { event_loop_delay: number; + event_loop_delay_histogram: IntervalHistogram; memory: { heap: { total_in_bytes: number; @@ -1450,6 +1493,7 @@ export interface OpsProcessMetrics { }; resident_set_size_in_bytes: number; }; + name: 'coordinator' | 'server_worker'; pid: number; uptime_in_millis: number; } diff --git a/src/core/server/status/routes/status.ts b/src/core/server/status/routes/status.ts index 43a596bd1e0ec..df0300c9fa0c2 100644 --- a/src/core/server/status/routes/status.ts +++ b/src/core/server/status/routes/status.ts @@ -106,6 +106,7 @@ export const registerStatusRoute = ({ router, config, metrics, status }: Deps) = collection_interval_in_millis: metrics.collectionInterval, os: lastMetrics.os, process: lastMetrics.process, + processes: lastMetrics.processes, response_times: lastMetrics.response_times, concurrent_connections: lastMetrics.concurrent_connections, requests: { 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 d6201deff5fec..4661441a15a6b 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 @@ -31,11 +31,6 @@ export const MONITOR_EVENT_LOOP_DELAYS_RESET = 24 * 60 * 60 * 1000; */ 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. */ 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 deleted file mode 100644 index b40030e210176..0000000000000 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/event_loop_delays.test.ts +++ /dev/null @@ -1,63 +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 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 { - mockMonitorEnable, - mockMonitorPercentile, - monitorEventLoopDelay, - mockMonitorReset, - mockMonitorDisable, -} from './event_loop_delays.mocks'; -import { EventLoopDelaysCollector } from './event_loop_delays'; - -describe('EventLoopDelaysCollector', () => { - jest.useFakeTimers('modern'); - const mockNow = jest.getRealSystemTime(); - jest.setSystemTime(mockNow); - - beforeEach(() => jest.clearAllMocks()); - afterAll(() => jest.useRealTimers()); - - test('#constructor enables monitoring', () => { - new EventLoopDelaysCollector(); - expect(monitorEventLoopDelay).toBeCalledWith({ resolution: 10 }); - expect(mockMonitorEnable).toBeCalledTimes(1); - }); - - test('#collect returns event loop delays histogram', () => { - const eventLoopDelaysCollector = new EventLoopDelaysCollector(); - const histogramData = eventLoopDelaysCollector.collect(); - expect(mockMonitorPercentile).toHaveBeenNthCalledWith(1, 50); - expect(mockMonitorPercentile).toHaveBeenNthCalledWith(2, 75); - expect(mockMonitorPercentile).toHaveBeenNthCalledWith(3, 95); - expect(mockMonitorPercentile).toHaveBeenNthCalledWith(4, 99); - - expect(Object.keys(histogramData)).toMatchInlineSnapshot(` - Array [ - "min", - "max", - "mean", - "exceeds", - "stddev", - "fromTimestamp", - "lastUpdatedAt", - "percentiles", - ] - `); - }); - test('#reset resets histogram data', () => { - const eventLoopDelaysCollector = new EventLoopDelaysCollector(); - eventLoopDelaysCollector.reset(); - expect(mockMonitorReset).toBeCalledTimes(1); - }); - test('#stop disables monitoring event loop delays', () => { - const eventLoopDelaysCollector = new EventLoopDelaysCollector(); - eventLoopDelaysCollector.stop(); - expect(mockMonitorDisable).toBeCalledTimes(1); - }); -}); diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/rollups/integration_tests/daily_rollups.test.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/rollups/integration_tests/daily_rollups.test.ts index 94840ccfc2748..499227d796f1e 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/rollups/integration_tests/daily_rollups.test.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/rollups/integration_tests/daily_rollups.test.ts @@ -14,7 +14,7 @@ import { createRootWithCorePlugins, } from '../../../../../../../core/test_helpers/kbn_server'; import { rollDailyData } from '../daily'; -import { mocked } from '../../event_loop_delays.mocks'; +import { metricsServiceMock } from '../../../../../../../core/server/mocks'; import { SAVED_OBJECTS_DAILY_TYPE, @@ -26,17 +26,16 @@ import moment from 'moment'; const { startES } = createTestServers({ adjustTimeout: (t: number) => jest.setTimeout(t), }); - +const eventLoopDelaysMonitor = metricsServiceMock.createEventLoopDelaysMonitor(); function createRawObject(date: moment.MomentInput) { const pid = Math.round(Math.random() * 10000); return { type: SAVED_OBJECTS_DAILY_TYPE, id: serializeSavedObjectId({ pid, date }), attributes: { - ...mocked.createHistogram({ - fromTimestamp: moment(date).startOf('day').toISOString(), - lastUpdatedAt: moment(date).toISOString(), - }), + ...eventLoopDelaysMonitor.collect(), + fromTimestamp: moment(date).startOf('day').toISOString(), + lastUpdatedAt: moment(date).toISOString(), processId: pid, }, }; diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/saved_objects.test.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/saved_objects.test.ts index 022040615bd45..ee610d918d61c 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/saved_objects.test.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/saved_objects.test.ts @@ -11,9 +11,8 @@ import { serializeSavedObjectId, deleteHistogramSavedObjects, } from './saved_objects'; -import { savedObjectsRepositoryMock } from '../../../../../core/server/mocks'; +import { savedObjectsRepositoryMock, metricsServiceMock } from '../../../../../core/server/mocks'; import type { SavedObjectsFindResponse } from '../../../../../core/server/'; -import { mocked } from './event_loop_delays.mocks'; describe('serializeSavedObjectId', () => { it('returns serialized id', () => { @@ -23,9 +22,8 @@ describe('serializeSavedObjectId', () => { }); describe('storeHistogram', () => { - const mockHistogram = mocked.createHistogram(); + const eventLoopDelaysMonitor = metricsServiceMock.createEventLoopDelaysMonitor(); const mockInternalRepository = savedObjectsRepositoryMock.create(); - jest.useFakeTimers('modern'); const mockNow = jest.getRealSystemTime(); jest.setSystemTime(mockNow); @@ -34,6 +32,7 @@ describe('storeHistogram', () => { afterAll(() => jest.useRealTimers()); it('stores histogram data in a savedObject', async () => { + const mockHistogram = eventLoopDelaysMonitor.collect(); await storeHistogram(mockHistogram, mockInternalRepository); const pid = process.pid; const id = serializeSavedObjectId({ date: mockNow, pid }); diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/saved_objects.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/saved_objects.ts index 610a6697da364..b66451d1fb764 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/saved_objects.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/saved_objects.ts @@ -12,8 +12,7 @@ import type { ISavedObjectsRepository, } from 'kibana/server'; import moment from 'moment'; -import type { IntervalHistogram } from './event_loop_delays'; - +import type { IntervalHistogram } from 'kibana/server'; export const SAVED_OBJECTS_DAILY_TYPE = 'event_loop_delays_daily'; export interface EventLoopDelaysDaily extends SavedObjectAttributes, IntervalHistogram { 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 index e0d8c20ead75a..ea8309cff31e7 100644 --- 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 @@ -7,43 +7,45 @@ */ import { Subject } from 'rxjs'; - -import { - mockMonitorPercentile, - monitorEventLoopDelay, - mockMonitorReset, - mockMonitorDisable, -} from './event_loop_delays.mocks'; -import { savedObjectsRepositoryMock } from '../../../../../core/server/mocks'; +import { savedObjectsRepositoryMock, metricsServiceMock } from '../../../../../core/server/mocks'; import { startTrackingEventLoopDelaysUsage } from './track_delays'; describe('startTrackingEventLoopDelaysUsage', () => { + const eventLoopDelaysMonitor = metricsServiceMock.createEventLoopDelaysMonitor(); const mockInternalRepository = savedObjectsRepositoryMock.create(); const stopMonitoringEventLoop$ = new Subject(); - beforeAll(() => jest.useFakeTimers('modern')); beforeEach(() => jest.clearAllMocks()); afterEach(() => stopMonitoringEventLoop$.next()); - it('initializes EventLoopDelaysCollector and starts timer', () => { + it('collects eventLoopDelaysMonitor metrics after start delay', () => { const collectionStartDelay = 1000; - startTrackingEventLoopDelaysUsage(mockInternalRepository, stopMonitoringEventLoop$, { - collectionStartDelay, - }); + startTrackingEventLoopDelaysUsage( + mockInternalRepository, + stopMonitoringEventLoop$, + eventLoopDelaysMonitor, + { + collectionStartDelay, + } + ); - expect(monitorEventLoopDelay).toBeCalledTimes(1); - expect(mockMonitorPercentile).toBeCalledTimes(0); + expect(eventLoopDelaysMonitor.collect).toBeCalledTimes(0); jest.advanceTimersByTime(collectionStartDelay); - expect(mockMonitorPercentile).toBeCalled(); + expect(eventLoopDelaysMonitor.collect).toBeCalledTimes(1); }); it('stores event loop delays every collectionInterval duration', () => { const collectionStartDelay = 100; const collectionInterval = 1000; - startTrackingEventLoopDelaysUsage(mockInternalRepository, stopMonitoringEventLoop$, { - collectionStartDelay, - collectionInterval, - }); + startTrackingEventLoopDelaysUsage( + mockInternalRepository, + stopMonitoringEventLoop$, + eventLoopDelaysMonitor, + { + collectionStartDelay, + collectionInterval, + } + ); expect(mockInternalRepository.create).toBeCalledTimes(0); jest.advanceTimersByTime(collectionStartDelay); @@ -54,28 +56,36 @@ describe('startTrackingEventLoopDelaysUsage', () => { expect(mockInternalRepository.create).toBeCalledTimes(3); }); - it('resets histogram every histogramReset duration', () => { + it('resets eventLoopDelaysMonitor every histogramReset duration', () => { const collectionStartDelay = 0; const collectionInterval = 1000; const histogramReset = 5000; - startTrackingEventLoopDelaysUsage(mockInternalRepository, stopMonitoringEventLoop$, { - collectionStartDelay, - collectionInterval, - histogramReset, - }); + startTrackingEventLoopDelaysUsage( + mockInternalRepository, + stopMonitoringEventLoop$, + eventLoopDelaysMonitor, + { + collectionStartDelay, + collectionInterval, + histogramReset, + } + ); - expect(mockMonitorReset).toBeCalledTimes(0); + expect(eventLoopDelaysMonitor.reset).toBeCalledTimes(0); jest.advanceTimersByTime(collectionInterval * 5); - expect(mockMonitorReset).toBeCalledTimes(1); + expect(eventLoopDelaysMonitor.reset).toBeCalledTimes(1); jest.advanceTimersByTime(collectionInterval * 5); - expect(mockMonitorReset).toBeCalledTimes(2); + expect(eventLoopDelaysMonitor.reset).toBeCalledTimes(2); }); it('stops monitoring event loop delays once stopMonitoringEventLoop$.next is called', () => { - startTrackingEventLoopDelaysUsage(mockInternalRepository, stopMonitoringEventLoop$); - - expect(mockMonitorDisable).toBeCalledTimes(0); + startTrackingEventLoopDelaysUsage( + mockInternalRepository, + stopMonitoringEventLoop$, + eventLoopDelaysMonitor + ); + expect(eventLoopDelaysMonitor.stop).toBeCalledTimes(0); stopMonitoringEventLoop$.next(); - expect(mockMonitorDisable).toBeCalledTimes(1); + expect(eventLoopDelaysMonitor.stop).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 index 70638d3b07cbc..d5006c801bddd 100644 --- 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 @@ -9,13 +9,13 @@ import { takeUntil, finalize, map } from 'rxjs/operators'; import { Observable, timer } from 'rxjs'; import type { ISavedObjectsRepository } from 'kibana/server'; +import type { EventLoopDelaysMonitor } from '../../../../../core/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. @@ -25,6 +25,7 @@ import { EventLoopDelaysCollector } from './event_loop_delays'; export function startTrackingEventLoopDelaysUsage( internalRepository: ISavedObjectsRepository, stopMonitoringEventLoop$: Observable, + eventLoopDelaysMonitor: EventLoopDelaysMonitor, configs: { collectionStartDelay?: number; collectionInterval?: number; @@ -37,19 +38,18 @@ export function startTrackingEventLoopDelaysUsage( 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()) + finalize(() => eventLoopDelaysMonitor.stop()) ) .subscribe(async (shouldReset) => { - const histogram = eventLoopDelaysCollector.collect(); + const histogram = eventLoopDelaysMonitor.collect(); if (shouldReset) { - eventLoopDelaysCollector.reset(); + eventLoopDelaysMonitor.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 index 1ff49a735a775..49b1943033719 100644 --- 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 @@ -7,13 +7,8 @@ */ import { Subject } from 'rxjs'; -import { - mockMonitorPercentile, - monitorEventLoopDelay, - mockMonitorReset, -} from './event_loop_delays.mocks'; +import { loggingSystemMock, metricsServiceMock } from '../../../../../core/server/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', () => { @@ -21,6 +16,7 @@ describe('startTrackingEventLoopDelaysThreshold', () => { const stopMonitoringEventLoop$ = new Subject(); const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); const mockEventLoopCounter = mockUsageCountersSetup.createUsageCounter('testCounter'); + const eventLoopDelaysMonitor = metricsServiceMock.createEventLoopDelaysMonitor(); beforeAll(() => jest.useFakeTimers('modern')); beforeEach(() => jest.clearAllMocks()); @@ -29,15 +25,20 @@ describe('startTrackingEventLoopDelaysThreshold', () => { it('initializes EventLoopDelaysCollector and starts timer', () => { const collectionStartDelay = 1000; const warnThreshold = 1000; - startTrackingEventLoopDelaysThreshold(mockEventLoopCounter, logger, stopMonitoringEventLoop$, { - warnThreshold, - collectionStartDelay, - }); + startTrackingEventLoopDelaysThreshold( + mockEventLoopCounter, + logger, + stopMonitoringEventLoop$, + eventLoopDelaysMonitor, + { + warnThreshold, + collectionStartDelay, + } + ); - expect(monitorEventLoopDelay).toBeCalledTimes(1); - expect(mockMonitorPercentile).toBeCalledTimes(0); + expect(eventLoopDelaysMonitor.collect).toBeCalledTimes(0); jest.advanceTimersByTime(collectionStartDelay); - expect(mockMonitorPercentile).toBeCalled(); + expect(eventLoopDelaysMonitor.collect).toBeCalledTimes(1); }); it('logs a warning and increments usage counter when the mean delay exceeds the threshold', () => { @@ -45,48 +46,60 @@ describe('startTrackingEventLoopDelaysThreshold', () => { const collectionInterval = 1000; const warnThreshold = 10; - startTrackingEventLoopDelaysThreshold(mockEventLoopCounter, logger, stopMonitoringEventLoop$, { - warnThreshold, - collectionStartDelay, - collectionInterval, - }); + startTrackingEventLoopDelaysThreshold( + mockEventLoopCounter, + logger, + stopMonitoringEventLoop$, + eventLoopDelaysMonitor, + { + warnThreshold, + collectionStartDelay, + collectionInterval, + } + ); expect(logger.warn).toBeCalledTimes(0); expect(mockEventLoopCounter.incrementCounter).toBeCalledTimes(0); - expect(mockMonitorReset).toBeCalledTimes(0); + expect(eventLoopDelaysMonitor.reset).toBeCalledTimes(0); jest.advanceTimersByTime(collectionStartDelay); expect(logger.warn).toBeCalledTimes(1); expect(mockEventLoopCounter.incrementCounter).toBeCalledTimes(1); - expect(mockMonitorReset).toBeCalledTimes(1); + expect(eventLoopDelaysMonitor.reset).toBeCalledTimes(1); jest.advanceTimersByTime(collectionInterval); expect(logger.warn).toBeCalledTimes(2); expect(mockEventLoopCounter.incrementCounter).toBeCalledTimes(2); - expect(mockMonitorReset).toBeCalledTimes(2); + expect(eventLoopDelaysMonitor.reset).toBeCalledTimes(2); jest.advanceTimersByTime(collectionInterval); expect(mockEventLoopCounter.incrementCounter).toBeCalledTimes(3); expect(logger.warn).toBeCalledTimes(3); - expect(mockMonitorReset).toBeCalledTimes(3); + expect(eventLoopDelaysMonitor.reset).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, - }); + startTrackingEventLoopDelaysThreshold( + mockEventLoopCounter, + logger, + stopMonitoringEventLoop$, + eventLoopDelaysMonitor, + { + warnThreshold, + collectionStartDelay, + } + ); expect(logger.warn).toBeCalledTimes(0); expect(mockEventLoopCounter.incrementCounter).toBeCalledTimes(0); - expect(mockMonitorReset).toBeCalledTimes(0); + expect(eventLoopDelaysMonitor.reset).toBeCalledTimes(0); jest.advanceTimersByTime(collectionStartDelay); expect(logger.warn).toBeCalledTimes(0); expect(mockEventLoopCounter.incrementCounter).toBeCalledTimes(0); - expect(mockMonitorReset).toBeCalledTimes(1); + expect(eventLoopDelaysMonitor.reset).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 index 246d88496a158..ba4e12a7bfced 100644 --- 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 @@ -17,7 +17,7 @@ import { MONITOR_EVENT_LOOP_WARN_THRESHOLD, ONE_MILLISECOND_AS_NANOSECONDS, } from './constants'; -import { EventLoopDelaysCollector } from './event_loop_delays'; +import type { EventLoopDelaysMonitor } from '../../../../../core/server'; /** * The monitoring of the event loop starts immediately. @@ -29,6 +29,7 @@ export function startTrackingEventLoopDelaysThreshold( eventLoopCounter: UsageCounter, logger: Logger, stopMonitoringEventLoop$: Observable, + eventLoopDelaysMonitor: EventLoopDelaysMonitor, configs: { warnThreshold?: number; collectionStartDelay?: number; @@ -41,14 +42,13 @@ export function startTrackingEventLoopDelaysThreshold( collectionInterval = MONITOR_EVENT_LOOP_THRESHOLD_INTERVAL, } = configs; - const eventLoopDelaysCollector = new EventLoopDelaysCollector(); timer(collectionStartDelay, collectionInterval) .pipe( takeUntil(stopMonitoringEventLoop$), - finalize(() => eventLoopDelaysCollector.stop()) + finalize(() => eventLoopDelaysMonitor.stop()) ) .subscribe(async () => { - const { mean } = eventLoopDelaysCollector.collect(); + const { mean } = eventLoopDelaysMonitor.collect(); const meanDurationMs = moment .duration(mean / ONE_MILLISECOND_AS_NANOSECONDS) .asMilliseconds(); @@ -64,6 +64,6 @@ export function startTrackingEventLoopDelaysThreshold( }); } - eventLoopDelaysCollector.reset(); + eventLoopDelaysMonitor.reset(); }); } diff --git a/src/plugins/kibana_usage_collection/server/collectors/ops_stats/__snapshots__/index.test.ts.snap b/src/plugins/kibana_usage_collection/server/collectors/ops_stats/__snapshots__/index.test.ts.snap deleted file mode 100644 index 678237ffb6ea2..0000000000000 --- a/src/plugins/kibana_usage_collection/server/collectors/ops_stats/__snapshots__/index.test.ts.snap +++ /dev/null @@ -1,43 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`telemetry_ops_stats should return something when there is a metric 1`] = ` -Object { - "concurrent_connections": 20, - "os": Object { - "load": Object { - "15m": 3, - "1m": 0.5, - "5m": 1, - }, - "memory": Object { - "free_in_bytes": 10, - "total_in_bytes": 10, - "used_in_bytes": 10, - }, - "platform": "darwin", - "platformRelease": "test", - "uptime_in_millis": 1000, - }, - "process": Object { - "event_loop_delay": 10, - "memory": Object { - "heap": Object { - "size_limit": 0, - "total_in_bytes": 0, - "used_in_bytes": 0, - }, - "resident_set_size_in_bytes": 0, - }, - "uptime_in_millis": 1000, - }, - "requests": Object { - "disconnects": 10, - "total": 100, - }, - "response_times": Object { - "average": 100, - "max": 200, - }, - "timestamp": Any, -} -`; diff --git a/src/plugins/kibana_usage_collection/server/collectors/ops_stats/__snapshots__/ops_stats_collector.test.ts.snap b/src/plugins/kibana_usage_collection/server/collectors/ops_stats/__snapshots__/ops_stats_collector.test.ts.snap new file mode 100644 index 0000000000000..69176fef2f4a5 --- /dev/null +++ b/src/plugins/kibana_usage_collection/server/collectors/ops_stats/__snapshots__/ops_stats_collector.test.ts.snap @@ -0,0 +1,61 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`telemetry_ops_stats should return something when there is a metric 1`] = ` +Object { + "concurrent_connections": 1, + "os": Object { + "load": Object { + "15m": 1, + "1m": 1, + "5m": 1, + }, + "memory": Object { + "free_in_bytes": 1, + "total_in_bytes": 1, + "used_in_bytes": 1, + }, + "platform": "darwin", + "platformRelease": "test", + "uptime_in_millis": 1, + }, + "process": Object { + "event_loop_delay": 1, + "event_loop_delay_histogram": Any, + "memory": Object { + "heap": Object { + "size_limit": 1, + "total_in_bytes": 1, + "used_in_bytes": 1, + }, + "resident_set_size_in_bytes": 1, + }, + "name": "server_worker", + "uptime_in_millis": 1, + }, + "processes": Array [ + Object { + "event_loop_delay": 1, + "event_loop_delay_histogram": Any, + "memory": Object { + "heap": Object { + "size_limit": 1, + "total_in_bytes": 1, + "used_in_bytes": 1, + }, + "resident_set_size_in_bytes": 1, + }, + "name": "server_worker", + "uptime_in_millis": 1, + }, + ], + "requests": Object { + "disconnects": 1, + "total": 1, + }, + "response_times": Object { + "average": 1, + "max": 1, + }, + "timestamp": Any, +} +`; diff --git a/src/plugins/kibana_usage_collection/server/collectors/ops_stats/index.test.ts b/src/plugins/kibana_usage_collection/server/collectors/ops_stats/ops_stats_collector.test.ts similarity index 50% rename from src/plugins/kibana_usage_collection/server/collectors/ops_stats/index.test.ts rename to src/plugins/kibana_usage_collection/server/collectors/ops_stats/ops_stats_collector.test.ts index dfd6a93b7ea18..54a7d3e220242 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/ops_stats/index.test.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/ops_stats/ops_stats_collector.test.ts @@ -7,15 +7,16 @@ */ import { Subject } from 'rxjs'; +import { take } from 'rxjs/operators'; import { Collector, createUsageCollectionSetupMock, createCollectorFetchContextMock, } from '../../../../usage_collection/server/mocks'; -import { registerOpsStatsCollector } from './'; +import { registerOpsStatsCollector } from '.'; import { OpsMetrics } from '../../../../../core/server'; -import { loggingSystemMock } from '../../../../../core/server/mocks'; +import { loggingSystemMock, metricsServiceMock } from '../../../../../core/server/mocks'; const logger = loggingSystemMock.createLogger(); @@ -23,6 +24,8 @@ describe('telemetry_ops_stats', () => { let collector: Collector; const usageCollectionMock = createUsageCollectionSetupMock(); + const metricsServiceSetupMock = metricsServiceMock.createInternalSetupContract(); + usageCollectionMock.makeStatsCollector.mockImplementation((config) => { collector = new Collector(logger, config); return createUsageCollectionSetupMock().makeStatsCollector(config); @@ -31,45 +34,6 @@ describe('telemetry_ops_stats', () => { const metrics$ = new Subject(); const mockedFetchContext = createCollectorFetchContextMock(); - const metric: OpsMetrics = { - collected_at: new Date('2020-01-01 01:00:00'), - process: { - memory: { - heap: { - total_in_bytes: 0, - used_in_bytes: 0, - size_limit: 0, - }, - resident_set_size_in_bytes: 0, - }, - event_loop_delay: 10, - pid: 10, - uptime_in_millis: 1000, - }, - os: { - platform: 'darwin', - platformRelease: 'test', - load: { - '1m': 0.5, - '5m': 1, - '15m': 3, - }, - memory: { - total_in_bytes: 10, - free_in_bytes: 10, - used_in_bytes: 10, - }, - uptime_in_millis: 1000, - }, - response_times: { avg_in_millis: 100, max_in_millis: 200 }, - requests: { - disconnects: 10, - total: 100, - statusCodes: { 200: 100 }, - }, - concurrent_connections: 20, - }; - beforeAll(() => registerOpsStatsCollector(usageCollectionMock, metrics$)); afterAll(() => jest.clearAllTimers()); @@ -83,45 +47,18 @@ describe('telemetry_ops_stats', () => { }); test('should return something when there is a metric', async () => { - metrics$.next(metric); + const opsMetrics = await metricsServiceSetupMock.getOpsMetrics$().pipe(take(1)).toPromise(); + metrics$.next(opsMetrics); expect(collector.isReady()).toBe(true); expect(await collector.fetch(mockedFetchContext)).toMatchSnapshot({ - concurrent_connections: 20, - os: { - load: { - '15m': 3, - '1m': 0.5, - '5m': 1, - }, - memory: { - free_in_bytes: 10, - total_in_bytes: 10, - used_in_bytes: 10, - }, - platform: 'darwin', - platformRelease: 'test', - uptime_in_millis: 1000, - }, process: { - event_loop_delay: 10, - memory: { - heap: { - size_limit: 0, - total_in_bytes: 0, - used_in_bytes: 0, - }, - resident_set_size_in_bytes: 0, - }, - uptime_in_millis: 1000, - }, - requests: { - disconnects: 10, - total: 100, - }, - response_times: { - average: 100, - max: 200, + event_loop_delay_histogram: expect.any(Object), }, + processes: [ + { + event_loop_delay_histogram: expect.any(Object), + }, + ], timestamp: expect.any(String), }); }); diff --git a/src/plugins/kibana_usage_collection/server/collectors/ops_stats/ops_stats_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/ops_stats/ops_stats_collector.ts index 7959b67b4f468..ca7cca2a9de8c 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/ops_stats/ops_stats_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/ops_stats/ops_stats_collector.ts @@ -33,6 +33,11 @@ export function getOpsStatsCollector( // Ensure we only include the same data that Metricbeat collection would get // @ts-expect-error delete metrics.process.pid; + for (const process of metrics.processes) { + // @ts-expect-error + delete process.pid; + } + const responseTimes = { average: metrics.response_times.avg_in_millis, max: metrics.response_times.max_in_millis, diff --git a/src/plugins/kibana_usage_collection/server/plugin.ts b/src/plugins/kibana_usage_collection/server/plugin.ts index dadb4283e84a7..200ce5693bcb6 100644 --- a/src/plugins/kibana_usage_collection/server/plugin.ts +++ b/src/plugins/kibana_usage_collection/server/plugin.ts @@ -21,7 +21,7 @@ import type { Logger, CoreUsageDataStart, } from 'src/core/server'; -import { SavedObjectsClient } from '../../../core/server'; +import { SavedObjectsClient, EventLoopDelaysMonitor } from '../../../core/server'; import { startTrackingEventLoopDelaysUsage, startTrackingEventLoopDelaysThreshold, @@ -92,11 +92,16 @@ export class KibanaUsageCollectionPlugin implements Plugin { this.uiSettingsClient = uiSettings.asScopedToClient(savedObjectsClient); core.metrics.getOpsMetrics$().subscribe(this.metric$); this.coreUsageData = core.coreUsageData; - startTrackingEventLoopDelaysUsage(this.savedObjectsClient, this.pluginStop$.asObservable()); + startTrackingEventLoopDelaysUsage( + this.savedObjectsClient, + this.pluginStop$.asObservable(), + new EventLoopDelaysMonitor() + ); startTrackingEventLoopDelaysThreshold( this.eventLoopUsageCounter, this.logger, - this.pluginStop$.asObservable() + this.pluginStop$.asObservable(), + new EventLoopDelaysMonitor() ); }