From 939031b7067397bfdc5eaf304cb20ad01d728fce Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 24 Aug 2021 14:48:37 +0300 Subject: [PATCH 1/8] 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 000000000000..3a9efc0eacdb --- /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 000000000000..6277f5906723 --- /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 000000000000..15d02ecd5f25 --- /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 000000000000..c593d0341bbe --- /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 000000000000..86e76d0c6fba --- /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 000000000000..664bdb8f24d7 --- /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 000000000000..00fa8dcb8443 --- /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 000000000000..58e75fc2ba43 --- /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 000000000000..14d7fe6b68c4 --- /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 000000000000..20f71420a0d8 --- /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 000000000000..e6794bfa5fe5 --- /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 000000000000..d0eb929601f1 --- /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 000000000000..b0adc9531c0b --- /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 000000000000..bca5ab56cb23 --- /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 96bb82c8968d..a702c5fe7b97 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 9803c0fbd53c..1572c1ae3131 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 b3759fadafc0..9da2c0644dc8 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 000000000000..cf1f0a7c5447 --- /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 239f94e37d00..d626b9cf8f98 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 000000000000..1d870b19f2d1 --- /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 79763b783470..fdaaf594232f 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 000000000000..72f98fb7e717 --- /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 e412192ea00e..7411cab5892a 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 1c3a0850d3b7..f2eb7ccd3a25 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 bf45925bf583..088156fa2ff5 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 ad8dd9fa5796..425751899ddc 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 000000000000..e9c002f320fb --- /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 0395cd8d597f..ff861d5c8bef 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 d7ff967114f0..8205de65a6b7 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 ec9746aaae76..597b5cafccd1 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 000000000000..7ebc92671361 --- /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 f266a27a7034..66daf8fce3f5 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 000000000000..fbb1fbba617a --- /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 f5de44a061d5..cf8f9e780e48 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 000000000000..50d2e35e388e --- /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 0631bb2b3580..63e475a25918 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 e535b9babf92..2d7a6bebf255 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 b023824df64d..5c41e78d8efc 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 3faa771db1da..7d263d8b7d6a 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 74e8b8246d83..98f78e4b1218 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 d70b8c9ff420..8beeae2ff7ad 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 67b08f4c0d9b..248e115cddcb 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 43a596bd1e0e..df0300c9fa0c 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 d6201deff5fe..4661441a15a6 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 b40030e21017..000000000000 --- 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 94840ccfc274..499227d796f1 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 022040615bd4..ee610d918d61 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 610a6697da36..b66451d1fb76 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 e0d8c20ead75..ea8309cff31e 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 70638d3b07cb..d5006c801bdd 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 1ff49a735a77..49b194303371 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 246d88496a15..ba4e12a7bfce 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 678237ffb6ea..000000000000 --- 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 000000000000..69176fef2f4a --- /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 dfd6a93b7ea1..54a7d3e22024 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 7959b67b4f46..ca7cca2a9de8 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 dadb4283e84a..200ce5693bcb 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() ); } From 077b1703626093e17099a264005c3cd2d8123fd1 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Sat, 11 Sep 2021 13:54:14 +0300 Subject: [PATCH 2/8] pass instanceUuid --- src/core/server/metrics/collectors/os.ts | 1 + src/core/server/metrics/collectors/process.ts | 9 +++++++++ src/core/server/metrics/collectors/types.ts | 2 ++ src/core/server/metrics/metrics_service.ts | 10 ++++++++-- src/core/server/metrics/ops_metrics_collector.ts | 2 +- src/core/server/server.ts | 5 ++++- 6 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/core/server/metrics/collectors/os.ts b/src/core/server/metrics/collectors/os.ts index 48808bfd8e79..c4e30fc229a3 100644 --- a/src/core/server/metrics/collectors/os.ts +++ b/src/core/server/metrics/collectors/os.ts @@ -16,6 +16,7 @@ import { OsCgroupMetricsCollector } from './cgroup'; const getos = promisify(getosAsync); export interface OpsMetricsCollectorOptions { + instanceUuid: string; logger: Logger; cpuPath?: string; cpuAcctPath?: string; diff --git a/src/core/server/metrics/collectors/process.ts b/src/core/server/metrics/collectors/process.ts index 8205de65a6b7..9826071cebd8 100644 --- a/src/core/server/metrics/collectors/process.ts +++ b/src/core/server/metrics/collectors/process.ts @@ -10,7 +10,15 @@ import v8 from 'v8'; import { OpsProcessMetrics, MetricsCollector } from './types'; import { EventLoopDelaysMonitor } from '../event_loop_delays'; +export interface ProcessMetricsCollectorOptions { + instanceUuid: string; +} + export class ProcessMetricsCollector implements MetricsCollector { + private readonly instanceUuid: string; + constructor({ instanceUuid }: ProcessMetricsCollectorOptions) { + this.instanceUuid = instanceUuid; + } static getMainThreadMetrics(processes: OpsProcessMetrics[]): undefined | OpsProcessMetrics { return processes.find(({ name }) => name === 'server_worker'); } @@ -33,6 +41,7 @@ export class ProcessMetricsCollector implements MetricsCollector { export interface OpsProcessMetrics { /** pid of the kibana process */ pid: number; + /** uuid of the kibana instance */ + instanceUuid: string; /** name of process (example: 'coordinator' | 'server_worker' | 'task_worker' | 'reporting_worker') */ name: 'coordinator' | 'server_worker'; /** process memory usage */ diff --git a/src/core/server/metrics/metrics_service.ts b/src/core/server/metrics/metrics_service.ts index 78e4dd98f93d..5c8c2a689a6e 100644 --- a/src/core/server/metrics/metrics_service.ts +++ b/src/core/server/metrics/metrics_service.ts @@ -16,9 +16,11 @@ import { InternalMetricsServiceSetup, InternalMetricsServiceStart, OpsMetrics } import { OpsMetricsCollector } from './ops_metrics_collector'; import { opsConfig, OpsConfigType } from './ops_config'; import { getEcsOpsMetricsLog } from './logging'; +import { InternalEnvironmentServiceSetup } from '../environment'; interface MetricsServiceSetupDeps { http: InternalHttpServiceSetup; + environment: InternalEnvironmentServiceSetup; } /** @internal */ @@ -36,14 +38,18 @@ export class MetricsService this.opsMetricsLogger = coreContext.logger.get('metrics', 'ops'); } - public async setup({ http }: MetricsServiceSetupDeps): Promise { + public async setup({ + http, + environment, + }: MetricsServiceSetupDeps): Promise { const config = await this.coreContext.configService .atPath(opsConfig.path) .pipe(first()) .toPromise(); - + const { instanceUuid } = environment; this.metricsCollector = new OpsMetricsCollector(http.server, { logger: this.logger, + instanceUuid, ...config.cGroupOverrides, }); diff --git a/src/core/server/metrics/ops_metrics_collector.ts b/src/core/server/metrics/ops_metrics_collector.ts index 98f78e4b1218..ae6bd6c01b68 100644 --- a/src/core/server/metrics/ops_metrics_collector.ts +++ b/src/core/server/metrics/ops_metrics_collector.ts @@ -22,7 +22,7 @@ export class OpsMetricsCollector implements MetricsCollector { private readonly serverCollector: ServerMetricsCollector; constructor(server: HapiServer, opsOptions: OpsMetricsCollectorOptions) { - this.processCollector = new ProcessMetricsCollector(); + this.processCollector = new ProcessMetricsCollector(opsOptions); this.osCollector = new OsMetricsCollector(opsOptions); this.serverCollector = new ServerMetricsCollector(server); } diff --git a/src/core/server/server.ts b/src/core/server/server.ts index 27c35031db46..35ca8b1b49f1 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -216,7 +216,10 @@ export class Server { executionContext: executionContextSetup, }); - const metricsSetup = await this.metrics.setup({ http: httpSetup }); + const metricsSetup = await this.metrics.setup({ + http: httpSetup, + environment: environmentSetup, + }); const coreUsageDataSetup = this.coreUsageData.setup({ http: httpSetup, From 05b299546adb4ced2899a1238ea700f6a90eeee7 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Sat, 11 Sep 2021 14:06:28 +0300 Subject: [PATCH 3/8] revert instance uuid in process metric --- src/core/server/metrics/collectors/os.ts | 1 - src/core/server/metrics/collectors/process.ts | 9 --------- src/core/server/metrics/collectors/types.ts | 2 -- src/core/server/metrics/metrics_service.ts | 9 ++------- src/core/server/metrics/ops_metrics_collector.ts | 2 +- src/core/server/server.ts | 5 +---- 6 files changed, 4 insertions(+), 24 deletions(-) diff --git a/src/core/server/metrics/collectors/os.ts b/src/core/server/metrics/collectors/os.ts index c4e30fc229a3..48808bfd8e79 100644 --- a/src/core/server/metrics/collectors/os.ts +++ b/src/core/server/metrics/collectors/os.ts @@ -16,7 +16,6 @@ import { OsCgroupMetricsCollector } from './cgroup'; const getos = promisify(getosAsync); export interface OpsMetricsCollectorOptions { - instanceUuid: string; logger: Logger; cpuPath?: string; cpuAcctPath?: string; diff --git a/src/core/server/metrics/collectors/process.ts b/src/core/server/metrics/collectors/process.ts index 9826071cebd8..8205de65a6b7 100644 --- a/src/core/server/metrics/collectors/process.ts +++ b/src/core/server/metrics/collectors/process.ts @@ -10,15 +10,7 @@ import v8 from 'v8'; import { OpsProcessMetrics, MetricsCollector } from './types'; import { EventLoopDelaysMonitor } from '../event_loop_delays'; -export interface ProcessMetricsCollectorOptions { - instanceUuid: string; -} - export class ProcessMetricsCollector implements MetricsCollector { - private readonly instanceUuid: string; - constructor({ instanceUuid }: ProcessMetricsCollectorOptions) { - this.instanceUuid = instanceUuid; - } static getMainThreadMetrics(processes: OpsProcessMetrics[]): undefined | OpsProcessMetrics { return processes.find(({ name }) => name === 'server_worker'); } @@ -41,7 +33,6 @@ export class ProcessMetricsCollector implements MetricsCollector { export interface OpsProcessMetrics { /** pid of the kibana process */ pid: number; - /** uuid of the kibana instance */ - instanceUuid: string; /** name of process (example: 'coordinator' | 'server_worker' | 'task_worker' | 'reporting_worker') */ name: 'coordinator' | 'server_worker'; /** process memory usage */ diff --git a/src/core/server/metrics/metrics_service.ts b/src/core/server/metrics/metrics_service.ts index 5c8c2a689a6e..8a0d6f17b446 100644 --- a/src/core/server/metrics/metrics_service.ts +++ b/src/core/server/metrics/metrics_service.ts @@ -20,7 +20,6 @@ import { InternalEnvironmentServiceSetup } from '../environment'; interface MetricsServiceSetupDeps { http: InternalHttpServiceSetup; - environment: InternalEnvironmentServiceSetup; } /** @internal */ @@ -38,18 +37,14 @@ export class MetricsService this.opsMetricsLogger = coreContext.logger.get('metrics', 'ops'); } - public async setup({ - http, - environment, - }: MetricsServiceSetupDeps): Promise { + public async setup({ http }: MetricsServiceSetupDeps): Promise { const config = await this.coreContext.configService .atPath(opsConfig.path) .pipe(first()) .toPromise(); - const { instanceUuid } = environment; + this.metricsCollector = new OpsMetricsCollector(http.server, { logger: this.logger, - instanceUuid, ...config.cGroupOverrides, }); diff --git a/src/core/server/metrics/ops_metrics_collector.ts b/src/core/server/metrics/ops_metrics_collector.ts index ae6bd6c01b68..98f78e4b1218 100644 --- a/src/core/server/metrics/ops_metrics_collector.ts +++ b/src/core/server/metrics/ops_metrics_collector.ts @@ -22,7 +22,7 @@ export class OpsMetricsCollector implements MetricsCollector { private readonly serverCollector: ServerMetricsCollector; constructor(server: HapiServer, opsOptions: OpsMetricsCollectorOptions) { - this.processCollector = new ProcessMetricsCollector(opsOptions); + this.processCollector = new ProcessMetricsCollector(); this.osCollector = new OsMetricsCollector(opsOptions); this.serverCollector = new ServerMetricsCollector(server); } diff --git a/src/core/server/server.ts b/src/core/server/server.ts index a1ee6201e91f..865cc71a7e26 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -216,10 +216,7 @@ export class Server { executionContext: executionContextSetup, }); - const metricsSetup = await this.metrics.setup({ - http: httpSetup, - environment: environmentSetup, - }); + const metricsSetup = await this.metrics.setup({ http: httpSetup }); const coreUsageDataSetup = this.coreUsageData.setup({ http: httpSetup, From b009fca39fe4e305786eb323e756d26296901b4f Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Sat, 11 Sep 2021 14:49:58 +0300 Subject: [PATCH 4/8] update event loop delays usage collection to include instance_uuid --- ...in-core-server.deprecationsservicesetup.md | 16 +++++++------- ...er.eventloopdelaysmonitor._constructor_.md | 2 +- ...e-server.eventloopdelaysmonitor.collect.md | 4 ++++ ...ugin-core-server.eventloopdelaysmonitor.md | 8 +++---- ...ore-server.eventloopdelaysmonitor.reset.md | 2 ++ ...core-server.eventloopdelaysmonitor.stop.md | 2 ++ ...na-plugin-core-server.intervalhistogram.md | 2 ++ .../core/server/kibana-plugin-core-server.md | 2 +- ...na-plugin-core-server.opsprocessmetrics.md | 1 - ...ugin-core-server.opsprocessmetrics.name.md | 13 ------------ .../core_app/status/lib/load_status.test.ts | 2 -- .../deprecations/deprecations_service.ts | 1 - .../metrics/collectors/process.mocks.ts | 1 - src/core/server/metrics/collectors/process.ts | 8 +++++-- src/core/server/metrics/collectors/types.ts | 2 -- .../event_loop_delays_monitor.ts | 21 ++++++++++++++++++- src/core/server/metrics/metrics_service.ts | 1 - src/core/server/server.api.md | 6 +----- .../integration_tests/daily_rollups.test.ts | 5 ++++- .../event_loop_delays/saved_objects.test.ts | 11 +++++----- .../event_loop_delays/saved_objects.ts | 20 +++++++++++++----- .../event_loop_delays/track_delays.test.ts | 7 +++++++ .../event_loop_delays/track_delays.ts | 3 ++- .../ops_stats_collector.test.ts.snap | 2 -- .../kibana_usage_collection/server/plugin.ts | 3 +++ 25 files changed, 87 insertions(+), 58 deletions(-) delete mode 100644 docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.name.md diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md index 00e5da4a9a9f..2bc7f6cba594 100644 --- a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md @@ -25,10 +25,9 @@ import { i18n } from '@kbn/i18n'; async function getDeprecations({ esClient, savedObjectsClient }: GetDeprecationsContext): Promise { const deprecations: DeprecationsDetails[] = []; - - // Example of an api correctiveAction const count = await getFooCount(savedObjectsClient); if (count > 0) { + // Example of a manual correctiveAction deprecations.push({ title: i18n.translate('xpack.foo.deprecations.title', { defaultMessage: `Foo's are deprecated` @@ -42,12 +41,12 @@ async function getDeprecations({ esClient, savedObjectsClient }: GetDeprecations level: 'warning', correctiveActions: { manualSteps: [ - i18n.translate('xpack.foo.deprecations.manualStepOneMessage', { - defaultMessage: 'Navigate to the Kibana Dashboard and click "Create dashboard".', - }), - i18n.translate('xpack.foo.deprecations.manualStepTwoMessage', { - defaultMessage: 'Select Foo from the "New Visualization" window.', - }), + i18n.translate('xpack.foo.deprecations.manualStepOneMessage', { + defaultMessage: 'Navigate to the Kibana Dashboard and click "Create dashboard".', + }), + i18n.translate('xpack.foo.deprecations.manualStepTwoMessage', { + defaultMessage: 'Select Foo from the "New Visualization" window.', + }), ], api: { path: '/internal/security/users/test_dashboard_user', @@ -68,7 +67,6 @@ async function getDeprecations({ esClient, savedObjectsClient }: GetDeprecations }, }); } - return deprecations; } 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 index 3a9efc0eacdb..ae9df8b406be 100644 --- a/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor._constructor_.md +++ b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor._constructor_.md @@ -4,7 +4,7 @@ ## EventLoopDelaysMonitor.(constructor) -Constructs a new instance of the `EventLoopDelaysMonitor` class +Creating a new instance from EventLoopDelaysMonitor will automatically start tracking event loop delays. Signature: 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 index 6277f5906723..0e07497baf88 100644 --- a/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.collect.md +++ b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.collect.md @@ -4,6 +4,8 @@ ## EventLoopDelaysMonitor.collect() method +Collect gathers event loop delays metrics from nodejs perf\_hooks.monitorEventLoopDelay the histogram calculations start from the last time `reset` was called or this EventLoopDelaysMonitor instance was created. + Signature: ```typescript @@ -13,3 +15,5 @@ collect(): IntervalHistogram; `IntervalHistogram` +{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 index 15d02ecd5f25..21bbd8b48840 100644 --- a/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.md +++ b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.md @@ -14,13 +14,13 @@ export declare class EventLoopDelaysMonitor | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)()](./kibana-plugin-core-server.eventloopdelaysmonitor._constructor_.md) | | Constructs a new instance of the EventLoopDelaysMonitor class | +| [(constructor)()](./kibana-plugin-core-server.eventloopdelaysmonitor._constructor_.md) | | Creating a new instance from EventLoopDelaysMonitor will automatically start tracking event loop delays. | ## 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) | | | +| [collect()](./kibana-plugin-core-server.eventloopdelaysmonitor.collect.md) | | Collect gathers event loop delays metrics from nodejs perf\_hooks.monitorEventLoopDelay the histogram calculations start from the last time reset was called or this EventLoopDelaysMonitor instance was created. | +| [reset()](./kibana-plugin-core-server.eventloopdelaysmonitor.reset.md) | | Resets the collected histogram data. | +| [stop()](./kibana-plugin-core-server.eventloopdelaysmonitor.stop.md) | | Disables updating the interval timer for collecting new data points. | 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 index c593d0341bbe..fdba7a79ebda 100644 --- a/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.reset.md +++ b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.reset.md @@ -4,6 +4,8 @@ ## EventLoopDelaysMonitor.reset() method +Resets the collected histogram data. + Signature: ```typescript 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 index 86e76d0c6fba..25b61434b006 100644 --- a/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.stop.md +++ b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.stop.md @@ -4,6 +4,8 @@ ## EventLoopDelaysMonitor.stop() method +Disables updating the interval timer for collecting new data points. + Signature: ```typescript diff --git a/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.md b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.md index 20f71420a0d8..d7fb889dce32 100644 --- a/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.md +++ b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.md @@ -4,6 +4,8 @@ ## IntervalHistogram interface +an IntervalHistogram object that samples and reports the event loop delay over time. The delays will be reported in nanoseconds. + Signature: ```typescript diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index a702c5fe7b97..66c0299669dc 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -98,7 +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) | | +| [IntervalHistogram](./kibana-plugin-core-server.intervalhistogram.md) | an IntervalHistogram object that samples and reports the event loop delay over time. The delays will be reported in nanoseconds. | | [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.opsprocessmetrics.md b/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.md index fdaaf594232f..198b668afca6 100644 --- a/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.md +++ b/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.md @@ -19,7 +19,6 @@ export interface OpsProcessMetrics | [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 deleted file mode 100644 index 72f98fb7e717..000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.opsprocessmetrics.name.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[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 7411cab5892a..73c697c3d55a 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 @@ -62,7 +62,6 @@ const mockedResponse: StatusResponse = { }, }, process: { - name: 'server_worker' as const, pid: 1, memory: { heap: { @@ -78,7 +77,6 @@ const mockedResponse: StatusResponse = { }, processes: [ { - name: 'server_worker' as const, pid: 1, memory: { heap: { diff --git a/src/core/server/deprecations/deprecations_service.ts b/src/core/server/deprecations/deprecations_service.ts index b8a134fbf8cd..bc981c21ba97 100644 --- a/src/core/server/deprecations/deprecations_service.ts +++ b/src/core/server/deprecations/deprecations_service.ts @@ -39,7 +39,6 @@ import { SavedObjectsClientContract } from '../saved_objects/types'; * const deprecations: DeprecationsDetails[] = []; * const count = await getFooCount(savedObjectsClient); * if (count > 0) { - * // Example of a manual correctiveAction * deprecations.push({ * title: i18n.translate('xpack.foo.deprecations.title', { * defaultMessage: `Foo's are deprecated` diff --git a/src/core/server/metrics/collectors/process.mocks.ts b/src/core/server/metrics/collectors/process.mocks.ts index e9c002f320fb..8ee43394b925 100644 --- a/src/core/server/metrics/collectors/process.mocks.ts +++ b/src/core/server/metrics/collectors/process.mocks.ts @@ -12,7 +12,6 @@ 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, diff --git a/src/core/server/metrics/collectors/process.ts b/src/core/server/metrics/collectors/process.ts index 8205de65a6b7..3acfda3e165e 100644 --- a/src/core/server/metrics/collectors/process.ts +++ b/src/core/server/metrics/collectors/process.ts @@ -12,7 +12,12 @@ import { EventLoopDelaysMonitor } from '../event_loop_delays'; export class ProcessMetricsCollector implements MetricsCollector { static getMainThreadMetrics(processes: OpsProcessMetrics[]): undefined | OpsProcessMetrics { - return processes.find(({ name }) => name === 'server_worker'); + /** + * Currently Kibana does not support multi-processes. + * Once we have multiple processes we can add a `name` field + * and filter on `name === 'server_worker'` to get the main thread. + */ + return processes[0]; } private readonly eventLoopDelayMonitor = new EventLoopDelaysMonitor(); @@ -23,7 +28,6 @@ export class ProcessMetricsCollector implements MetricsCollector { 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 */ diff --git a/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.ts b/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.ts index cf8f9e780e48..12063aa88550 100644 --- a/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.ts +++ b/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.ts @@ -9,6 +9,10 @@ import type { EventLoopDelayMonitor } from 'perf_hooks'; import { monitorEventLoopDelay } from 'perf_hooks'; +/** + * an IntervalHistogram object that samples and reports the event loop delay over time. + * The delays will be reported in nanoseconds. + */ export interface IntervalHistogram { fromTimestamp: string; lastUpdatedAt: string; @@ -29,13 +33,22 @@ export class EventLoopDelaysMonitor { private readonly loopMonitor: EventLoopDelayMonitor; private fromTimestamp: Date; + /** + * Creating a new instance from EventLoopDelaysMonitor will + * automatically start tracking event loop delays. + */ constructor() { const monitor = monitorEventLoopDelay(); monitor.enable(); this.fromTimestamp = new Date(); this.loopMonitor = monitor; } - + /** + * Collect gathers event loop delays metrics from nodejs perf_hooks.monitorEventLoopDelay + * the histogram calculations start from the last time `reset` was called or this + * EventLoopDelaysMonitor instance was created. + * @returns {IntervalHistogram} + */ public collect(): IntervalHistogram { const lastUpdated = new Date(); this.loopMonitor.disable(); @@ -61,11 +74,17 @@ export class EventLoopDelaysMonitor { return collectedData; } + /** + * Resets the collected histogram data. + */ public reset() { this.loopMonitor.reset(); this.fromTimestamp = new Date(); } + /** + * Disables updating the interval timer for collecting new data points. + */ public stop() { this.loopMonitor.disable(); } diff --git a/src/core/server/metrics/metrics_service.ts b/src/core/server/metrics/metrics_service.ts index 8a0d6f17b446..78e4dd98f93d 100644 --- a/src/core/server/metrics/metrics_service.ts +++ b/src/core/server/metrics/metrics_service.ts @@ -16,7 +16,6 @@ import { InternalMetricsServiceSetup, InternalMetricsServiceStart, OpsMetrics } import { OpsMetricsCollector } from './ops_metrics_collector'; import { opsConfig, OpsConfigType } from './ops_config'; import { getEcsOpsMetricsLog } from './logging'; -import { InternalEnvironmentServiceSetup } from '../environment'; interface MetricsServiceSetupDeps { http: InternalHttpServiceSetup; diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 5fca11e7856c..476777e43684 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -943,11 +943,8 @@ export interface ErrorHttpResponseOptions { // @public (undocumented) export class EventLoopDelaysMonitor { constructor(); - // (undocumented) collect(): IntervalHistogram; - // (undocumented) reset(): void; - // (undocumented) stop(): void; } @@ -1186,7 +1183,7 @@ export interface IKibanaSocket { // 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) +// @public export interface IntervalHistogram { // (undocumented) exceeds: number; @@ -1548,7 +1545,6 @@ export interface OpsProcessMetrics { }; resident_set_size_in_bytes: number; }; - name: 'coordinator' | 'server_worker'; pid: number; uptime_in_millis: number; } 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 499227d796f1..64668a5f23de 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 @@ -29,14 +29,17 @@ const { startES } = createTestServers({ const eventLoopDelaysMonitor = metricsServiceMock.createEventLoopDelaysMonitor(); function createRawObject(date: moment.MomentInput) { const pid = Math.round(Math.random() * 10000); + const instanceUuid = 'mock_instance'; + return { type: SAVED_OBJECTS_DAILY_TYPE, - id: serializeSavedObjectId({ pid, date }), + id: serializeSavedObjectId({ pid, date, instanceUuid }), attributes: { ...eventLoopDelaysMonitor.collect(), fromTimestamp: moment(date).startOf('day').toISOString(), lastUpdatedAt: moment(date).toISOString(), processId: pid, + instanceUuid, }, }; } 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 ee610d918d61..ddae0ff30282 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 @@ -16,8 +16,8 @@ import type { SavedObjectsFindResponse } from '../../../../../core/server/'; describe('serializeSavedObjectId', () => { it('returns serialized id', () => { - const id = serializeSavedObjectId({ date: 1623233091278, pid: 123 }); - expect(id).toBe('123::09062021'); + const id = serializeSavedObjectId({ instanceUuid: 'mock_uuid', date: 1623233091278, pid: 123 }); + expect(id).toBe('mock_uuid::123::09062021'); }); }); @@ -33,13 +33,14 @@ describe('storeHistogram', () => { it('stores histogram data in a savedObject', async () => { const mockHistogram = eventLoopDelaysMonitor.collect(); - await storeHistogram(mockHistogram, mockInternalRepository); + const instanceUuid = 'mock_uuid'; + await storeHistogram(mockHistogram, mockInternalRepository, instanceUuid); const pid = process.pid; - const id = serializeSavedObjectId({ date: mockNow, pid }); + const id = serializeSavedObjectId({ date: mockNow, pid, instanceUuid }); expect(mockInternalRepository.create).toBeCalledWith( 'event_loop_delays_daily', - { ...mockHistogram, processId: pid }, + { ...mockHistogram, processId: pid, instanceUuid }, { id, overwrite: true } ); }); 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 b66451d1fb76..57a9bb3b739c 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 @@ -17,6 +17,7 @@ export const SAVED_OBJECTS_DAILY_TYPE = 'event_loop_delays_daily'; export interface EventLoopDelaysDaily extends SavedObjectAttributes, IntervalHistogram { processId: number; + instanceUuid: string; } export function registerSavedObjectTypes(registerType: SavedObjectsServiceSetup['registerType']) { @@ -34,10 +35,18 @@ export function registerSavedObjectTypes(registerType: SavedObjectsServiceSetup[ }); } -export function serializeSavedObjectId({ date, pid }: { date: moment.MomentInput; pid: number }) { +export function serializeSavedObjectId({ + date, + pid, + instanceUuid, +}: { + date: moment.MomentInput; + pid: number; + instanceUuid: string; +}) { const formattedDate = moment(date).format('DDMMYYYY'); - return `${pid}::${formattedDate}`; + return `${instanceUuid}::${pid}::${formattedDate}`; } export async function deleteHistogramSavedObjects( @@ -58,14 +67,15 @@ export async function deleteHistogramSavedObjects( export async function storeHistogram( histogram: IntervalHistogram, - internalRepository: ISavedObjectsRepository + internalRepository: ISavedObjectsRepository, + instanceUuid: string ) { const pid = process.pid; - const id = serializeSavedObjectId({ date: histogram.lastUpdatedAt, pid }); + const id = serializeSavedObjectId({ date: histogram.lastUpdatedAt, pid, instanceUuid }); return await internalRepository.create( SAVED_OBJECTS_DAILY_TYPE, - { ...histogram, processId: pid }, + { ...histogram, processId: pid, instanceUuid }, { id, overwrite: true } ); } 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 ea8309cff31e..92549b926eaf 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 @@ -14,6 +14,8 @@ describe('startTrackingEventLoopDelaysUsage', () => { const eventLoopDelaysMonitor = metricsServiceMock.createEventLoopDelaysMonitor(); const mockInternalRepository = savedObjectsRepositoryMock.create(); const stopMonitoringEventLoop$ = new Subject(); + const instanceUuid = 'mock_uuid'; + beforeAll(() => jest.useFakeTimers('modern')); beforeEach(() => jest.clearAllMocks()); afterEach(() => stopMonitoringEventLoop$.next()); @@ -22,6 +24,7 @@ describe('startTrackingEventLoopDelaysUsage', () => { const collectionStartDelay = 1000; startTrackingEventLoopDelaysUsage( mockInternalRepository, + instanceUuid, stopMonitoringEventLoop$, eventLoopDelaysMonitor, { @@ -39,6 +42,7 @@ describe('startTrackingEventLoopDelaysUsage', () => { const collectionInterval = 1000; startTrackingEventLoopDelaysUsage( mockInternalRepository, + instanceUuid, stopMonitoringEventLoop$, eventLoopDelaysMonitor, { @@ -60,8 +64,10 @@ describe('startTrackingEventLoopDelaysUsage', () => { const collectionStartDelay = 0; const collectionInterval = 1000; const histogramReset = 5000; + startTrackingEventLoopDelaysUsage( mockInternalRepository, + instanceUuid, stopMonitoringEventLoop$, eventLoopDelaysMonitor, { @@ -81,6 +87,7 @@ describe('startTrackingEventLoopDelaysUsage', () => { it('stops monitoring event loop delays once stopMonitoringEventLoop$.next is called', () => { startTrackingEventLoopDelaysUsage( mockInternalRepository, + instanceUuid, stopMonitoringEventLoop$, eventLoopDelaysMonitor ); 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 d5006c801bdd..facdb549d0df 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 @@ -24,6 +24,7 @@ import { storeHistogram } from './saved_objects'; */ export function startTrackingEventLoopDelaysUsage( internalRepository: ISavedObjectsRepository, + instanceUuid: string, stopMonitoringEventLoop$: Observable, eventLoopDelaysMonitor: EventLoopDelaysMonitor, configs: { @@ -51,6 +52,6 @@ export function startTrackingEventLoopDelaysUsage( if (shouldReset) { eventLoopDelaysMonitor.reset(); } - await storeHistogram(histogram, internalRepository); + await storeHistogram(histogram, internalRepository, instanceUuid); }); } 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 index 69176fef2f4a..f962eca85819 100644 --- 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 @@ -29,7 +29,6 @@ Object { }, "resident_set_size_in_bytes": 1, }, - "name": "server_worker", "uptime_in_millis": 1, }, "processes": Array [ @@ -44,7 +43,6 @@ Object { }, "resident_set_size_in_bytes": 1, }, - "name": "server_worker", "uptime_in_millis": 1, }, ], diff --git a/src/plugins/kibana_usage_collection/server/plugin.ts b/src/plugins/kibana_usage_collection/server/plugin.ts index 2363dd8671ae..07a70dfd56fb 100644 --- a/src/plugins/kibana_usage_collection/server/plugin.ts +++ b/src/plugins/kibana_usage_collection/server/plugin.ts @@ -56,6 +56,7 @@ type SavedObjectsRegisterType = SavedObjectsServiceSetup['registerType']; export class KibanaUsageCollectionPlugin implements Plugin { private readonly logger: Logger; private readonly legacyConfig$: Observable; + private readonly instanceUuid: string; private savedObjectsClient?: ISavedObjectsRepository; private uiSettingsClient?: IUiSettingsClient; private metric$: Subject; @@ -68,6 +69,7 @@ export class KibanaUsageCollectionPlugin implements Plugin { this.legacyConfig$ = initializerContext.config.legacy.globalConfig$; this.metric$ = new Subject(); this.pluginStop$ = new Subject(); + this.instanceUuid = initializerContext.env.instanceUuid; } public setup(coreSetup: CoreSetup, { usageCollection }: KibanaUsageCollectionPluginsDepsSetup) { @@ -95,6 +97,7 @@ export class KibanaUsageCollectionPlugin implements Plugin { this.coreUsageData = core.coreUsageData; startTrackingEventLoopDelaysUsage( this.savedObjectsClient, + this.instanceUuid, this.pluginStop$.asObservable(), new EventLoopDelaysMonitor() ); From 4ae05114991951d03f34a613ac1b0e0b9cd3ce1f Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Sat, 11 Sep 2021 14:53:36 +0300 Subject: [PATCH 5/8] remove extra comment in docs --- .../server/kibana-plugin-core-server.deprecationsservicesetup.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md index 2bc7f6cba594..7b2cbdecd146 100644 --- a/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.deprecationsservicesetup.md @@ -27,7 +27,6 @@ async function getDeprecations({ esClient, savedObjectsClient }: GetDeprecations const deprecations: DeprecationsDetails[] = []; const count = await getFooCount(savedObjectsClient); if (count > 0) { - // Example of a manual correctiveAction deprecations.push({ title: i18n.translate('xpack.foo.deprecations.title', { defaultMessage: `Foo's are deprecated` From a1c48fe68ba0bbbfa417dfd227913e592ed10d45 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Sat, 11 Sep 2021 15:20:13 +0300 Subject: [PATCH 6/8] update documentation --- src/core/server/metrics/collectors/types.ts | 2 +- .../event_loop_delays_monitor.mocks.ts | 2 +- .../event_loop_delays_monitor.ts | 21 +----------- .../server/metrics/event_loop_delays/index.ts | 1 - src/core/server/metrics/index.ts | 2 +- src/core/server/metrics/types.ts | 34 +++++++++++++++++++ src/core/server/server.api.md | 2 -- 7 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/core/server/metrics/collectors/types.ts b/src/core/server/metrics/collectors/types.ts index 9306dbb1dd9c..1f1a48bae754 100644 --- a/src/core/server/metrics/collectors/types.ts +++ b/src/core/server/metrics/collectors/types.ts @@ -5,7 +5,7 @@ * 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'; +import type { IntervalHistogram } from '../types'; /** Base interface for all metrics gatherers */ export interface MetricsCollector { diff --git a/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.mocks.ts b/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.mocks.ts index 66daf8fce3f5..9069078fffec 100644 --- a/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.mocks.ts +++ b/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.mocks.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ import moment from 'moment'; -import type { IntervalHistogram } from 'kibana/server'; import type { EventLoopDelaysMonitor } from './event_loop_delays_monitor'; +import type { IntervalHistogram } from '../types'; function createMockHistogram(overwrites: Partial = {}): IntervalHistogram { const now = moment(); diff --git a/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.ts b/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.ts index 12063aa88550..3dff847f83c9 100644 --- a/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.ts +++ b/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.ts @@ -8,26 +8,7 @@ import type { EventLoopDelayMonitor } from 'perf_hooks'; import { monitorEventLoopDelay } from 'perf_hooks'; - -/** - * an IntervalHistogram object that samples and reports the event loop delay over time. - * The delays will be reported in nanoseconds. - */ -export interface IntervalHistogram { - fromTimestamp: string; - lastUpdatedAt: string; - min: number; - max: number; - mean: number; - exceeds: number; - stddev: number; - percentiles: { - 50: number; - 75: number; - 95: number; - 99: number; - }; -} +import type { IntervalHistogram } from '../types'; export class EventLoopDelaysMonitor { private readonly loopMonitor: EventLoopDelayMonitor; diff --git a/src/core/server/metrics/event_loop_delays/index.ts b/src/core/server/metrics/event_loop_delays/index.ts index 50d2e35e388e..bc9cda18d443 100644 --- a/src/core/server/metrics/event_loop_delays/index.ts +++ b/src/core/server/metrics/event_loop_delays/index.ts @@ -7,4 +7,3 @@ */ 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 63e475a25918..797a0ae8c3f0 100644 --- a/src/core/server/metrics/index.ts +++ b/src/core/server/metrics/index.ts @@ -12,10 +12,10 @@ export type { MetricsServiceSetup, MetricsServiceStart, OpsMetrics, + IntervalHistogram, } from './types'; export type { OpsProcessMetrics, OpsServerMetrics, OpsOsMetrics } from './collectors'; 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/types.ts b/src/core/server/metrics/types.ts index 8beeae2ff7ad..c6a846cf91b6 100644 --- a/src/core/server/metrics/types.ts +++ b/src/core/server/metrics/types.ts @@ -67,3 +67,37 @@ export interface OpsMetrics { /** number of current concurrent connections to the server */ concurrent_connections: OpsServerMetrics['concurrent_connections']; } + +/** + * an IntervalHistogram object that samples and reports the event loop delay over time. + * The delays will be reported in nanoseconds. + * + * @public + */ +export interface IntervalHistogram { + // The first timestamp the interval timer kicked in for collecting data points. + fromTimestamp: string; + // Last timestamp the interval timer kicked in for collecting data points. + lastUpdatedAt: string; + // The minimum recorded event loop delay. + min: number; + // The maximum recorded event loop delay. + max: number; + // The mean of the recorded event loop delays. + mean: number; + // The number of times the event loop delay exceeded the maximum 1 hour event loop delay threshold. + exceeds: number; + // The standard deviation of the recorded event loop delays. + stddev: number; + // An object detailing the accumulated percentile distribution. + percentiles: { + // 50th percentile of delays of the collected data points. + 50: number; + // 75th percentile of delays of the collected data points. + 75: number; + // 95th percentile of delays of the collected data points. + 95: number; + // 99th percentile of delays of the collected data points. + 99: number; + }; +} diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 476777e43684..ea2b9dde949b 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -1181,8 +1181,6 @@ 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 export interface IntervalHistogram { // (undocumented) From c5ba74a9a47c90942408e8ad35997b8893589648 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Sat, 11 Sep 2021 17:26:49 +0300 Subject: [PATCH 7/8] update telemetry schema --- .../server/collectors/event_loop_delays/schema.ts | 7 +++++++ src/plugins/telemetry/schema/oss_plugins.json | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/schema.ts index 319e8c77438b..757e96e5602f 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/schema.ts @@ -11,6 +11,7 @@ import { MakeSchemaFrom } from 'src/plugins/usage_collection/server'; export interface EventLoopDelaysUsageReport { daily: Array<{ processId: number; + instanceUuid: string; lastUpdatedAt: string; fromTimestamp: string; min: number; @@ -37,6 +38,12 @@ export const eventLoopDelaysUsageSchema: MakeSchemaFrom Date: Mon, 13 Sep 2021 15:50:38 +0300 Subject: [PATCH 8/8] core review fixes --- src/core/server/metrics/collectors/types.ts | 3 ++- .../event_loop_delays/__mocks__/perf_hooks.ts | 20 ++++++++++--------- .../event_loop_delays_monitor.mocks.ts | 6 +++--- .../event_loop_delays_monitor.test.ts | 18 ++++++----------- .../server/metrics/ops_metrics_collector.ts | 5 +++++ src/core/server/metrics/types.ts | 4 ++-- 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/core/server/metrics/collectors/types.ts b/src/core/server/metrics/collectors/types.ts index 1f1a48bae754..4684e8008f4d 100644 --- a/src/core/server/metrics/collectors/types.ts +++ b/src/core/server/metrics/collectors/types.ts @@ -5,12 +5,13 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ +import { MaybePromise } from '@kbn/utility-types'; import type { IntervalHistogram } from '../types'; /** Base interface for all metrics gatherers */ export interface MetricsCollector { /** collect the data currently gathered by the collector */ - collect(): Promise | T; + collect(): MaybePromise; /** reset the internal state of the collector */ reset(): void; } 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 index 7ebc92671361..2a5477a1c4e9 100644 --- a/src/core/server/metrics/event_loop_delays/__mocks__/perf_hooks.ts +++ b/src/core/server/metrics/event_loop_delays/__mocks__/perf_hooks.ts @@ -8,14 +8,16 @@ 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().mockImplementation(() => { + const mockedHistogram = mocked.createHistogram(); -export const monitorEventLoopDelay = jest.fn().mockReturnValue({ - ...mockMonitor, - ...mocked.createHistogram(), + return { + ...mockedHistogram, + enable: jest.fn(), + percentile: jest.fn().mockImplementation((percentile: number) => { + return (mockedHistogram.percentiles as Record)[`${percentile}`]; + }), + disable: jest.fn(), + reset: jest.fn(), + }; }); diff --git a/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.mocks.ts b/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.mocks.ts index 9069078fffec..ee96668cf3e7 100644 --- a/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.mocks.ts +++ b/src/core/server/metrics/event_loop_delays/event_loop_delays_monitor.mocks.ts @@ -10,7 +10,7 @@ import type { EventLoopDelaysMonitor } from './event_loop_delays_monitor'; import type { IntervalHistogram } from '../types'; function createMockHistogram(overwrites: Partial = {}): IntervalHistogram { - const now = moment(); + const now = Date.now(); return { min: 9093120, @@ -18,8 +18,8 @@ function createMockHistogram(overwrites: Partial = {}): Inter mean: 11993238.600747818, exceeds: 0, stddev: 1168191.9357543814, - fromTimestamp: now.startOf('day').toISOString(), - lastUpdatedAt: now.toISOString(), + fromTimestamp: moment(now).toISOString(), + lastUpdatedAt: moment(now).toISOString(), percentiles: { '50': 12607487, '75': 12615679, 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 index fbb1fbba617a..3e88dbca8f4e 100644 --- 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 @@ -10,6 +10,7 @@ jest.mock('perf_hooks'); import { monitorEventLoopDelay } from 'perf_hooks'; import { EventLoopDelaysMonitor } from './event_loop_delays_monitor'; +import { mocked } from './event_loop_delays_monitor.mocks'; describe('EventLoopDelaysMonitor', () => { beforeAll(() => { @@ -38,19 +39,12 @@ describe('EventLoopDelaysMonitor', () => { 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", - ] - `); + // mocked perf_hook returns `mocked.createHistogram()`. + // This ensures that the wiring of the `collect` function is correct. + const mockedHistogram = mocked.createHistogram(); + expect(histogramData).toEqual(mockedHistogram); }); + test('#reset resets histogram data', () => { const eventLoopDelaysMonitor = new EventLoopDelaysMonitor(); eventLoopDelaysMonitor.reset(); diff --git a/src/core/server/metrics/ops_metrics_collector.ts b/src/core/server/metrics/ops_metrics_collector.ts index 98f78e4b1218..376b10dcccdd 100644 --- a/src/core/server/metrics/ops_metrics_collector.ts +++ b/src/core/server/metrics/ops_metrics_collector.ts @@ -36,6 +36,11 @@ export class OpsMetricsCollector implements MetricsCollector { return { collected_at: new Date(), + /** + * Kibana does not yet support multi-process nodes. + * `processes` is just an Array(1) only returning the current process's data + * which is why we can just use processes[0] for `process` + */ process: processes[0], processes, os, diff --git a/src/core/server/metrics/types.ts b/src/core/server/metrics/types.ts index c6a846cf91b6..550a60d0d295 100644 --- a/src/core/server/metrics/types.ts +++ b/src/core/server/metrics/types.ts @@ -52,8 +52,8 @@ export interface OpsMetrics { /** Time metrics were recorded at. */ collected_at: Date; /** - * Process related metrics. Deprecated in favor of processes field. - * @deprecated + * Process related metrics. + * @deprecated use the processes field instead. */ process: OpsProcessMetrics; /** Process related metrics. Reports an array of objects for each kibana pid.*/