diff --git a/docs/apm/troubleshooting.asciidoc b/docs/apm/troubleshooting.asciidoc
index 65f7a378ec244..e00a67f6c78a4 100644
--- a/docs/apm/troubleshooting.asciidoc
+++ b/docs/apm/troubleshooting.asciidoc
@@ -49,7 +49,7 @@ GET /_template/apm-{version}
*Using Logstash, Kafka, etc.*
If you're not outputting data directly from APM Server to Elasticsearch (perhaps you're using Logstash or Kafka),
then the index template will not be set up automatically. Instead, you'll need to
-{apm-server-ref}/_manually_loading_template_configuration.html[load the template manually].
+{apm-server-ref}/configuration-template.html[load the template manually].
*Using a custom index names*
This problem can also occur if you've customized the index name that you write APM data to.
diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md
index 89330d2a86f76..c16600d1d0492 100644
--- a/docs/development/core/server/kibana-plugin-core-server.md
+++ b/docs/development/core/server/kibana-plugin-core-server.md
@@ -28,6 +28,7 @@ The plugin integrates with the core system via lifecycle events: `setup`
| [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md) | |
| [SavedObjectsRepository](./kibana-plugin-core-server.savedobjectsrepository.md) | |
| [SavedObjectsSerializer](./kibana-plugin-core-server.savedobjectsserializer.md) | A serializer that can be used to manually convert [raw](./kibana-plugin-core-server.savedobjectsrawdoc.md) or [sanitized](./kibana-plugin-core-server.savedobjectsanitizeddoc.md) documents to the other kind. |
+| [SavedObjectsUtils](./kibana-plugin-core-server.savedobjectsutils.md) | |
| [SavedObjectTypeRegistry](./kibana-plugin-core-server.savedobjecttyperegistry.md) | Registry holding information about all the registered [saved object types](./kibana-plugin-core-server.savedobjectstype.md). |
## Enumerations
@@ -123,7 +124,7 @@ The plugin integrates with the core system via lifecycle events: `setup`
| [LoggerFactory](./kibana-plugin-core-server.loggerfactory.md) | The single purpose of LoggerFactory
interface is to define a way to retrieve a context-based logger instance. |
| [LoggingServiceSetup](./kibana-plugin-core-server.loggingservicesetup.md) | Provides APIs to plugins for customizing the plugin's logger. |
| [LogMeta](./kibana-plugin-core-server.logmeta.md) | Contextual metadata |
-| [MetricsServiceSetup](./kibana-plugin-core-server.metricsservicesetup.md) | |
+| [MetricsServiceSetup](./kibana-plugin-core-server.metricsservicesetup.md) | APIs to retrieves metrics gathered and exposed by the core platform. |
| [NodesVersionCompatibility](./kibana-plugin-core-server.nodesversioncompatibility.md) | |
| [OnPostAuthToolkit](./kibana-plugin-core-server.onpostauthtoolkit.md) | A tool set defining an outcome of OnPostAuth interceptor for incoming request. |
| [OnPreAuthToolkit](./kibana-plugin-core-server.onpreauthtoolkit.md) | A tool set defining an outcome of OnPreAuth interceptor for incoming request. |
diff --git a/docs/development/core/server/kibana-plugin-core-server.metricsservicesetup.collectioninterval.md b/docs/development/core/server/kibana-plugin-core-server.metricsservicesetup.collectioninterval.md
new file mode 100644
index 0000000000000..6f05526b66c83
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-core-server.metricsservicesetup.collectioninterval.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [MetricsServiceSetup](./kibana-plugin-core-server.metricsservicesetup.md) > [collectionInterval](./kibana-plugin-core-server.metricsservicesetup.collectioninterval.md)
+
+## MetricsServiceSetup.collectionInterval property
+
+Interval metrics are collected in milliseconds
+
+Signature:
+
+```typescript
+readonly collectionInterval: number;
+```
diff --git a/docs/development/core/server/kibana-plugin-core-server.metricsservicesetup.getopsmetrics_.md b/docs/development/core/server/kibana-plugin-core-server.metricsservicesetup.getopsmetrics_.md
new file mode 100644
index 0000000000000..61107fbf20ad9
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-core-server.metricsservicesetup.getopsmetrics_.md
@@ -0,0 +1,24 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [MetricsServiceSetup](./kibana-plugin-core-server.metricsservicesetup.md) > [getOpsMetrics$](./kibana-plugin-core-server.metricsservicesetup.getopsmetrics_.md)
+
+## MetricsServiceSetup.getOpsMetrics$ property
+
+Retrieve an observable emitting the [OpsMetrics](./kibana-plugin-core-server.opsmetrics.md) gathered. The observable will emit an initial value during core's `start` phase, and a new value every fixed interval of time, based on the `opts.interval` configuration property.
+
+Signature:
+
+```typescript
+getOpsMetrics$: () => Observable;
+```
+
+## Example
+
+
+```ts
+core.metrics.getOpsMetrics$().subscribe(metrics => {
+ // do something with the metrics
+})
+
+```
+
diff --git a/docs/development/core/server/kibana-plugin-core-server.metricsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.metricsservicesetup.md
index 0bec919797b6f..5fcb1417dea0e 100644
--- a/docs/development/core/server/kibana-plugin-core-server.metricsservicesetup.md
+++ b/docs/development/core/server/kibana-plugin-core-server.metricsservicesetup.md
@@ -4,8 +4,18 @@
## MetricsServiceSetup interface
+APIs to retrieves metrics gathered and exposed by the core platform.
+
Signature:
```typescript
export interface MetricsServiceSetup
```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [collectionInterval](./kibana-plugin-core-server.metricsservicesetup.collectioninterval.md) | number
| Interval metrics are collected in milliseconds |
+| [getOpsMetrics$](./kibana-plugin-core-server.metricsservicesetup.getopsmetrics_.md) | () => Observable<OpsMetrics>
| Retrieve an observable emitting the [OpsMetrics](./kibana-plugin-core-server.opsmetrics.md) gathered. The observable will emit an initial value during core's start
phase, and a new value every fixed interval of time, based on the opts.interval
configuration property. |
+
diff --git a/docs/development/core/server/kibana-plugin-core-server.opsmetrics.collected_at.md b/docs/development/core/server/kibana-plugin-core-server.opsmetrics.collected_at.md
new file mode 100644
index 0000000000000..25125569b7b38
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-core-server.opsmetrics.collected_at.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [OpsMetrics](./kibana-plugin-core-server.opsmetrics.md) > [collected\_at](./kibana-plugin-core-server.opsmetrics.collected_at.md)
+
+## OpsMetrics.collected\_at property
+
+Time metrics were recorded at.
+
+Signature:
+
+```typescript
+collected_at: Date;
+```
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 d2d4782385c06..9803c0fbd53cc 100644
--- a/docs/development/core/server/kibana-plugin-core-server.opsmetrics.md
+++ b/docs/development/core/server/kibana-plugin-core-server.opsmetrics.md
@@ -16,6 +16,7 @@ export interface OpsMetrics
| Property | Type | Description |
| --- | --- | --- |
+| [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 |
diff --git a/docs/development/core/server/kibana-plugin-core-server.opsosmetrics.cpu.md b/docs/development/core/server/kibana-plugin-core-server.opsosmetrics.cpu.md
new file mode 100644
index 0000000000000..095c45266a251
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-core-server.opsosmetrics.cpu.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [OpsOsMetrics](./kibana-plugin-core-server.opsosmetrics.md) > [cpu](./kibana-plugin-core-server.opsosmetrics.cpu.md)
+
+## OpsOsMetrics.cpu property
+
+cpu cgroup metrics, undefined when not running in a cgroup
+
+Signature:
+
+```typescript
+cpu?: {
+ control_group: string;
+ cfs_period_micros: number;
+ cfs_quota_micros: number;
+ stat: {
+ number_of_elapsed_periods: number;
+ number_of_times_throttled: number;
+ time_throttled_nanos: number;
+ };
+ };
+```
diff --git a/docs/development/core/server/kibana-plugin-core-server.opsosmetrics.cpuacct.md b/docs/development/core/server/kibana-plugin-core-server.opsosmetrics.cpuacct.md
new file mode 100644
index 0000000000000..140646a0d1a35
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-core-server.opsosmetrics.cpuacct.md
@@ -0,0 +1,16 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [OpsOsMetrics](./kibana-plugin-core-server.opsosmetrics.md) > [cpuacct](./kibana-plugin-core-server.opsosmetrics.cpuacct.md)
+
+## OpsOsMetrics.cpuacct property
+
+cpu accounting metrics, undefined when not running in a cgroup
+
+Signature:
+
+```typescript
+cpuacct?: {
+ control_group: string;
+ usage_nanos: number;
+ };
+```
diff --git a/docs/development/core/server/kibana-plugin-core-server.opsosmetrics.md b/docs/development/core/server/kibana-plugin-core-server.opsosmetrics.md
index 5fedb76a9c8d7..8938608531139 100644
--- a/docs/development/core/server/kibana-plugin-core-server.opsosmetrics.md
+++ b/docs/development/core/server/kibana-plugin-core-server.opsosmetrics.md
@@ -16,6 +16,8 @@ export interface OpsOsMetrics
| Property | Type | Description |
| --- | --- | --- |
+| [cpu](./kibana-plugin-core-server.opsosmetrics.cpu.md) | {
control_group: string;
cfs_period_micros: number;
cfs_quota_micros: number;
stat: {
number_of_elapsed_periods: number;
number_of_times_throttled: number;
time_throttled_nanos: number;
};
}
| cpu cgroup metrics, undefined when not running in a cgroup |
+| [cpuacct](./kibana-plugin-core-server.opsosmetrics.cpuacct.md) | {
control_group: string;
usage_nanos: number;
}
| cpu accounting metrics, undefined when not running in a cgroup |
| [distro](./kibana-plugin-core-server.opsosmetrics.distro.md) | string
| The os distrib. Only present for linux platforms |
| [distroRelease](./kibana-plugin-core-server.opsosmetrics.distrorelease.md) | string
| The os distrib release, prefixed by the os distrib. Only present for linux platforms |
| [load](./kibana-plugin-core-server.opsosmetrics.load.md) | {
'1m': number;
'5m': number;
'15m': number;
}
| cpu load metrics |
diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkupdateobject.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkupdateobject.md
index e079e0fa51aac..d71eda6009284 100644
--- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkupdateobject.md
+++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkupdateobject.md
@@ -17,5 +17,6 @@ export interface SavedObjectsBulkUpdateObject extends PickPartial<T> | The data for a Saved Object is stored as an object in the attributes
property. |
| [id](./kibana-plugin-core-server.savedobjectsbulkupdateobject.id.md) | string
| The ID of this Saved Object, guaranteed to be unique for all objects of the same type
|
+| [namespace](./kibana-plugin-core-server.savedobjectsbulkupdateobject.namespace.md) | string
| Optional namespace string to use when searching for this object. If this is defined, it will supersede the namespace ID that is in [SavedObjectsBulkUpdateOptions](./kibana-plugin-core-server.savedobjectsbulkupdateoptions.md).Note: the default namespace's string representation is 'default'
, and its ID representation is undefined
. |
| [type](./kibana-plugin-core-server.savedobjectsbulkupdateobject.type.md) | string
| The type of this Saved Object. Each plugin can define it's own custom Saved Object types. |
diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkupdateobject.namespace.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkupdateobject.namespace.md
new file mode 100644
index 0000000000000..544efcd3be909
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkupdateobject.namespace.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsBulkUpdateObject](./kibana-plugin-core-server.savedobjectsbulkupdateobject.md) > [namespace](./kibana-plugin-core-server.savedobjectsbulkupdateobject.namespace.md)
+
+## SavedObjectsBulkUpdateObject.namespace property
+
+Optional namespace string to use when searching for this object. If this is defined, it will supersede the namespace ID that is in [SavedObjectsBulkUpdateOptions](./kibana-plugin-core-server.savedobjectsbulkupdateoptions.md).
+
+Note: the default namespace's string representation is `'default'`, and its ID representation is `undefined`.
+
+Signature:
+
+```typescript
+namespace?: string;
+```
diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md
index 6ef7b991bb159..650459bfdb435 100644
--- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md
+++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md
@@ -16,8 +16,6 @@ export interface SavedObjectsServiceSetup
When plugins access the Saved Objects client, a new client is created using the factory provided to `setClientFactory` and wrapped by all wrappers registered through `addClientWrapper`.
-All the setup APIs will throw if called after the service has started, and therefor cannot be used from legacy plugin code. Legacy plugins should use the legacy savedObject service until migrated.
-
## Example 1
diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md
index 57c9e04966c1b..54e01d3110a2d 100644
--- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md
+++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md
@@ -14,10 +14,6 @@ See the [mappings format](./kibana-plugin-core-server.savedobjectstypemappingdef
registerType: (type: SavedObjectsType) => void;
```
-## Remarks
-
-The type definition is an aggregation of the legacy savedObjects `schema`, `mappings` and `migration` concepts. This API is the single entry point to register saved object types in the new platform.
-
## Example
diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.md
new file mode 100644
index 0000000000000..e365dfbcb5142
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.md
@@ -0,0 +1,20 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsUtils](./kibana-plugin-core-server.savedobjectsutils.md)
+
+## SavedObjectsUtils class
+
+
+Signature:
+
+```typescript
+export declare class SavedObjectsUtils
+```
+
+## Properties
+
+| Property | Modifiers | Type | Description |
+| --- | --- | --- | --- |
+| [namespaceIdToString](./kibana-plugin-core-server.savedobjectsutils.namespaceidtostring.md) | static
| (namespace?: string | undefined) => string
| Converts a given saved object namespace ID to its string representation. All namespace IDs have an identical string representation, with the exception of the undefined
namespace ID (which has a namespace string of 'default'
). |
+| [namespaceStringToId](./kibana-plugin-core-server.savedobjectsutils.namespacestringtoid.md) | static
| (namespace: string) => string | undefined
| Converts a given saved object namespace string to its ID representation. All namespace strings have an identical ID representation, with the exception of the 'default'
namespace string (which has a namespace ID of undefined
). |
+
diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.namespaceidtostring.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.namespaceidtostring.md
new file mode 100644
index 0000000000000..591505892e64f
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.namespaceidtostring.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsUtils](./kibana-plugin-core-server.savedobjectsutils.md) > [namespaceIdToString](./kibana-plugin-core-server.savedobjectsutils.namespaceidtostring.md)
+
+## SavedObjectsUtils.namespaceIdToString property
+
+Converts a given saved object namespace ID to its string representation. All namespace IDs have an identical string representation, with the exception of the `undefined` namespace ID (which has a namespace string of `'default'`).
+
+Signature:
+
+```typescript
+static namespaceIdToString: (namespace?: string | undefined) => string;
+```
diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.namespacestringtoid.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.namespacestringtoid.md
new file mode 100644
index 0000000000000..e052fe493b5ea
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsutils.namespacestringtoid.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsUtils](./kibana-plugin-core-server.savedobjectsutils.md) > [namespaceStringToId](./kibana-plugin-core-server.savedobjectsutils.namespacestringtoid.md)
+
+## SavedObjectsUtils.namespaceStringToId property
+
+Converts a given saved object namespace string to its ID representation. All namespace strings have an identical ID representation, with the exception of the `'default'` namespace string (which has a namespace ID of `undefined`).
+
+Signature:
+
+```typescript
+static namespaceStringToId: (namespace: string) => string | undefined;
+```
diff --git a/docs/development/core/server/kibana-plugin-core-server.statusservicesetup.dependencies_.md b/docs/development/core/server/kibana-plugin-core-server.statusservicesetup.dependencies_.md
new file mode 100644
index 0000000000000..7475f0e3a4c1c
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-core-server.statusservicesetup.dependencies_.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [StatusServiceSetup](./kibana-plugin-core-server.statusservicesetup.md) > [dependencies$](./kibana-plugin-core-server.statusservicesetup.dependencies_.md)
+
+## StatusServiceSetup.dependencies$ property
+
+Current status for all plugins this plugin depends on. Each key of the `Record` is a plugin id.
+
+Signature:
+
+```typescript
+dependencies$: Observable>;
+```
diff --git a/docs/development/core/server/kibana-plugin-core-server.statusservicesetup.derivedstatus_.md b/docs/development/core/server/kibana-plugin-core-server.statusservicesetup.derivedstatus_.md
new file mode 100644
index 0000000000000..6c65e44270a06
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-core-server.statusservicesetup.derivedstatus_.md
@@ -0,0 +1,20 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [StatusServiceSetup](./kibana-plugin-core-server.statusservicesetup.md) > [derivedStatus$](./kibana-plugin-core-server.statusservicesetup.derivedstatus_.md)
+
+## StatusServiceSetup.derivedStatus$ property
+
+The status of this plugin as derived from its dependencies.
+
+Signature:
+
+```typescript
+derivedStatus$: Observable;
+```
+
+## Remarks
+
+By default, plugins inherit this derived status from their dependencies. Calling overrides this default status.
+
+This may emit multliple times for a single status change event as propagates through the dependency tree
+
diff --git a/docs/development/core/server/kibana-plugin-core-server.statusservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.statusservicesetup.md
index 3d3b73ccda25f..ba0645be4d26c 100644
--- a/docs/development/core/server/kibana-plugin-core-server.statusservicesetup.md
+++ b/docs/development/core/server/kibana-plugin-core-server.statusservicesetup.md
@@ -12,10 +12,73 @@ API for accessing status of Core and this plugin's dependencies as well as for c
export interface StatusServiceSetup
```
+## Remarks
+
+By default, a plugin inherits it's current status from the most severe status level of any Core services and any plugins that it depends on. This default status is available on the API.
+
+Plugins may customize their status calculation by calling the API with an Observable. Within this Observable, a plugin may choose to only depend on the status of some of its dependencies, to ignore severe status levels of particular Core services they are not concerned with, or to make its status dependent on other external services.
+
+## Example 1
+
+Customize a plugin's status to only depend on the status of SavedObjects:
+
+```ts
+core.status.set(
+ core.status.core$.pipe(
+. map((coreStatus) => {
+ return coreStatus.savedObjects;
+ }) ;
+ );
+);
+
+```
+
+## Example 2
+
+Customize a plugin's status to include an external service:
+
+```ts
+const externalStatus$ = interval(1000).pipe(
+ switchMap(async () => {
+ const resp = await fetch(`https://myexternaldep.com/_healthz`);
+ const body = await resp.json();
+ if (body.ok) {
+ return of({ level: ServiceStatusLevels.available, summary: 'External Service is up'});
+ } else {
+ return of({ level: ServiceStatusLevels.available, summary: 'External Service is unavailable'});
+ }
+ }),
+ catchError((error) => {
+ of({ level: ServiceStatusLevels.unavailable, summary: `External Service is down`, meta: { error }})
+ })
+);
+
+core.status.set(
+ combineLatest([core.status.derivedStatus$, externalStatus$]).pipe(
+ map(([derivedStatus, externalStatus]) => {
+ if (externalStatus.level > derivedStatus) {
+ return externalStatus;
+ } else {
+ return derivedStatus;
+ }
+ })
+ )
+);
+
+```
+
## Properties
| Property | Type | Description |
| --- | --- | --- |
| [core$](./kibana-plugin-core-server.statusservicesetup.core_.md) | Observable<CoreStatus>
| Current status for all Core services. |
+| [dependencies$](./kibana-plugin-core-server.statusservicesetup.dependencies_.md) | Observable<Record<string, ServiceStatus>>
| Current status for all plugins this plugin depends on. Each key of the Record
is a plugin id. |
+| [derivedStatus$](./kibana-plugin-core-server.statusservicesetup.derivedstatus_.md) | Observable<ServiceStatus>
| The status of this plugin as derived from its dependencies. |
| [overall$](./kibana-plugin-core-server.statusservicesetup.overall_.md) | Observable<ServiceStatus>
| Overall system status for all of Kibana. |
+## Methods
+
+| Method | Description |
+| --- | --- |
+| [set(status$)](./kibana-plugin-core-server.statusservicesetup.set.md) | Allows a plugin to specify a custom status dependent on its own criteria. Completely overrides the default inherited status. |
+
diff --git a/docs/development/core/server/kibana-plugin-core-server.statusservicesetup.set.md b/docs/development/core/server/kibana-plugin-core-server.statusservicesetup.set.md
new file mode 100644
index 0000000000000..143cd397c40ae
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-core-server.statusservicesetup.set.md
@@ -0,0 +1,28 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [StatusServiceSetup](./kibana-plugin-core-server.statusservicesetup.md) > [set](./kibana-plugin-core-server.statusservicesetup.set.md)
+
+## StatusServiceSetup.set() method
+
+Allows a plugin to specify a custom status dependent on its own criteria. Completely overrides the default inherited status.
+
+Signature:
+
+```typescript
+set(status$: Observable): void;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| status$ | Observable<ServiceStatus>
| |
+
+Returns:
+
+`void`
+
+## Remarks
+
+See the [StatusServiceSetup.derivedStatus$](./kibana-plugin-core-server.statusservicesetup.derivedstatus_.md) API for leveraging the default status calculation that is provided by Core.
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig._constructor_.md
new file mode 100644
index 0000000000000..9287a08ff196b
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig._constructor_.md
@@ -0,0 +1,21 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [(constructor)](./kibana-plugin-plugins-data-public.aggconfig._constructor_.md)
+
+## AggConfig.(constructor)
+
+Constructs a new instance of the `AggConfig` class
+
+Signature:
+
+```typescript
+constructor(aggConfigs: IAggConfigs, opts: AggConfigOptions);
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| aggConfigs | IAggConfigs
| |
+| opts | AggConfigOptions
| |
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.aggconfigs.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.aggconfigs.md
new file mode 100644
index 0000000000000..f552bbd2d1cfc
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.aggconfigs.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [aggConfigs](./kibana-plugin-plugins-data-public.aggconfig.aggconfigs.md)
+
+## AggConfig.aggConfigs property
+
+Signature:
+
+```typescript
+aggConfigs: IAggConfigs;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.brandnew.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.brandnew.md
new file mode 100644
index 0000000000000..eb1f3af4c5b01
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.brandnew.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [brandNew](./kibana-plugin-plugins-data-public.aggconfig.brandnew.md)
+
+## AggConfig.brandNew property
+
+Signature:
+
+```typescript
+brandNew?: boolean;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.createfilter.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.createfilter.md
new file mode 100644
index 0000000000000..7ec0350f65321
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.createfilter.md
@@ -0,0 +1,23 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [createFilter](./kibana-plugin-plugins-data-public.aggconfig.createfilter.md)
+
+## AggConfig.createFilter() method
+
+Signature:
+
+```typescript
+createFilter(key: string, params?: {}): any;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| key | string
| |
+| params | {}
| |
+
+Returns:
+
+`any`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.enabled.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.enabled.md
new file mode 100644
index 0000000000000..82595ee5f5b63
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.enabled.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [enabled](./kibana-plugin-plugins-data-public.aggconfig.enabled.md)
+
+## AggConfig.enabled property
+
+Signature:
+
+```typescript
+enabled: boolean;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.ensureids.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.ensureids.md
new file mode 100644
index 0000000000000..04e0b82187a5f
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.ensureids.md
@@ -0,0 +1,24 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [ensureIds](./kibana-plugin-plugins-data-public.aggconfig.ensureids.md)
+
+## AggConfig.ensureIds() method
+
+Ensure that all of the objects in the list have ids, the objects and list are modified by reference.
+
+Signature:
+
+```typescript
+static ensureIds(list: any[]): any[];
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| list | any[]
| |
+
+Returns:
+
+`any[]`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.fieldistimefield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.fieldistimefield.md
new file mode 100644
index 0000000000000..a1fde4dec25b1
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.fieldistimefield.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [fieldIsTimeField](./kibana-plugin-plugins-data-public.aggconfig.fieldistimefield.md)
+
+## AggConfig.fieldIsTimeField() method
+
+Signature:
+
+```typescript
+fieldIsTimeField(): boolean | "" | undefined;
+```
+Returns:
+
+`boolean | "" | undefined`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.fieldname.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.fieldname.md
new file mode 100644
index 0000000000000..2d3acb7f026ff
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.fieldname.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [fieldName](./kibana-plugin-plugins-data-public.aggconfig.fieldname.md)
+
+## AggConfig.fieldName() method
+
+Signature:
+
+```typescript
+fieldName(): any;
+```
+Returns:
+
+`any`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getaggparams.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getaggparams.md
new file mode 100644
index 0000000000000..f898844ff0273
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getaggparams.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [getAggParams](./kibana-plugin-plugins-data-public.aggconfig.getaggparams.md)
+
+## AggConfig.getAggParams() method
+
+Signature:
+
+```typescript
+getAggParams(): import("./param_types/agg").AggParamType[];
+```
+Returns:
+
+`import("./param_types/agg").AggParamType[]`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getfield.md
new file mode 100644
index 0000000000000..1fb6f88c43171
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getfield.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [getField](./kibana-plugin-plugins-data-public.aggconfig.getfield.md)
+
+## AggConfig.getField() method
+
+Signature:
+
+```typescript
+getField(): any;
+```
+Returns:
+
+`any`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getfielddisplayname.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getfielddisplayname.md
new file mode 100644
index 0000000000000..710499cee62dd
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getfielddisplayname.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [getFieldDisplayName](./kibana-plugin-plugins-data-public.aggconfig.getfielddisplayname.md)
+
+## AggConfig.getFieldDisplayName() method
+
+Signature:
+
+```typescript
+getFieldDisplayName(): any;
+```
+Returns:
+
+`any`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getindexpattern.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getindexpattern.md
new file mode 100644
index 0000000000000..ed0e9d0fbb5de
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getindexpattern.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [getIndexPattern](./kibana-plugin-plugins-data-public.aggconfig.getindexpattern.md)
+
+## AggConfig.getIndexPattern() method
+
+Signature:
+
+```typescript
+getIndexPattern(): import("../../../public").IndexPattern;
+```
+Returns:
+
+`import("../../../public").IndexPattern`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getkey.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getkey.md
new file mode 100644
index 0000000000000..a2a59fcf9ae31
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getkey.md
@@ -0,0 +1,23 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [getKey](./kibana-plugin-plugins-data-public.aggconfig.getkey.md)
+
+## AggConfig.getKey() method
+
+Signature:
+
+```typescript
+getKey(bucket: any, key?: string): any;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| bucket | any
| |
+| key | string
| |
+
+Returns:
+
+`any`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getparam.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getparam.md
new file mode 100644
index 0000000000000..ad4cd2fa175f8
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getparam.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [getParam](./kibana-plugin-plugins-data-public.aggconfig.getparam.md)
+
+## AggConfig.getParam() method
+
+Signature:
+
+```typescript
+getParam(key: string): any;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| key | string
| |
+
+Returns:
+
+`any`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getrequestaggs.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getrequestaggs.md
new file mode 100644
index 0000000000000..773c2f5a7c0e9
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getrequestaggs.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [getRequestAggs](./kibana-plugin-plugins-data-public.aggconfig.getrequestaggs.md)
+
+## AggConfig.getRequestAggs() method
+
+Signature:
+
+```typescript
+getRequestAggs(): AggConfig[];
+```
+Returns:
+
+`AggConfig[]`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getresponseaggs.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getresponseaggs.md
new file mode 100644
index 0000000000000..cf515e68dcc57
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getresponseaggs.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [getResponseAggs](./kibana-plugin-plugins-data-public.aggconfig.getresponseaggs.md)
+
+## AggConfig.getResponseAggs() method
+
+Signature:
+
+```typescript
+getResponseAggs(): AggConfig[];
+```
+Returns:
+
+`AggConfig[]`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.gettimerange.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.gettimerange.md
new file mode 100644
index 0000000000000..897a6d8dda3f1
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.gettimerange.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [getTimeRange](./kibana-plugin-plugins-data-public.aggconfig.gettimerange.md)
+
+## AggConfig.getTimeRange() method
+
+Signature:
+
+```typescript
+getTimeRange(): import("../../../public").TimeRange | undefined;
+```
+Returns:
+
+`import("../../../public").TimeRange | undefined`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getvalue.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getvalue.md
new file mode 100644
index 0000000000000..4fab1af3f6464
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.getvalue.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [getValue](./kibana-plugin-plugins-data-public.aggconfig.getvalue.md)
+
+## AggConfig.getValue() method
+
+Signature:
+
+```typescript
+getValue(bucket: any): any;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| bucket | any
| |
+
+Returns:
+
+`any`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.id.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.id.md
new file mode 100644
index 0000000000000..1fa7a5c57e2a8
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.id.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [id](./kibana-plugin-plugins-data-public.aggconfig.id.md)
+
+## AggConfig.id property
+
+Signature:
+
+```typescript
+id: string;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.isfilterable.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.isfilterable.md
new file mode 100644
index 0000000000000..a795ab1e91c2c
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.isfilterable.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [isFilterable](./kibana-plugin-plugins-data-public.aggconfig.isfilterable.md)
+
+## AggConfig.isFilterable() method
+
+Signature:
+
+```typescript
+isFilterable(): boolean;
+```
+Returns:
+
+`boolean`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.makelabel.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.makelabel.md
new file mode 100644
index 0000000000000..65923ed0ae889
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.makelabel.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [makeLabel](./kibana-plugin-plugins-data-public.aggconfig.makelabel.md)
+
+## AggConfig.makeLabel() method
+
+Signature:
+
+```typescript
+makeLabel(percentageMode?: boolean): any;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| percentageMode | boolean
| |
+
+Returns:
+
+`any`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.md
new file mode 100644
index 0000000000000..ceb90cffbf6ca
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.md
@@ -0,0 +1,62 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md)
+
+## AggConfig class
+
+Signature:
+
+```typescript
+export declare class AggConfig
+```
+
+## Constructors
+
+| Constructor | Modifiers | Description |
+| --- | --- | --- |
+| [(constructor)(aggConfigs, opts)](./kibana-plugin-plugins-data-public.aggconfig._constructor_.md) | | Constructs a new instance of the AggConfig
class |
+
+## Properties
+
+| Property | Modifiers | Type | Description |
+| --- | --- | --- | --- |
+| [aggConfigs](./kibana-plugin-plugins-data-public.aggconfig.aggconfigs.md) | | IAggConfigs
| |
+| [brandNew](./kibana-plugin-plugins-data-public.aggconfig.brandnew.md) | | boolean
| |
+| [enabled](./kibana-plugin-plugins-data-public.aggconfig.enabled.md) | | boolean
| |
+| [id](./kibana-plugin-plugins-data-public.aggconfig.id.md) | | string
| |
+| [params](./kibana-plugin-plugins-data-public.aggconfig.params.md) | | any
| |
+| [parent](./kibana-plugin-plugins-data-public.aggconfig.parent.md) | | IAggConfigs
| |
+| [schema](./kibana-plugin-plugins-data-public.aggconfig.schema.md) | | string
| |
+| [type](./kibana-plugin-plugins-data-public.aggconfig.type.md) | | IAggType
| |
+
+## Methods
+
+| Method | Modifiers | Description |
+| --- | --- | --- |
+| [createFilter(key, params)](./kibana-plugin-plugins-data-public.aggconfig.createfilter.md) | | |
+| [ensureIds(list)](./kibana-plugin-plugins-data-public.aggconfig.ensureids.md) | static
| Ensure that all of the objects in the list have ids, the objects and list are modified by reference. |
+| [fieldIsTimeField()](./kibana-plugin-plugins-data-public.aggconfig.fieldistimefield.md) | | |
+| [fieldName()](./kibana-plugin-plugins-data-public.aggconfig.fieldname.md) | | |
+| [getAggParams()](./kibana-plugin-plugins-data-public.aggconfig.getaggparams.md) | | |
+| [getField()](./kibana-plugin-plugins-data-public.aggconfig.getfield.md) | | |
+| [getFieldDisplayName()](./kibana-plugin-plugins-data-public.aggconfig.getfielddisplayname.md) | | |
+| [getIndexPattern()](./kibana-plugin-plugins-data-public.aggconfig.getindexpattern.md) | | |
+| [getKey(bucket, key)](./kibana-plugin-plugins-data-public.aggconfig.getkey.md) | | |
+| [getParam(key)](./kibana-plugin-plugins-data-public.aggconfig.getparam.md) | | |
+| [getRequestAggs()](./kibana-plugin-plugins-data-public.aggconfig.getrequestaggs.md) | | |
+| [getResponseAggs()](./kibana-plugin-plugins-data-public.aggconfig.getresponseaggs.md) | | |
+| [getTimeRange()](./kibana-plugin-plugins-data-public.aggconfig.gettimerange.md) | | |
+| [getValue(bucket)](./kibana-plugin-plugins-data-public.aggconfig.getvalue.md) | | |
+| [isFilterable()](./kibana-plugin-plugins-data-public.aggconfig.isfilterable.md) | | |
+| [makeLabel(percentageMode)](./kibana-plugin-plugins-data-public.aggconfig.makelabel.md) | | |
+| [nextId(list)](./kibana-plugin-plugins-data-public.aggconfig.nextid.md) | static
| Calculate the next id based on the ids in this list {array} list - a list of objects with id properties |
+| [onSearchRequestStart(searchSource, options)](./kibana-plugin-plugins-data-public.aggconfig.onsearchrequeststart.md) | | Hook for pre-flight logic, see AggType\#onSearchRequestStart |
+| [serialize()](./kibana-plugin-plugins-data-public.aggconfig.serialize.md) | | |
+| [setParams(from)](./kibana-plugin-plugins-data-public.aggconfig.setparams.md) | | Write the current values to this.params, filling in the defaults as we go |
+| [setType(type)](./kibana-plugin-plugins-data-public.aggconfig.settype.md) | | |
+| [toDsl(aggConfigs)](./kibana-plugin-plugins-data-public.aggconfig.todsl.md) | | Convert this aggConfig to its dsl syntax.Adds params and adhoc subaggs to a pojo, then returns it |
+| [toExpressionAst()](./kibana-plugin-plugins-data-public.aggconfig.toexpressionast.md) | | |
+| [toJSON()](./kibana-plugin-plugins-data-public.aggconfig.tojson.md) | | |
+| [toSerializedFieldFormat()](./kibana-plugin-plugins-data-public.aggconfig.toserializedfieldformat.md) | | Returns a serialized field format for the field used in this agg. This can be passed to fieldFormats.deserialize to get the field format instance. |
+| [write(aggs)](./kibana-plugin-plugins-data-public.aggconfig.write.md) | | |
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.nextid.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.nextid.md
new file mode 100644
index 0000000000000..ab524a6d1c4f1
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.nextid.md
@@ -0,0 +1,26 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [nextId](./kibana-plugin-plugins-data-public.aggconfig.nextid.md)
+
+## AggConfig.nextId() method
+
+Calculate the next id based on the ids in this list
+
+ {array} list - a list of objects with id properties
+
+Signature:
+
+```typescript
+static nextId(list: IAggConfig[]): number;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| list | IAggConfig[]
| |
+
+Returns:
+
+`number`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.onsearchrequeststart.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.onsearchrequeststart.md
new file mode 100644
index 0000000000000..81df7866560e3
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.onsearchrequeststart.md
@@ -0,0 +1,25 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [onSearchRequestStart](./kibana-plugin-plugins-data-public.aggconfig.onsearchrequeststart.md)
+
+## AggConfig.onSearchRequestStart() method
+
+Hook for pre-flight logic, see AggType\#onSearchRequestStart
+
+Signature:
+
+```typescript
+onSearchRequestStart(searchSource: ISearchSource, options?: ISearchOptions): Promise | Promise;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| searchSource | ISearchSource
| |
+| options | ISearchOptions
| |
+
+Returns:
+
+`Promise | Promise`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.params.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.params.md
new file mode 100644
index 0000000000000..5bdb67f53b519
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.params.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [params](./kibana-plugin-plugins-data-public.aggconfig.params.md)
+
+## AggConfig.params property
+
+Signature:
+
+```typescript
+params: any;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.parent.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.parent.md
new file mode 100644
index 0000000000000..53d028457a9ae
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.parent.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [parent](./kibana-plugin-plugins-data-public.aggconfig.parent.md)
+
+## AggConfig.parent property
+
+Signature:
+
+```typescript
+parent?: IAggConfigs;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.schema.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.schema.md
new file mode 100644
index 0000000000000..afbf685951356
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.schema.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [schema](./kibana-plugin-plugins-data-public.aggconfig.schema.md)
+
+## AggConfig.schema property
+
+Signature:
+
+```typescript
+schema?: string;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.serialize.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.serialize.md
new file mode 100644
index 0000000000000..b0eebdbcc11ec
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.serialize.md
@@ -0,0 +1,17 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [serialize](./kibana-plugin-plugins-data-public.aggconfig.serialize.md)
+
+## AggConfig.serialize() method
+
+Signature:
+
+```typescript
+serialize(): AggConfigSerialized;
+```
+Returns:
+
+`AggConfigSerialized`
+
+Returns a serialized representation of an AggConfig.
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.setparams.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.setparams.md
new file mode 100644
index 0000000000000..cb495b7653f8a
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.setparams.md
@@ -0,0 +1,24 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [setParams](./kibana-plugin-plugins-data-public.aggconfig.setparams.md)
+
+## AggConfig.setParams() method
+
+Write the current values to this.params, filling in the defaults as we go
+
+Signature:
+
+```typescript
+setParams(from: any): void;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| from | any
| |
+
+Returns:
+
+`void`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.settype.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.settype.md
new file mode 100644
index 0000000000000..0b07186a6ca33
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.settype.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [setType](./kibana-plugin-plugins-data-public.aggconfig.settype.md)
+
+## AggConfig.setType() method
+
+Signature:
+
+```typescript
+setType(type: IAggType): void;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| type | IAggType
| |
+
+Returns:
+
+`void`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.todsl.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.todsl.md
new file mode 100644
index 0000000000000..ac655c2a88a7b
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.todsl.md
@@ -0,0 +1,26 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [toDsl](./kibana-plugin-plugins-data-public.aggconfig.todsl.md)
+
+## AggConfig.toDsl() method
+
+Convert this aggConfig to its dsl syntax.
+
+Adds params and adhoc subaggs to a pojo, then returns it
+
+Signature:
+
+```typescript
+toDsl(aggConfigs?: IAggConfigs): any;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| aggConfigs | IAggConfigs
| |
+
+Returns:
+
+`any`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.toexpressionast.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.toexpressionast.md
new file mode 100644
index 0000000000000..99001e81fde49
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.toexpressionast.md
@@ -0,0 +1,17 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [toExpressionAst](./kibana-plugin-plugins-data-public.aggconfig.toexpressionast.md)
+
+## AggConfig.toExpressionAst() method
+
+Signature:
+
+```typescript
+toExpressionAst(): ExpressionAstFunction | undefined;
+```
+Returns:
+
+`ExpressionAstFunction | undefined`
+
+Returns an ExpressionAst representing the function for this agg type.
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.tojson.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.tojson.md
new file mode 100644
index 0000000000000..aa639aa574076
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.tojson.md
@@ -0,0 +1,20 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [toJSON](./kibana-plugin-plugins-data-public.aggconfig.tojson.md)
+
+## AggConfig.toJSON() method
+
+> Warning: This API is now obsolete.
+>
+> - Use serialize() instead.
+>
+
+Signature:
+
+```typescript
+toJSON(): AggConfigSerialized;
+```
+Returns:
+
+`AggConfigSerialized`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.toserializedfieldformat.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.toserializedfieldformat.md
new file mode 100644
index 0000000000000..7a75950f9cc6d
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.toserializedfieldformat.md
@@ -0,0 +1,17 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [toSerializedFieldFormat](./kibana-plugin-plugins-data-public.aggconfig.toserializedfieldformat.md)
+
+## AggConfig.toSerializedFieldFormat() method
+
+Returns a serialized field format for the field used in this agg. This can be passed to fieldFormats.deserialize to get the field format instance.
+
+Signature:
+
+```typescript
+toSerializedFieldFormat(): {} | Ensure, SerializableState>;
+```
+Returns:
+
+`{} | Ensure, SerializableState>`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.type.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.type.md
new file mode 100644
index 0000000000000..9dc44caee42e8
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.type.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [type](./kibana-plugin-plugins-data-public.aggconfig.type.md)
+
+## AggConfig.type property
+
+Signature:
+
+```typescript
+get type(): IAggType;
+
+set type(type: IAggType);
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.write.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.write.md
new file mode 100644
index 0000000000000..f98394b57cac3
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfig.write.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) > [write](./kibana-plugin-plugins-data-public.aggconfig.write.md)
+
+## AggConfig.write() method
+
+Signature:
+
+```typescript
+write(aggs?: IAggConfigs): Record;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| aggs | IAggConfigs
| |
+
+Returns:
+
+`Record`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs._constructor_.md
new file mode 100644
index 0000000000000..c9e08b9712480
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs._constructor_.md
@@ -0,0 +1,32 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [(constructor)](./kibana-plugin-plugins-data-public.aggconfigs._constructor_.md)
+
+## AggConfigs.(constructor)
+
+Constructs a new instance of the `AggConfigs` class
+
+Signature:
+
+```typescript
+constructor(indexPattern: IndexPattern, configStates: Pick & Pick<{
+ type: string | IAggType;
+ }, "type"> & Pick<{
+ type: string | IAggType;
+ }, never>, "enabled" | "type" | "schema" | "id" | "params">[] | undefined, opts: AggConfigsOptions);
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| indexPattern | IndexPattern
| |
+| configStates | Pick<Pick<{
type: string;
enabled?: boolean | undefined;
id?: string | undefined;
params?: {} | import("./agg_config").SerializableState | undefined;
schema?: string | undefined;
}, "enabled" | "schema" | "id" | "params"> & Pick<{
type: string | IAggType;
}, "type"> & Pick<{
type: string | IAggType;
}, never>, "enabled" | "type" | "schema" | "id" | "params">[] | undefined
| |
+| opts | AggConfigsOptions
| |
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.aggs.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.aggs.md
new file mode 100644
index 0000000000000..0d217e037ecb1
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.aggs.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [aggs](./kibana-plugin-plugins-data-public.aggconfigs.aggs.md)
+
+## AggConfigs.aggs property
+
+Signature:
+
+```typescript
+aggs: IAggConfig[];
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.byid.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.byid.md
new file mode 100644
index 0000000000000..14d65ada5e39d
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.byid.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [byId](./kibana-plugin-plugins-data-public.aggconfigs.byid.md)
+
+## AggConfigs.byId() method
+
+Signature:
+
+```typescript
+byId(id: string): AggConfig | undefined;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| id | string
| |
+
+Returns:
+
+`AggConfig | undefined`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.byindex.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.byindex.md
new file mode 100644
index 0000000000000..5977c81ddaf36
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.byindex.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [byIndex](./kibana-plugin-plugins-data-public.aggconfigs.byindex.md)
+
+## AggConfigs.byIndex() method
+
+Signature:
+
+```typescript
+byIndex(index: number): AggConfig;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| index | number
| |
+
+Returns:
+
+`AggConfig`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.byname.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.byname.md
new file mode 100644
index 0000000000000..772ba1f074d0d
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.byname.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [byName](./kibana-plugin-plugins-data-public.aggconfigs.byname.md)
+
+## AggConfigs.byName() method
+
+Signature:
+
+```typescript
+byName(name: string): AggConfig[];
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| name | string
| |
+
+Returns:
+
+`AggConfig[]`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.byschemaname.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.byschemaname.md
new file mode 100644
index 0000000000000..3a7c6a5f89e17
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.byschemaname.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [bySchemaName](./kibana-plugin-plugins-data-public.aggconfigs.byschemaname.md)
+
+## AggConfigs.bySchemaName() method
+
+Signature:
+
+```typescript
+bySchemaName(schema: string): AggConfig[];
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| schema | string
| |
+
+Returns:
+
+`AggConfig[]`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.bytype.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.bytype.md
new file mode 100644
index 0000000000000..8bbf85ce4f29b
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.bytype.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [byType](./kibana-plugin-plugins-data-public.aggconfigs.bytype.md)
+
+## AggConfigs.byType() method
+
+Signature:
+
+```typescript
+byType(type: string): AggConfig[];
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| type | string
| |
+
+Returns:
+
+`AggConfig[]`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.bytypename.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.bytypename.md
new file mode 100644
index 0000000000000..97f05837493f2
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.bytypename.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [byTypeName](./kibana-plugin-plugins-data-public.aggconfigs.bytypename.md)
+
+## AggConfigs.byTypeName() method
+
+Signature:
+
+```typescript
+byTypeName(type: string): AggConfig[];
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| type | string
| |
+
+Returns:
+
+`AggConfig[]`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.clone.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.clone.md
new file mode 100644
index 0000000000000..0206f3c6b4751
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.clone.md
@@ -0,0 +1,24 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [clone](./kibana-plugin-plugins-data-public.aggconfigs.clone.md)
+
+## AggConfigs.clone() method
+
+Signature:
+
+```typescript
+clone({ enabledOnly }?: {
+ enabledOnly?: boolean | undefined;
+ }): AggConfigs;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| { enabledOnly } | {
enabledOnly?: boolean | undefined;
}
| |
+
+Returns:
+
+`AggConfigs`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.createaggconfig.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.createaggconfig.md
new file mode 100644
index 0000000000000..2ccded7c74e4c
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.createaggconfig.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [createAggConfig](./kibana-plugin-plugins-data-public.aggconfigs.createaggconfig.md)
+
+## AggConfigs.createAggConfig property
+
+Signature:
+
+```typescript
+createAggConfig: (params: CreateAggConfigParams, { addToAggConfigs }?: {
+ addToAggConfigs?: boolean | undefined;
+ }) => T;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getall.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getall.md
new file mode 100644
index 0000000000000..091ec1ce416c3
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getall.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [getAll](./kibana-plugin-plugins-data-public.aggconfigs.getall.md)
+
+## AggConfigs.getAll() method
+
+Signature:
+
+```typescript
+getAll(): AggConfig[];
+```
+Returns:
+
+`AggConfig[]`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getrequestaggbyid.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getrequestaggbyid.md
new file mode 100644
index 0000000000000..f375648ca1cb7
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getrequestaggbyid.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [getRequestAggById](./kibana-plugin-plugins-data-public.aggconfigs.getrequestaggbyid.md)
+
+## AggConfigs.getRequestAggById() method
+
+Signature:
+
+```typescript
+getRequestAggById(id: string): AggConfig | undefined;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| id | string
| |
+
+Returns:
+
+`AggConfig | undefined`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getrequestaggs.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getrequestaggs.md
new file mode 100644
index 0000000000000..f4db6e373f5c3
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getrequestaggs.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [getRequestAggs](./kibana-plugin-plugins-data-public.aggconfigs.getrequestaggs.md)
+
+## AggConfigs.getRequestAggs() method
+
+Signature:
+
+```typescript
+getRequestAggs(): AggConfig[];
+```
+Returns:
+
+`AggConfig[]`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getresponseaggbyid.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getresponseaggbyid.md
new file mode 100644
index 0000000000000..ab31c74f6000d
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getresponseaggbyid.md
@@ -0,0 +1,24 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [getResponseAggById](./kibana-plugin-plugins-data-public.aggconfigs.getresponseaggbyid.md)
+
+## AggConfigs.getResponseAggById() method
+
+Find a response agg by it's id. This may be an agg in the aggConfigs, or one created specifically for a response value
+
+Signature:
+
+```typescript
+getResponseAggById(id: string): AggConfig | undefined;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| id | string
| |
+
+Returns:
+
+`AggConfig | undefined`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getresponseaggs.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getresponseaggs.md
new file mode 100644
index 0000000000000..47e26bdea9e9c
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.getresponseaggs.md
@@ -0,0 +1,21 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [getResponseAggs](./kibana-plugin-plugins-data-public.aggconfigs.getresponseaggs.md)
+
+## AggConfigs.getResponseAggs() method
+
+Gets the AggConfigs (and possibly ResponseAggConfigs) that represent the values that will be produced when all aggs are run.
+
+With multi-value metric aggs it is possible for a single agg request to result in multiple agg values, which is why the length of a vis' responseValuesAggs may be different than the vis' aggs
+
+ {array\[AggConfig\]}
+
+Signature:
+
+```typescript
+getResponseAggs(): AggConfig[];
+```
+Returns:
+
+`AggConfig[]`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.indexpattern.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.indexpattern.md
new file mode 100644
index 0000000000000..9bd91e185df1e
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.indexpattern.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [indexPattern](./kibana-plugin-plugins-data-public.aggconfigs.indexpattern.md)
+
+## AggConfigs.indexPattern property
+
+Signature:
+
+```typescript
+indexPattern: IndexPattern;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.jsondataequals.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.jsondataequals.md
new file mode 100644
index 0000000000000..d94c3959cd6a2
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.jsondataequals.md
@@ -0,0 +1,24 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [jsonDataEquals](./kibana-plugin-plugins-data-public.aggconfigs.jsondataequals.md)
+
+## AggConfigs.jsonDataEquals() method
+
+Data-by-data comparison of this Aggregation Ignores the non-array indexes
+
+Signature:
+
+```typescript
+jsonDataEquals(aggConfigs: AggConfig[]): boolean;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| aggConfigs | AggConfig[]
| |
+
+Returns:
+
+`boolean`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.md
new file mode 100644
index 0000000000000..c0ba1bbeea334
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.md
@@ -0,0 +1,48 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md)
+
+## AggConfigs class
+
+Signature:
+
+```typescript
+export declare class AggConfigs
+```
+
+## Constructors
+
+| Constructor | Modifiers | Description |
+| --- | --- | --- |
+| [(constructor)(indexPattern, configStates, opts)](./kibana-plugin-plugins-data-public.aggconfigs._constructor_.md) | | Constructs a new instance of the AggConfigs
class |
+
+## Properties
+
+| Property | Modifiers | Type | Description |
+| --- | --- | --- | --- |
+| [aggs](./kibana-plugin-plugins-data-public.aggconfigs.aggs.md) | | IAggConfig[]
| |
+| [createAggConfig](./kibana-plugin-plugins-data-public.aggconfigs.createaggconfig.md) | | <T extends AggConfig = AggConfig>(params: CreateAggConfigParams, { addToAggConfigs }?: {
addToAggConfigs?: boolean | undefined;
}) => T
| |
+| [indexPattern](./kibana-plugin-plugins-data-public.aggconfigs.indexpattern.md) | | IndexPattern
| |
+| [timeRange](./kibana-plugin-plugins-data-public.aggconfigs.timerange.md) | | TimeRange
| |
+
+## Methods
+
+| Method | Modifiers | Description |
+| --- | --- | --- |
+| [byId(id)](./kibana-plugin-plugins-data-public.aggconfigs.byid.md) | | |
+| [byIndex(index)](./kibana-plugin-plugins-data-public.aggconfigs.byindex.md) | | |
+| [byName(name)](./kibana-plugin-plugins-data-public.aggconfigs.byname.md) | | |
+| [bySchemaName(schema)](./kibana-plugin-plugins-data-public.aggconfigs.byschemaname.md) | | |
+| [byType(type)](./kibana-plugin-plugins-data-public.aggconfigs.bytype.md) | | |
+| [byTypeName(type)](./kibana-plugin-plugins-data-public.aggconfigs.bytypename.md) | | |
+| [clone({ enabledOnly })](./kibana-plugin-plugins-data-public.aggconfigs.clone.md) | | |
+| [getAll()](./kibana-plugin-plugins-data-public.aggconfigs.getall.md) | | |
+| [getRequestAggById(id)](./kibana-plugin-plugins-data-public.aggconfigs.getrequestaggbyid.md) | | |
+| [getRequestAggs()](./kibana-plugin-plugins-data-public.aggconfigs.getrequestaggs.md) | | |
+| [getResponseAggById(id)](./kibana-plugin-plugins-data-public.aggconfigs.getresponseaggbyid.md) | | Find a response agg by it's id. This may be an agg in the aggConfigs, or one created specifically for a response value |
+| [getResponseAggs()](./kibana-plugin-plugins-data-public.aggconfigs.getresponseaggs.md) | | Gets the AggConfigs (and possibly ResponseAggConfigs) that represent the values that will be produced when all aggs are run.With multi-value metric aggs it is possible for a single agg request to result in multiple agg values, which is why the length of a vis' responseValuesAggs may be different than the vis' aggs {array\[AggConfig\]} |
+| [jsonDataEquals(aggConfigs)](./kibana-plugin-plugins-data-public.aggconfigs.jsondataequals.md) | | Data-by-data comparison of this Aggregation Ignores the non-array indexes |
+| [onSearchRequestStart(searchSource, options)](./kibana-plugin-plugins-data-public.aggconfigs.onsearchrequeststart.md) | | |
+| [setTimeRange(timeRange)](./kibana-plugin-plugins-data-public.aggconfigs.settimerange.md) | | |
+| [toDsl(hierarchical)](./kibana-plugin-plugins-data-public.aggconfigs.todsl.md) | | |
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.onsearchrequeststart.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.onsearchrequeststart.md
new file mode 100644
index 0000000000000..3ae7af408563c
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.onsearchrequeststart.md
@@ -0,0 +1,23 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [onSearchRequestStart](./kibana-plugin-plugins-data-public.aggconfigs.onsearchrequeststart.md)
+
+## AggConfigs.onSearchRequestStart() method
+
+Signature:
+
+```typescript
+onSearchRequestStart(searchSource: ISearchSource, options?: ISearchOptions): Promise<[unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown]>;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| searchSource | ISearchSource
| |
+| options | ISearchOptions
| |
+
+Returns:
+
+`Promise<[unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown]>`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.settimerange.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.settimerange.md
new file mode 100644
index 0000000000000..77530f02bc9a3
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.settimerange.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [setTimeRange](./kibana-plugin-plugins-data-public.aggconfigs.settimerange.md)
+
+## AggConfigs.setTimeRange() method
+
+Signature:
+
+```typescript
+setTimeRange(timeRange: TimeRange): void;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| timeRange | TimeRange
| |
+
+Returns:
+
+`void`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.timerange.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.timerange.md
new file mode 100644
index 0000000000000..b4caef6c7f6d2
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.timerange.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [timeRange](./kibana-plugin-plugins-data-public.aggconfigs.timerange.md)
+
+## AggConfigs.timeRange property
+
+Signature:
+
+```typescript
+timeRange?: TimeRange;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.todsl.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.todsl.md
new file mode 100644
index 0000000000000..055c4113ca3e4
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggconfigs.todsl.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) > [toDsl](./kibana-plugin-plugins-data-public.aggconfigs.todsl.md)
+
+## AggConfigs.toDsl() method
+
+Signature:
+
+```typescript
+toDsl(hierarchical?: boolean): Record;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| hierarchical | boolean
| |
+
+Returns:
+
+`Record`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggsstart.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggsstart.md
new file mode 100644
index 0000000000000..7bdf9d6501203
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.aggsstart.md
@@ -0,0 +1,15 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AggsStart](./kibana-plugin-plugins-data-public.aggsstart.md)
+
+## AggsStart type
+
+AggsStart represents the actual external contract as AggsCommonStart is only used internally. The difference is that AggsStart includes the typings for the registry with initialized agg types.
+
+Signature:
+
+```typescript
+export declare type AggsStart = Assign;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.autocompletestart.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.autocompletestart.md
new file mode 100644
index 0000000000000..44cee8c32421d
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.autocompletestart.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AutocompleteStart](./kibana-plugin-plugins-data-public.autocompletestart.md)
+
+## AutocompleteStart type
+
+\*
+
+Signature:
+
+```typescript
+export declare type AutocompleteStart = ReturnType;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginsetup.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginsetup.md
index dba1d79e78682..fc5624aeddce1 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginsetup.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginsetup.md
@@ -4,6 +4,8 @@
## DataPublicPluginSetup interface
+Data plugin public Setup contract
+
Signature:
```typescript
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.actions.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.actions.md
index 25ce6eaa688f8..10997c94fab06 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.actions.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.actions.md
@@ -4,11 +4,10 @@
## DataPublicPluginStart.actions property
+filter creation utilities [DataPublicPluginStartActions](./kibana-plugin-plugins-data-public.datapublicpluginstartactions.md)
+
Signature:
```typescript
-actions: {
- createFiltersFromValueClickAction: typeof createFiltersFromValueClickAction;
- createFiltersFromRangeSelectAction: typeof createFiltersFromRangeSelectAction;
- };
+actions: DataPublicPluginStartActions;
```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.autocomplete.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.autocomplete.md
index d2e5aee7d90dd..8a09a10cccb24 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.autocomplete.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.autocomplete.md
@@ -4,6 +4,8 @@
## DataPublicPluginStart.autocomplete property
+autocomplete service [AutocompleteStart](./kibana-plugin-plugins-data-public.autocompletestart.md)
+
Signature:
```typescript
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.fieldformats.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.fieldformats.md
index dd4b38f64d10b..344044b38f7de 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.fieldformats.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.fieldformats.md
@@ -4,6 +4,8 @@
## DataPublicPluginStart.fieldFormats property
+field formats service [FieldFormatsStart](./kibana-plugin-plugins-data-public.fieldformatsstart.md)
+
Signature:
```typescript
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.indexpatterns.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.indexpatterns.md
index b3dd6a61760a6..0cf1e3101713d 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.indexpatterns.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.indexpatterns.md
@@ -4,6 +4,8 @@
## DataPublicPluginStart.indexPatterns property
+index patterns service [IndexPatternsContract](./kibana-plugin-plugins-data-public.indexpatternscontract.md)
+
Signature:
```typescript
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.md
index 4f43f10ce089e..7bae0bca701bf 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.md
@@ -4,6 +4,8 @@
## DataPublicPluginStart interface
+Data plugin public Start contract
+
Signature:
```typescript
@@ -14,11 +16,11 @@ export interface DataPublicPluginStart
| Property | Type | Description |
| --- | --- | --- |
-| [actions](./kibana-plugin-plugins-data-public.datapublicpluginstart.actions.md) | {
createFiltersFromValueClickAction: typeof createFiltersFromValueClickAction;
createFiltersFromRangeSelectAction: typeof createFiltersFromRangeSelectAction;
}
| |
-| [autocomplete](./kibana-plugin-plugins-data-public.datapublicpluginstart.autocomplete.md) | AutocompleteStart
| |
-| [fieldFormats](./kibana-plugin-plugins-data-public.datapublicpluginstart.fieldformats.md) | FieldFormatsStart
| |
-| [indexPatterns](./kibana-plugin-plugins-data-public.datapublicpluginstart.indexpatterns.md) | IndexPatternsContract
| |
-| [query](./kibana-plugin-plugins-data-public.datapublicpluginstart.query.md) | QueryStart
| |
-| [search](./kibana-plugin-plugins-data-public.datapublicpluginstart.search.md) | ISearchStart
| |
-| [ui](./kibana-plugin-plugins-data-public.datapublicpluginstart.ui.md) | {
IndexPatternSelect: React.ComponentType<IndexPatternSelectProps>;
SearchBar: React.ComponentType<StatefulSearchBarProps>;
}
| |
+| [actions](./kibana-plugin-plugins-data-public.datapublicpluginstart.actions.md) | DataPublicPluginStartActions
| filter creation utilities [DataPublicPluginStartActions](./kibana-plugin-plugins-data-public.datapublicpluginstartactions.md) |
+| [autocomplete](./kibana-plugin-plugins-data-public.datapublicpluginstart.autocomplete.md) | AutocompleteStart
| autocomplete service [AutocompleteStart](./kibana-plugin-plugins-data-public.autocompletestart.md) |
+| [fieldFormats](./kibana-plugin-plugins-data-public.datapublicpluginstart.fieldformats.md) | FieldFormatsStart
| field formats service [FieldFormatsStart](./kibana-plugin-plugins-data-public.fieldformatsstart.md) |
+| [indexPatterns](./kibana-plugin-plugins-data-public.datapublicpluginstart.indexpatterns.md) | IndexPatternsContract
| index patterns service [IndexPatternsContract](./kibana-plugin-plugins-data-public.indexpatternscontract.md) |
+| [query](./kibana-plugin-plugins-data-public.datapublicpluginstart.query.md) | QueryStart
| query service [QueryStart](./kibana-plugin-plugins-data-public.querystart.md) |
+| [search](./kibana-plugin-plugins-data-public.datapublicpluginstart.search.md) | ISearchStart
| search service [ISearchStart](./kibana-plugin-plugins-data-public.isearchstart.md) |
+| [ui](./kibana-plugin-plugins-data-public.datapublicpluginstart.ui.md) | DataPublicPluginStartUi
| prewired UI components [DataPublicPluginStartUi](./kibana-plugin-plugins-data-public.datapublicpluginstartui.md) |
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.query.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.query.md
index a44e250077ed4..16ba5dafbb264 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.query.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.query.md
@@ -4,6 +4,8 @@
## DataPublicPluginStart.query property
+query service [QueryStart](./kibana-plugin-plugins-data-public.querystart.md)
+
Signature:
```typescript
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.search.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.search.md
index eec00e7b13e9d..98832d7ca11d8 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.search.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.search.md
@@ -4,6 +4,8 @@
## DataPublicPluginStart.search property
+search service [ISearchStart](./kibana-plugin-plugins-data-public.isearchstart.md)
+
Signature:
```typescript
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.ui.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.ui.md
index 9c24216834371..671a1814ac644 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.ui.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstart.ui.md
@@ -4,11 +4,10 @@
## DataPublicPluginStart.ui property
+prewired UI components [DataPublicPluginStartUi](./kibana-plugin-plugins-data-public.datapublicpluginstartui.md)
+
Signature:
```typescript
-ui: {
- IndexPatternSelect: React.ComponentType;
- SearchBar: React.ComponentType;
- };
+ui: DataPublicPluginStartUi;
```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartactions.createfiltersfromrangeselectaction.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartactions.createfiltersfromrangeselectaction.md
new file mode 100644
index 0000000000000..c954e0095cbb6
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartactions.createfiltersfromrangeselectaction.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [DataPublicPluginStartActions](./kibana-plugin-plugins-data-public.datapublicpluginstartactions.md) > [createFiltersFromRangeSelectAction](./kibana-plugin-plugins-data-public.datapublicpluginstartactions.createfiltersfromrangeselectaction.md)
+
+## DataPublicPluginStartActions.createFiltersFromRangeSelectAction property
+
+Signature:
+
+```typescript
+createFiltersFromRangeSelectAction: typeof createFiltersFromRangeSelectAction;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartactions.createfiltersfromvalueclickaction.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartactions.createfiltersfromvalueclickaction.md
new file mode 100644
index 0000000000000..70bd5091f3604
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartactions.createfiltersfromvalueclickaction.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [DataPublicPluginStartActions](./kibana-plugin-plugins-data-public.datapublicpluginstartactions.md) > [createFiltersFromValueClickAction](./kibana-plugin-plugins-data-public.datapublicpluginstartactions.createfiltersfromvalueclickaction.md)
+
+## DataPublicPluginStartActions.createFiltersFromValueClickAction property
+
+Signature:
+
+```typescript
+createFiltersFromValueClickAction: typeof createFiltersFromValueClickAction;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartactions.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartactions.md
new file mode 100644
index 0000000000000..d44c9e892cb80
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartactions.md
@@ -0,0 +1,21 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [DataPublicPluginStartActions](./kibana-plugin-plugins-data-public.datapublicpluginstartactions.md)
+
+## DataPublicPluginStartActions interface
+
+utilities to generate filters from action context
+
+Signature:
+
+```typescript
+export interface DataPublicPluginStartActions
+```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [createFiltersFromRangeSelectAction](./kibana-plugin-plugins-data-public.datapublicpluginstartactions.createfiltersfromrangeselectaction.md) | typeof createFiltersFromRangeSelectAction
| |
+| [createFiltersFromValueClickAction](./kibana-plugin-plugins-data-public.datapublicpluginstartactions.createfiltersfromvalueclickaction.md) | typeof createFiltersFromValueClickAction
| |
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartui.indexpatternselect.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartui.indexpatternselect.md
new file mode 100644
index 0000000000000..eac29dc5de70d
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartui.indexpatternselect.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [DataPublicPluginStartUi](./kibana-plugin-plugins-data-public.datapublicpluginstartui.md) > [IndexPatternSelect](./kibana-plugin-plugins-data-public.datapublicpluginstartui.indexpatternselect.md)
+
+## DataPublicPluginStartUi.IndexPatternSelect property
+
+Signature:
+
+```typescript
+IndexPatternSelect: React.ComponentType;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartui.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartui.md
new file mode 100644
index 0000000000000..3d827c0db465b
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartui.md
@@ -0,0 +1,21 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [DataPublicPluginStartUi](./kibana-plugin-plugins-data-public.datapublicpluginstartui.md)
+
+## DataPublicPluginStartUi interface
+
+Data plugin prewired UI components
+
+Signature:
+
+```typescript
+export interface DataPublicPluginStartUi
+```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [IndexPatternSelect](./kibana-plugin-plugins-data-public.datapublicpluginstartui.indexpatternselect.md) | React.ComponentType<IndexPatternSelectProps>
| |
+| [SearchBar](./kibana-plugin-plugins-data-public.datapublicpluginstartui.searchbar.md) | React.ComponentType<StatefulSearchBarProps>
| |
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartui.searchbar.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartui.searchbar.md
new file mode 100644
index 0000000000000..06339d14cde24
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.datapublicpluginstartui.searchbar.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [DataPublicPluginStartUi](./kibana-plugin-plugins-data-public.datapublicpluginstartui.md) > [SearchBar](./kibana-plugin-plugins-data-public.datapublicpluginstartui.searchbar.md)
+
+## DataPublicPluginStartUi.SearchBar property
+
+Signature:
+
+```typescript
+SearchBar: React.ComponentType;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldformatsstart.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldformatsstart.md
new file mode 100644
index 0000000000000..1a0a08f44451a
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.fieldformatsstart.md
@@ -0,0 +1,14 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [FieldFormatsStart](./kibana-plugin-plugins-data-public.fieldformatsstart.md)
+
+## FieldFormatsStart type
+
+
+Signature:
+
+```typescript
+export declare type FieldFormatsStart = Omit & {
+ deserialize: FormatFactory;
+};
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md
index 337b4b3302cc3..d32e9a955f890 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md
@@ -9,7 +9,6 @@
```typescript
export declare function getSearchParamsFromRequest(searchRequest: SearchRequest, dependencies: {
- esShardTimeout: number;
getConfig: GetConfigFn;
}): ISearchRequestParams;
```
@@ -19,7 +18,7 @@ export declare function getSearchParamsFromRequest(searchRequest: SearchRequest,
| Parameter | Type | Description |
| --- | --- | --- |
| searchRequest | SearchRequest
| |
-| dependencies | {
esShardTimeout: number;
getConfig: GetConfigFn;
}
| |
+| dependencies | {
getConfig: GetConfigFn;
}
| |
Returns:
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._constructor_.md
index 2e078e3404fe6..a5bb15c963978 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._constructor_.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern._constructor_.md
@@ -9,7 +9,7 @@ Constructs a new instance of the `IndexPattern` class
Signature:
```typescript
-constructor(id: string | undefined, { savedObjectsClient, apiClient, patternCache, fieldFormats, onNotification, onError, shortDotsEnable, metaFields, }: IndexPatternDeps);
+constructor(id: string | undefined, { savedObjectsClient, apiClient, patternCache, fieldFormats, indexPatternsService, onNotification, onError, shortDotsEnable, metaFields, }: IndexPatternDeps);
```
## Parameters
@@ -17,5 +17,5 @@ constructor(id: string | undefined, { savedObjectsClient, apiClient, patternCach
| Parameter | Type | Description |
| --- | --- | --- |
| id | string | undefined
| |
-| { savedObjectsClient, apiClient, patternCache, fieldFormats, onNotification, onError, shortDotsEnable, metaFields, } | IndexPatternDeps
| |
+| { savedObjectsClient, apiClient, patternCache, fieldFormats, indexPatternsService, onNotification, onError, shortDotsEnable, metaFields, } | IndexPatternDeps
| |
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md
index 4c53af3f8970e..87ce1e258712a 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.md
@@ -14,7 +14,7 @@ export declare class IndexPattern implements IIndexPattern
| Constructor | Modifiers | Description |
| --- | --- | --- |
-| [(constructor)(id, { savedObjectsClient, apiClient, patternCache, fieldFormats, onNotification, onError, shortDotsEnable, metaFields, })](./kibana-plugin-plugins-data-public.indexpattern._constructor_.md) | | Constructs a new instance of the IndexPattern
class |
+| [(constructor)(id, { savedObjectsClient, apiClient, patternCache, fieldFormats, indexPatternsService, onNotification, onError, shortDotsEnable, metaFields, })](./kibana-plugin-plugins-data-public.indexpattern._constructor_.md) | | Constructs a new instance of the IndexPattern
class |
## Properties
@@ -29,11 +29,13 @@ export declare class IndexPattern implements IIndexPattern
| [id](./kibana-plugin-plugins-data-public.indexpattern.id.md) | | string
| |
| [intervalName](./kibana-plugin-plugins-data-public.indexpattern.intervalname.md) | | string | undefined
| |
| [metaFields](./kibana-plugin-plugins-data-public.indexpattern.metafields.md) | | string[]
| |
+| [originalBody](./kibana-plugin-plugins-data-public.indexpattern.originalbody.md) | | {
[key: string]: any;
}
| |
| [sourceFilters](./kibana-plugin-plugins-data-public.indexpattern.sourcefilters.md) | | SourceFilter[]
| |
| [timeFieldName](./kibana-plugin-plugins-data-public.indexpattern.timefieldname.md) | | string | undefined
| |
| [title](./kibana-plugin-plugins-data-public.indexpattern.title.md) | | string
| |
| [type](./kibana-plugin-plugins-data-public.indexpattern.type.md) | | string | undefined
| |
| [typeMeta](./kibana-plugin-plugins-data-public.indexpattern.typemeta.md) | | TypeMeta
| |
+| [version](./kibana-plugin-plugins-data-public.indexpattern.version.md) | | string | undefined
| |
## Methods
@@ -60,6 +62,5 @@ export declare class IndexPattern implements IIndexPattern
| [prepBody()](./kibana-plugin-plugins-data-public.indexpattern.prepbody.md) | | |
| [refreshFields()](./kibana-plugin-plugins-data-public.indexpattern.refreshfields.md) | | |
| [removeScriptedField(fieldName)](./kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md) | | |
-| [save(saveAttempts)](./kibana-plugin-plugins-data-public.indexpattern.save.md) | | |
| [toSpec()](./kibana-plugin-plugins-data-public.indexpattern.tospec.md) | | |
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.originalbody.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.originalbody.md
new file mode 100644
index 0000000000000..4bc3c76afbae9
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.originalbody.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [originalBody](./kibana-plugin-plugins-data-public.indexpattern.originalbody.md)
+
+## IndexPattern.originalBody property
+
+Signature:
+
+```typescript
+originalBody: {
+ [key: string]: any;
+ };
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md
index 42c6dd72b8c4e..e902d9c42b082 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.removescriptedfield.md
@@ -7,7 +7,7 @@
Signature:
```typescript
-removeScriptedField(fieldName: string): Promise;
+removeScriptedField(fieldName: string): void;
```
## Parameters
@@ -18,5 +18,5 @@ removeScriptedField(fieldName: string): Promise;
Returns:
-`Promise`
+`void`
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.save.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.save.md
deleted file mode 100644
index d0b471cc2bc21..0000000000000
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.save.md
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [save](./kibana-plugin-plugins-data-public.indexpattern.save.md)
-
-## IndexPattern.save() method
-
-Signature:
-
-```typescript
-save(saveAttempts?: number): Promise;
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| saveAttempts | number
| |
-
-Returns:
-
-`Promise`
-
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.version.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.version.md
new file mode 100644
index 0000000000000..99d3bc4e7a04d
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.version.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) > [version](./kibana-plugin-plugins-data-public.indexpattern.version.md)
+
+## IndexPattern.version property
+
+Signature:
+
+```typescript
+version: string | undefined;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchsetup.aggs.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchsetup.aggs.md
new file mode 100644
index 0000000000000..ad97820d4d760
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchsetup.aggs.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ISearchSetup](./kibana-plugin-plugins-data-public.isearchsetup.md) > [aggs](./kibana-plugin-plugins-data-public.isearchsetup.aggs.md)
+
+## ISearchSetup.aggs property
+
+Signature:
+
+```typescript
+aggs: AggsSetup;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchsetup.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchsetup.md
new file mode 100644
index 0000000000000..b68c4d61e4e03
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchsetup.md
@@ -0,0 +1,21 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ISearchSetup](./kibana-plugin-plugins-data-public.isearchsetup.md)
+
+## ISearchSetup interface
+
+The setup contract exposed by the Search plugin exposes the search strategy extension point.
+
+Signature:
+
+```typescript
+export interface ISearchSetup
+```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [aggs](./kibana-plugin-plugins-data-public.isearchsetup.aggs.md) | AggsSetup
| |
+| [usageCollector](./kibana-plugin-plugins-data-public.isearchsetup.usagecollector.md) | SearchUsageCollector
| |
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchsetup.usagecollector.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchsetup.usagecollector.md
new file mode 100644
index 0000000000000..908a842974f25
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchsetup.usagecollector.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ISearchSetup](./kibana-plugin-plugins-data-public.isearchsetup.md) > [usageCollector](./kibana-plugin-plugins-data-public.isearchsetup.usagecollector.md)
+
+## ISearchSetup.usageCollector property
+
+Signature:
+
+```typescript
+usageCollector?: SearchUsageCollector;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchsource.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchsource.md
index 4b9f6e3594dc5..43e10d0bef57a 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchsource.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchsource.md
@@ -4,7 +4,7 @@
## ISearchSource type
-\*
+search source interface
Signature:
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.aggs.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.aggs.md
new file mode 100644
index 0000000000000..993c6bf5a922b
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.aggs.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ISearchStart](./kibana-plugin-plugins-data-public.isearchstart.md) > [aggs](./kibana-plugin-plugins-data-public.isearchstart.aggs.md)
+
+## ISearchStart.aggs property
+
+agg config sub service [AggsStart](./kibana-plugin-plugins-data-public.aggsstart.md)
+
+Signature:
+
+```typescript
+aggs: AggsStart;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.md
new file mode 100644
index 0000000000000..cee213fc6e7e3
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ISearchStart](./kibana-plugin-plugins-data-public.isearchstart.md)
+
+## ISearchStart interface
+
+search service
+
+Signature:
+
+```typescript
+export interface ISearchStart
+```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [aggs](./kibana-plugin-plugins-data-public.isearchstart.aggs.md) | AggsStart
| agg config sub service [AggsStart](./kibana-plugin-plugins-data-public.aggsstart.md) |
+| [search](./kibana-plugin-plugins-data-public.isearchstart.search.md) | ISearchGeneric
| low level search [ISearchGeneric](./kibana-plugin-plugins-data-public.isearchgeneric.md) |
+| [searchSource](./kibana-plugin-plugins-data-public.isearchstart.searchsource.md) | ISearchStartSearchSource
| high level search [ISearchStartSearchSource](./kibana-plugin-plugins-data-public.isearchstartsearchsource.md) |
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.search.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.search.md
new file mode 100644
index 0000000000000..80e140e9fdd5c
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.search.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ISearchStart](./kibana-plugin-plugins-data-public.isearchstart.md) > [search](./kibana-plugin-plugins-data-public.isearchstart.search.md)
+
+## ISearchStart.search property
+
+low level search [ISearchGeneric](./kibana-plugin-plugins-data-public.isearchgeneric.md)
+
+Signature:
+
+```typescript
+search: ISearchGeneric;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.searchsource.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.searchsource.md
new file mode 100644
index 0000000000000..5d4b884b2c25b
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstart.searchsource.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ISearchStart](./kibana-plugin-plugins-data-public.isearchstart.md) > [searchSource](./kibana-plugin-plugins-data-public.isearchstart.searchsource.md)
+
+## ISearchStart.searchSource property
+
+high level search [ISearchStartSearchSource](./kibana-plugin-plugins-data-public.isearchstartsearchsource.md)
+
+Signature:
+
+```typescript
+searchSource: ISearchStartSearchSource;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstartsearchsource.create.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstartsearchsource.create.md
new file mode 100644
index 0000000000000..7f6344b82d27c
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstartsearchsource.create.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ISearchStartSearchSource](./kibana-plugin-plugins-data-public.isearchstartsearchsource.md) > [create](./kibana-plugin-plugins-data-public.isearchstartsearchsource.create.md)
+
+## ISearchStartSearchSource.create property
+
+creates [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) based on provided serialized [SearchSourceFields](./kibana-plugin-plugins-data-public.searchsourcefields.md)
+
+Signature:
+
+```typescript
+create: (fields?: SearchSourceFields) => Promise;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstartsearchsource.createempty.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstartsearchsource.createempty.md
new file mode 100644
index 0000000000000..b13b5d227c8b4
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstartsearchsource.createempty.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ISearchStartSearchSource](./kibana-plugin-plugins-data-public.isearchstartsearchsource.md) > [createEmpty](./kibana-plugin-plugins-data-public.isearchstartsearchsource.createempty.md)
+
+## ISearchStartSearchSource.createEmpty property
+
+creates empty [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md)
+
+Signature:
+
+```typescript
+createEmpty: () => ISearchSource;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstartsearchsource.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstartsearchsource.md
new file mode 100644
index 0000000000000..f10d5bb002a0f
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.isearchstartsearchsource.md
@@ -0,0 +1,21 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [ISearchStartSearchSource](./kibana-plugin-plugins-data-public.isearchstartsearchsource.md)
+
+## ISearchStartSearchSource interface
+
+high level search service
+
+Signature:
+
+```typescript
+export interface ISearchStartSearchSource
+```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [create](./kibana-plugin-plugins-data-public.isearchstartsearchsource.create.md) | (fields?: SearchSourceFields) => Promise<ISearchSource>
| creates [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) based on provided serialized [SearchSourceFields](./kibana-plugin-plugins-data-public.searchsourcefields.md) |
+| [createEmpty](./kibana-plugin-plugins-data-public.isearchstartsearchsource.createempty.md) | () => ISearchSource
| creates empty [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) |
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md
index b651480a85899..f51549c81fb62 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md
@@ -8,6 +8,8 @@
| Class | Description |
| --- | --- |
+| [AggConfig](./kibana-plugin-plugins-data-public.aggconfig.md) | |
+| [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) | |
| [AggParamType](./kibana-plugin-plugins-data-public.aggparamtype.md) | |
| [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) | |
| [FilterManager](./kibana-plugin-plugins-data-public.filtermanager.md) | |
@@ -18,6 +20,7 @@
| [Plugin](./kibana-plugin-plugins-data-public.plugin.md) | |
| [RequestTimeoutError](./kibana-plugin-plugins-data-public.requesttimeouterror.md) | Class used to signify that a request timed out. Useful for applications to conditionally handle this type of error differently than other errors. |
| [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) | |
+| [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) | \* |
| [TimeHistory](./kibana-plugin-plugins-data-public.timehistory.md) | |
## Enumerations
@@ -47,8 +50,10 @@
| --- | --- |
| [AggParamOption](./kibana-plugin-plugins-data-public.aggparamoption.md) | |
| [ApplyGlobalFilterActionContext](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md) | |
-| [DataPublicPluginSetup](./kibana-plugin-plugins-data-public.datapublicpluginsetup.md) | |
-| [DataPublicPluginStart](./kibana-plugin-plugins-data-public.datapublicpluginstart.md) | |
+| [DataPublicPluginSetup](./kibana-plugin-plugins-data-public.datapublicpluginsetup.md) | Data plugin public Setup contract |
+| [DataPublicPluginStart](./kibana-plugin-plugins-data-public.datapublicpluginstart.md) | Data plugin public Start contract |
+| [DataPublicPluginStartActions](./kibana-plugin-plugins-data-public.datapublicpluginstartactions.md) | utilities to generate filters from action context |
+| [DataPublicPluginStartUi](./kibana-plugin-plugins-data-public.datapublicpluginstartui.md) | Data plugin prewired UI components |
| [EsQueryConfig](./kibana-plugin-plugins-data-public.esqueryconfig.md) | |
| [FieldFormatConfig](./kibana-plugin-plugins-data-public.fieldformatconfig.md) | |
| [FieldMappingSpec](./kibana-plugin-plugins-data-public.fieldmappingspec.md) | |
@@ -65,10 +70,14 @@
| [IndexPatternAttributes](./kibana-plugin-plugins-data-public.indexpatternattributes.md) | Use data plugin interface instead |
| [IndexPatternTypeMeta](./kibana-plugin-plugins-data-public.indexpatterntypemeta.md) | |
| [ISearchOptions](./kibana-plugin-plugins-data-public.isearchoptions.md) | |
+| [ISearchSetup](./kibana-plugin-plugins-data-public.isearchsetup.md) | The setup contract exposed by the Search plugin exposes the search strategy extension point. |
+| [ISearchStart](./kibana-plugin-plugins-data-public.isearchstart.md) | search service |
+| [ISearchStartSearchSource](./kibana-plugin-plugins-data-public.isearchstartsearchsource.md) | high level search service |
| [KueryNode](./kibana-plugin-plugins-data-public.kuerynode.md) | |
| [OptionedValueProp](./kibana-plugin-plugins-data-public.optionedvalueprop.md) | |
| [Query](./kibana-plugin-plugins-data-public.query.md) | |
| [QueryState](./kibana-plugin-plugins-data-public.querystate.md) | All query state service state |
+| [QueryStateChange](./kibana-plugin-plugins-data-public.querystatechange.md) | |
| [QuerySuggestionBasic](./kibana-plugin-plugins-data-public.querysuggestionbasic.md) | \* |
| [QuerySuggestionField](./kibana-plugin-plugins-data-public.querysuggestionfield.md) | \* |
| [QuerySuggestionGetFnArgs](./kibana-plugin-plugins-data-public.querysuggestiongetfnargs.md) | \* |
@@ -78,7 +87,7 @@
| [SavedQueryService](./kibana-plugin-plugins-data-public.savedqueryservice.md) | |
| [SearchError](./kibana-plugin-plugins-data-public.searcherror.md) | |
| [SearchInterceptorDeps](./kibana-plugin-plugins-data-public.searchinterceptordeps.md) | |
-| [SearchSourceFields](./kibana-plugin-plugins-data-public.searchsourcefields.md) | |
+| [SearchSourceFields](./kibana-plugin-plugins-data-public.searchsourcefields.md) | search source fields |
| [TabbedAggColumn](./kibana-plugin-plugins-data-public.tabbedaggcolumn.md) | \* |
| [TabbedTable](./kibana-plugin-plugins-data-public.tabbedtable.md) | \* |
| [TimeRange](./kibana-plugin-plugins-data-public.timerange.md) | |
@@ -124,6 +133,8 @@
| [AggConfigOptions](./kibana-plugin-plugins-data-public.aggconfigoptions.md) | |
| [AggGroupName](./kibana-plugin-plugins-data-public.agggroupname.md) | |
| [AggParam](./kibana-plugin-plugins-data-public.aggparam.md) | |
+| [AggsStart](./kibana-plugin-plugins-data-public.aggsstart.md) | AggsStart represents the actual external contract as AggsCommonStart is only used internally. The difference is that AggsStart includes the typings for the registry with initialized agg types. |
+| [AutocompleteStart](./kibana-plugin-plugins-data-public.autocompletestart.md) | \* |
| [CustomFilter](./kibana-plugin-plugins-data-public.customfilter.md) | |
| [EsaggsExpressionFunctionDefinition](./kibana-plugin-plugins-data-public.esaggsexpressionfunctiondefinition.md) | |
| [EsdslExpressionFunctionDefinition](./kibana-plugin-plugins-data-public.esdslexpressionfunctiondefinition.md) | |
@@ -133,6 +144,7 @@
| [FieldFormatId](./kibana-plugin-plugins-data-public.fieldformatid.md) | id type is needed for creating custom converters. |
| [FieldFormatsContentType](./kibana-plugin-plugins-data-public.fieldformatscontenttype.md) | \* |
| [FieldFormatsGetConfigFn](./kibana-plugin-plugins-data-public.fieldformatsgetconfigfn.md) | |
+| [FieldFormatsStart](./kibana-plugin-plugins-data-public.fieldformatsstart.md) | |
| [IAggConfig](./kibana-plugin-plugins-data-public.iaggconfig.md) | AggConfig This class represents an aggregation, which is displayed in the left-hand nav of the Visualize app. |
| [IAggType](./kibana-plugin-plugins-data-public.iaggtype.md) | |
| [IFieldFormat](./kibana-plugin-plugins-data-public.ifieldformat.md) | |
@@ -144,12 +156,13 @@
| [InputTimeRange](./kibana-plugin-plugins-data-public.inputtimerange.md) | |
| [ISearch](./kibana-plugin-plugins-data-public.isearch.md) | |
| [ISearchGeneric](./kibana-plugin-plugins-data-public.isearchgeneric.md) | |
-| [ISearchSource](./kibana-plugin-plugins-data-public.isearchsource.md) | \* |
+| [ISearchSource](./kibana-plugin-plugins-data-public.isearchsource.md) | search source interface |
| [MappingObject](./kibana-plugin-plugins-data-public.mappingobject.md) | |
| [MatchAllFilter](./kibana-plugin-plugins-data-public.matchallfilter.md) | |
| [ParsedInterval](./kibana-plugin-plugins-data-public.parsedinterval.md) | |
| [PhraseFilter](./kibana-plugin-plugins-data-public.phrasefilter.md) | |
| [PhrasesFilter](./kibana-plugin-plugins-data-public.phrasesfilter.md) | |
+| [QueryStart](./kibana-plugin-plugins-data-public.querystart.md) | |
| [QuerySuggestion](./kibana-plugin-plugins-data-public.querysuggestion.md) | \* |
| [QuerySuggestionGetFn](./kibana-plugin-plugins-data-public.querysuggestiongetfn.md) | |
| [RangeFilter](./kibana-plugin-plugins-data-public.rangefilter.md) | |
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystart.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystart.md
new file mode 100644
index 0000000000000..f48a9ee7a79e4
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystart.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStart](./kibana-plugin-plugins-data-public.querystart.md)
+
+## QueryStart type
+
+Signature:
+
+```typescript
+export declare type QueryStart = ReturnType;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystatechange.appfilters.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystatechange.appfilters.md
new file mode 100644
index 0000000000000..b358e9477e515
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystatechange.appfilters.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStateChange](./kibana-plugin-plugins-data-public.querystatechange.md) > [appFilters](./kibana-plugin-plugins-data-public.querystatechange.appfilters.md)
+
+## QueryStateChange.appFilters property
+
+Signature:
+
+```typescript
+appFilters?: boolean;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystatechange.globalfilters.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystatechange.globalfilters.md
new file mode 100644
index 0000000000000..c395f169c35a5
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystatechange.globalfilters.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStateChange](./kibana-plugin-plugins-data-public.querystatechange.md) > [globalFilters](./kibana-plugin-plugins-data-public.querystatechange.globalfilters.md)
+
+## QueryStateChange.globalFilters property
+
+Signature:
+
+```typescript
+globalFilters?: boolean;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystatechange.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystatechange.md
new file mode 100644
index 0000000000000..71fb211da11d2
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystatechange.md
@@ -0,0 +1,19 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [QueryStateChange](./kibana-plugin-plugins-data-public.querystatechange.md)
+
+## QueryStateChange interface
+
+Signature:
+
+```typescript
+export interface QueryStateChange extends QueryStateChangePartial
+```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [appFilters](./kibana-plugin-plugins-data-public.querystatechange.appfilters.md) | boolean
| |
+| [globalFilters](./kibana-plugin-plugins-data-public.querystatechange.globalfilters.md) | boolean
| |
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md
index 9f3ed8c1263ba..cf171d9ee9f37 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md
@@ -7,5 +7,5 @@
Signature:
```typescript
-QueryStringInput: React.FC>
+QueryStringInput: React.FC>
```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md
index 498691c06285d..d1d20291a6799 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md
@@ -7,7 +7,7 @@
Signature:
```typescript
-SearchBar: React.ComponentClass, "query" | "isLoading" | "filters" | "onRefresh" | "onRefreshChange" | "refreshInterval" | "indexPatterns" | "dataTestSubj" | "customSubmitButton" | "screenTitle" | "showQueryBar" | "showQueryInput" | "showFilterBar" | "showDatePicker" | "showAutoRefreshOnly" | "isRefreshPaused" | "dateRangeFrom" | "dateRangeTo" | "showSaveQuery" | "savedQuery" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated" | "onClearSavedQuery" | "indicateNoData" | "timeHistory" | "onFiltersUpdated">, any> & {
- WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>;
+SearchBar: React.ComponentClass, "query" | "isLoading" | "filters" | "onRefresh" | "onRefreshChange" | "refreshInterval" | "indexPatterns" | "dataTestSubj" | "timeHistory" | "customSubmitButton" | "screenTitle" | "showQueryBar" | "showQueryInput" | "showFilterBar" | "showDatePicker" | "showAutoRefreshOnly" | "isRefreshPaused" | "dateRangeFrom" | "dateRangeTo" | "showSaveQuery" | "savedQuery" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated" | "onClearSavedQuery" | "indicateNoData" | "onFiltersUpdated">, any> & {
+ WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>;
}
```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md
index 6f5dd1076fb40..4c67639300883 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md
@@ -4,12 +4,12 @@
## SearchInterceptor.(constructor)
-This class should be instantiated with a `requestTimeout` corresponding with how many ms after requests are initiated that they should automatically cancel.
+Constructs a new instance of the `SearchInterceptor` class
Signature:
```typescript
-constructor(deps: SearchInterceptorDeps, requestTimeout?: number | undefined);
+constructor(deps: SearchInterceptorDeps);
```
## Parameters
@@ -17,5 +17,4 @@ constructor(deps: SearchInterceptorDeps, requestTimeout?: number | undefined);
| Parameter | Type | Description |
| --- | --- | --- |
| deps | SearchInterceptorDeps
| |
-| requestTimeout | number | undefined
| |
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md
deleted file mode 100644
index ef36b3f37b0c7..0000000000000
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [getPendingCount$](./kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md)
-
-## SearchInterceptor.getPendingCount$() method
-
-Returns an `Observable` over the current number of pending searches. This could mean that one of the search requests is still in flight, or that it has only received partial responses.
-
-Signature:
-
-```typescript
-getPendingCount$(): Observable;
-```
-Returns:
-
-`Observable`
-
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md
index 32954927504ae..5cee345db6cd2 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md
@@ -14,21 +14,18 @@ export declare class SearchInterceptor
| Constructor | Modifiers | Description |
| --- | --- | --- |
-| [(constructor)(deps, requestTimeout)](./kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md) | | This class should be instantiated with a requestTimeout
corresponding with how many ms after requests are initiated that they should automatically cancel. |
+| [(constructor)(deps)](./kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md) | | Constructs a new instance of the SearchInterceptor
class |
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [deps](./kibana-plugin-plugins-data-public.searchinterceptor.deps.md) | | SearchInterceptorDeps
| |
-| [requestTimeout](./kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md) | | number | undefined
| |
+| [showTimeoutError](./kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md) | | ((e: Error) => void) & import("lodash").Cancelable
| |
## Methods
| Method | Modifiers | Description |
| --- | --- | --- |
-| [getPendingCount$()](./kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md) | | Returns an Observable
over the current number of pending searches. This could mean that one of the search requests is still in flight, or that it has only received partial responses. |
-| [runSearch(request, signal, strategy)](./kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md) | | |
| [search(request, options)](./kibana-plugin-plugins-data-public.searchinterceptor.search.md) | | Searches using the given search
method. Overrides the AbortSignal
with one that will abort either when cancelPending
is called, when the request times out, or when the original AbortSignal
is aborted. Updates pendingCount$
when the request is started/finalized. |
-| [setupTimers(options)](./kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md) | | |
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md
deleted file mode 100644
index 3123433762991..0000000000000
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [requestTimeout](./kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md)
-
-## SearchInterceptor.requestTimeout property
-
-Signature:
-
-```typescript
-protected readonly requestTimeout?: number | undefined;
-```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md
deleted file mode 100644
index ad1d1dcb59d7b..0000000000000
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [runSearch](./kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md)
-
-## SearchInterceptor.runSearch() method
-
-Signature:
-
-```typescript
-protected runSearch(request: IEsSearchRequest, signal: AbortSignal, strategy?: string): Observable;
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| request | IEsSearchRequest
| |
-| signal | AbortSignal
| |
-| strategy | string
| |
-
-Returns:
-
-`Observable`
-
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md
deleted file mode 100644
index fe35655258b4c..0000000000000
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [setupTimers](./kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md)
-
-## SearchInterceptor.setupTimers() method
-
-Signature:
-
-```typescript
-protected setupTimers(options?: ISearchOptions): {
- combinedSignal: AbortSignal;
- cleanup: () => void;
- };
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| options | ISearchOptions
| |
-
-Returns:
-
-`{
- combinedSignal: AbortSignal;
- cleanup: () => void;
- }`
-
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md
new file mode 100644
index 0000000000000..91ecb2821acbf
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [showTimeoutError](./kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md)
+
+## SearchInterceptor.showTimeoutError property
+
+Signature:
+
+```typescript
+protected showTimeoutError: ((e: Error) => void) & import("lodash").Cancelable;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource._constructor_.md
new file mode 100644
index 0000000000000..00e9050ee8ff9
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource._constructor_.md
@@ -0,0 +1,21 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [(constructor)](./kibana-plugin-plugins-data-public.searchsource._constructor_.md)
+
+## SearchSource.(constructor)
+
+Constructs a new instance of the `SearchSource` class
+
+Signature:
+
+```typescript
+constructor(fields: SearchSourceFields | undefined, dependencies: SearchSourceDependencies);
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| fields | SearchSourceFields | undefined
| |
+| dependencies | SearchSourceDependencies
| |
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.create.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.create.md
new file mode 100644
index 0000000000000..4264c3ff224b1
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.create.md
@@ -0,0 +1,20 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [create](./kibana-plugin-plugins-data-public.searchsource.create.md)
+
+## SearchSource.create() method
+
+> Warning: This API is now obsolete.
+>
+> Don't use.
+>
+
+Signature:
+
+```typescript
+create(): SearchSource;
+```
+Returns:
+
+`SearchSource`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.createchild.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.createchild.md
new file mode 100644
index 0000000000000..0c2e75651b354
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.createchild.md
@@ -0,0 +1,24 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [createChild](./kibana-plugin-plugins-data-public.searchsource.createchild.md)
+
+## SearchSource.createChild() method
+
+creates a new child search source
+
+Signature:
+
+```typescript
+createChild(options?: {}): SearchSource;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| options | {}
| |
+
+Returns:
+
+`SearchSource`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.createcopy.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.createcopy.md
new file mode 100644
index 0000000000000..1053d31010d00
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.createcopy.md
@@ -0,0 +1,17 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [createCopy](./kibana-plugin-plugins-data-public.searchsource.createcopy.md)
+
+## SearchSource.createCopy() method
+
+creates a copy of this search source (without its children)
+
+Signature:
+
+```typescript
+createCopy(): SearchSource;
+```
+Returns:
+
+`SearchSource`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.destroy.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.destroy.md
new file mode 100644
index 0000000000000..8a7cc5ee75d11
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.destroy.md
@@ -0,0 +1,17 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [destroy](./kibana-plugin-plugins-data-public.searchsource.destroy.md)
+
+## SearchSource.destroy() method
+
+Completely destroy the SearchSource. {undefined}
+
+Signature:
+
+```typescript
+destroy(): void;
+```
+Returns:
+
+`void`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.fetch.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.fetch.md
new file mode 100644
index 0000000000000..8fd17e6b1a1d9
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.fetch.md
@@ -0,0 +1,25 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [fetch](./kibana-plugin-plugins-data-public.searchsource.fetch.md)
+
+## SearchSource.fetch() method
+
+Fetch this source and reject the returned Promise on error
+
+
+Signature:
+
+```typescript
+fetch(options?: ISearchOptions): Promise>;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| options | ISearchOptions
| |
+
+Returns:
+
+`Promise>`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getfield.md
new file mode 100644
index 0000000000000..7c516cc29df15
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getfield.md
@@ -0,0 +1,25 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [getField](./kibana-plugin-plugins-data-public.searchsource.getfield.md)
+
+## SearchSource.getField() method
+
+Gets a single field from the fields
+
+Signature:
+
+```typescript
+getField(field: K, recurse?: boolean): SearchSourceFields[K];
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| field | K
| |
+| recurse | boolean
| |
+
+Returns:
+
+`SearchSourceFields[K]`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getfields.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getfields.md
new file mode 100644
index 0000000000000..1980227bee623
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getfields.md
@@ -0,0 +1,51 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [getFields](./kibana-plugin-plugins-data-public.searchsource.getfields.md)
+
+## SearchSource.getFields() method
+
+returns all search source fields
+
+Signature:
+
+```typescript
+getFields(): {
+ type?: string | undefined;
+ query?: import("../..").Query | undefined;
+ filter?: Filter | Filter[] | (() => Filter | Filter[] | undefined) | undefined;
+ sort?: Record | Record[] | undefined;
+ highlight?: any;
+ highlightAll?: boolean | undefined;
+ aggs?: any;
+ from?: number | undefined;
+ size?: number | undefined;
+ source?: string | boolean | string[] | undefined;
+ version?: boolean | undefined;
+ fields?: string | boolean | string[] | undefined;
+ index?: import("../..").IndexPattern | undefined;
+ searchAfter?: import("./types").EsQuerySearchAfter | undefined;
+ timeout?: string | undefined;
+ terminate_after?: number | undefined;
+ };
+```
+Returns:
+
+`{
+ type?: string | undefined;
+ query?: import("../..").Query | undefined;
+ filter?: Filter | Filter[] | (() => Filter | Filter[] | undefined) | undefined;
+ sort?: Record | Record[] | undefined;
+ highlight?: any;
+ highlightAll?: boolean | undefined;
+ aggs?: any;
+ from?: number | undefined;
+ size?: number | undefined;
+ source?: string | boolean | string[] | undefined;
+ version?: boolean | undefined;
+ fields?: string | boolean | string[] | undefined;
+ index?: import("../..").IndexPattern | undefined;
+ searchAfter?: import("./types").EsQuerySearchAfter | undefined;
+ timeout?: string | undefined;
+ terminate_after?: number | undefined;
+ }`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getid.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getid.md
new file mode 100644
index 0000000000000..b33410d86ae85
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getid.md
@@ -0,0 +1,17 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [getId](./kibana-plugin-plugins-data-public.searchsource.getid.md)
+
+## SearchSource.getId() method
+
+returns search source id
+
+Signature:
+
+```typescript
+getId(): string;
+```
+Returns:
+
+`string`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getownfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getownfield.md
new file mode 100644
index 0000000000000..d5a133772264e
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getownfield.md
@@ -0,0 +1,24 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [getOwnField](./kibana-plugin-plugins-data-public.searchsource.getownfield.md)
+
+## SearchSource.getOwnField() method
+
+Get the field from our own fields, don't traverse up the chain
+
+Signature:
+
+```typescript
+getOwnField(field: K): SearchSourceFields[K];
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| field | K
| |
+
+Returns:
+
+`SearchSourceFields[K]`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getparent.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getparent.md
new file mode 100644
index 0000000000000..14578f7949ba6
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getparent.md
@@ -0,0 +1,17 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [getParent](./kibana-plugin-plugins-data-public.searchsource.getparent.md)
+
+## SearchSource.getParent() method
+
+Get the parent of this SearchSource {undefined\|searchSource}
+
+Signature:
+
+```typescript
+getParent(): SearchSource | undefined;
+```
+Returns:
+
+`SearchSource | undefined`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getsearchrequestbody.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getsearchrequestbody.md
new file mode 100644
index 0000000000000..cc50d3f017971
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getsearchrequestbody.md
@@ -0,0 +1,17 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [getSearchRequestBody](./kibana-plugin-plugins-data-public.searchsource.getsearchrequestbody.md)
+
+## SearchSource.getSearchRequestBody() method
+
+Returns body contents of the search request, often referred as query DSL.
+
+Signature:
+
+```typescript
+getSearchRequestBody(): Promise;
+```
+Returns:
+
+`Promise`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getserializedfields.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getserializedfields.md
new file mode 100644
index 0000000000000..3f58a76b24cd0
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.getserializedfields.md
@@ -0,0 +1,17 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [getSerializedFields](./kibana-plugin-plugins-data-public.searchsource.getserializedfields.md)
+
+## SearchSource.getSerializedFields() method
+
+serializes search source fields (which can later be passed to [ISearchStartSearchSource](./kibana-plugin-plugins-data-public.isearchstartsearchsource.md))
+
+Signature:
+
+```typescript
+getSerializedFields(): SearchSourceFields;
+```
+Returns:
+
+`SearchSourceFields`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.history.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.history.md
new file mode 100644
index 0000000000000..e77c9dac7239f
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.history.md
@@ -0,0 +1,11 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [history](./kibana-plugin-plugins-data-public.searchsource.history.md)
+
+## SearchSource.history property
+
+Signature:
+
+```typescript
+history: SearchRequest[];
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.md
new file mode 100644
index 0000000000000..87346f81b13e2
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.md
@@ -0,0 +1,49 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md)
+
+## SearchSource class
+
+\*
+
+Signature:
+
+```typescript
+export declare class SearchSource
+```
+
+## Constructors
+
+| Constructor | Modifiers | Description |
+| --- | --- | --- |
+| [(constructor)(fields, dependencies)](./kibana-plugin-plugins-data-public.searchsource._constructor_.md) | | Constructs a new instance of the SearchSource
class |
+
+## Properties
+
+| Property | Modifiers | Type | Description |
+| --- | --- | --- | --- |
+| [history](./kibana-plugin-plugins-data-public.searchsource.history.md) | | SearchRequest[]
| |
+
+## Methods
+
+| Method | Modifiers | Description |
+| --- | --- | --- |
+| [create()](./kibana-plugin-plugins-data-public.searchsource.create.md) | | |
+| [createChild(options)](./kibana-plugin-plugins-data-public.searchsource.createchild.md) | | creates a new child search source |
+| [createCopy()](./kibana-plugin-plugins-data-public.searchsource.createcopy.md) | | creates a copy of this search source (without its children) |
+| [destroy()](./kibana-plugin-plugins-data-public.searchsource.destroy.md) | | Completely destroy the SearchSource. {undefined} |
+| [fetch(options)](./kibana-plugin-plugins-data-public.searchsource.fetch.md) | | Fetch this source and reject the returned Promise on error |
+| [getField(field, recurse)](./kibana-plugin-plugins-data-public.searchsource.getfield.md) | | Gets a single field from the fields |
+| [getFields()](./kibana-plugin-plugins-data-public.searchsource.getfields.md) | | returns all search source fields |
+| [getId()](./kibana-plugin-plugins-data-public.searchsource.getid.md) | | returns search source id |
+| [getOwnField(field)](./kibana-plugin-plugins-data-public.searchsource.getownfield.md) | | Get the field from our own fields, don't traverse up the chain |
+| [getParent()](./kibana-plugin-plugins-data-public.searchsource.getparent.md) | | Get the parent of this SearchSource {undefined\|searchSource} |
+| [getSearchRequestBody()](./kibana-plugin-plugins-data-public.searchsource.getsearchrequestbody.md) | | Returns body contents of the search request, often referred as query DSL. |
+| [getSerializedFields()](./kibana-plugin-plugins-data-public.searchsource.getserializedfields.md) | | serializes search source fields (which can later be passed to [ISearchStartSearchSource](./kibana-plugin-plugins-data-public.isearchstartsearchsource.md)) |
+| [onRequestStart(handler)](./kibana-plugin-plugins-data-public.searchsource.onrequeststart.md) | | Add a handler that will be notified whenever requests start |
+| [serialize()](./kibana-plugin-plugins-data-public.searchsource.serialize.md) | | Serializes the instance to a JSON string and a set of referenced objects. Use this method to get a representation of the search source which can be stored in a saved object.The references returned by this function can be mixed with other references in the same object, however make sure there are no name-collisions. The references will be named kibanaSavedObjectMeta.searchSourceJSON.index
and kibanaSavedObjectMeta.searchSourceJSON.filter[<number>].meta.index
.Using createSearchSource
, the instance can be re-created. |
+| [setField(field, value)](./kibana-plugin-plugins-data-public.searchsource.setfield.md) | | sets value to a single search source feild |
+| [setFields(newFields)](./kibana-plugin-plugins-data-public.searchsource.setfields.md) | | Internal, do not use. Overrides all search source fields with the new field array. |
+| [setParent(parent, options)](./kibana-plugin-plugins-data-public.searchsource.setparent.md) | | Set a searchSource that this source should inherit from |
+| [setPreferredSearchStrategyId(searchStrategyId)](./kibana-plugin-plugins-data-public.searchsource.setpreferredsearchstrategyid.md) | | internal, dont use |
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.onrequeststart.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.onrequeststart.md
new file mode 100644
index 0000000000000..a9386ddae44e1
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.onrequeststart.md
@@ -0,0 +1,24 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [onRequestStart](./kibana-plugin-plugins-data-public.searchsource.onrequeststart.md)
+
+## SearchSource.onRequestStart() method
+
+Add a handler that will be notified whenever requests start
+
+Signature:
+
+```typescript
+onRequestStart(handler: (searchSource: SearchSource, options?: ISearchOptions) => Promise): void;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| handler | (searchSource: SearchSource, options?: ISearchOptions) => Promise<unknown>
| |
+
+Returns:
+
+`void`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md
new file mode 100644
index 0000000000000..73ba8eb66040b
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.serialize.md
@@ -0,0 +1,27 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [serialize](./kibana-plugin-plugins-data-public.searchsource.serialize.md)
+
+## SearchSource.serialize() method
+
+Serializes the instance to a JSON string and a set of referenced objects. Use this method to get a representation of the search source which can be stored in a saved object.
+
+The references returned by this function can be mixed with other references in the same object, however make sure there are no name-collisions. The references will be named `kibanaSavedObjectMeta.searchSourceJSON.index` and `kibanaSavedObjectMeta.searchSourceJSON.filter[].meta.index`.
+
+Using `createSearchSource`, the instance can be re-created.
+
+Signature:
+
+```typescript
+serialize(): {
+ searchSourceJSON: string;
+ references: import("../../../../../core/public").SavedObjectReference[];
+ };
+```
+Returns:
+
+`{
+ searchSourceJSON: string;
+ references: import("../../../../../core/public").SavedObjectReference[];
+ }`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.setfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.setfield.md
new file mode 100644
index 0000000000000..22619940f1589
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.setfield.md
@@ -0,0 +1,25 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [setField](./kibana-plugin-plugins-data-public.searchsource.setfield.md)
+
+## SearchSource.setField() method
+
+sets value to a single search source feild
+
+Signature:
+
+```typescript
+setField(field: K, value: SearchSourceFields[K]): this;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| field | K
| |
+| value | SearchSourceFields[K]
| |
+
+Returns:
+
+`this`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.setfields.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.setfields.md
new file mode 100644
index 0000000000000..f92ffc0fc991d
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.setfields.md
@@ -0,0 +1,25 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [setFields](./kibana-plugin-plugins-data-public.searchsource.setfields.md)
+
+## SearchSource.setFields() method
+
+Internal, do not use. Overrides all search source fields with the new field array.
+
+
+Signature:
+
+```typescript
+setFields(newFields: SearchSourceFields): this;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| newFields | SearchSourceFields
| |
+
+Returns:
+
+`this`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.setparent.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.setparent.md
new file mode 100644
index 0000000000000..19bf10bec210f
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.setparent.md
@@ -0,0 +1,25 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [setParent](./kibana-plugin-plugins-data-public.searchsource.setparent.md)
+
+## SearchSource.setParent() method
+
+Set a searchSource that this source should inherit from
+
+Signature:
+
+```typescript
+setParent(parent?: ISearchSource, options?: SearchSourceOptions): this;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| parent | ISearchSource
| |
+| options | SearchSourceOptions
| |
+
+Returns:
+
+`this`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.setpreferredsearchstrategyid.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.setpreferredsearchstrategyid.md
new file mode 100644
index 0000000000000..e3261873ba104
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsource.setpreferredsearchstrategyid.md
@@ -0,0 +1,24 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchSource](./kibana-plugin-plugins-data-public.searchsource.md) > [setPreferredSearchStrategyId](./kibana-plugin-plugins-data-public.searchsource.setpreferredsearchstrategyid.md)
+
+## SearchSource.setPreferredSearchStrategyId() method
+
+internal, dont use
+
+Signature:
+
+```typescript
+setPreferredSearchStrategyId(searchStrategyId: string): void;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| searchStrategyId | string
| |
+
+Returns:
+
+`void`
+
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.aggs.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.aggs.md
index 743646708b4c6..f6bab8e424857 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.aggs.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.aggs.md
@@ -4,6 +4,8 @@
## SearchSourceFields.aggs property
+[AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md)
+
Signature:
```typescript
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.filter.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.filter.md
index a14d33420a22d..5fd615cc647d2 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.filter.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.filter.md
@@ -4,6 +4,8 @@
## SearchSourceFields.filter property
+[Filter](./kibana-plugin-plugins-data-public.filter.md)
+
Signature:
```typescript
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.index.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.index.md
index fa1d1a552a560..cf1b1cfa253fd 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.index.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.index.md
@@ -4,6 +4,7 @@
## SearchSourceFields.index property
+
Signature:
```typescript
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.md
index 7a64af0f8b2b8..d19f1da439cee 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.md
@@ -4,6 +4,8 @@
## SearchSourceFields interface
+search source fields
+
Signature:
```typescript
@@ -14,17 +16,17 @@ export interface SearchSourceFields
| Property | Type | Description |
| --- | --- | --- |
-| [aggs](./kibana-plugin-plugins-data-public.searchsourcefields.aggs.md) | any
| |
+| [aggs](./kibana-plugin-plugins-data-public.searchsourcefields.aggs.md) | any
| [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) |
| [fields](./kibana-plugin-plugins-data-public.searchsourcefields.fields.md) | NameList
| |
-| [filter](./kibana-plugin-plugins-data-public.searchsourcefields.filter.md) | Filter[] | Filter | (() => Filter[] | Filter | undefined)
| |
+| [filter](./kibana-plugin-plugins-data-public.searchsourcefields.filter.md) | Filter[] | Filter | (() => Filter[] | Filter | undefined)
| [Filter](./kibana-plugin-plugins-data-public.filter.md) |
| [from](./kibana-plugin-plugins-data-public.searchsourcefields.from.md) | number
| |
| [highlight](./kibana-plugin-plugins-data-public.searchsourcefields.highlight.md) | any
| |
| [highlightAll](./kibana-plugin-plugins-data-public.searchsourcefields.highlightall.md) | boolean
| |
| [index](./kibana-plugin-plugins-data-public.searchsourcefields.index.md) | IndexPattern
| |
-| [query](./kibana-plugin-plugins-data-public.searchsourcefields.query.md) | Query
| |
+| [query](./kibana-plugin-plugins-data-public.searchsourcefields.query.md) | Query
| [Query](./kibana-plugin-plugins-data-public.query.md) |
| [searchAfter](./kibana-plugin-plugins-data-public.searchsourcefields.searchafter.md) | EsQuerySearchAfter
| |
| [size](./kibana-plugin-plugins-data-public.searchsourcefields.size.md) | number
| |
-| [sort](./kibana-plugin-plugins-data-public.searchsourcefields.sort.md) | EsQuerySortValue | EsQuerySortValue[]
| |
+| [sort](./kibana-plugin-plugins-data-public.searchsourcefields.sort.md) | EsQuerySortValue | EsQuerySortValue[]
| [EsQuerySortValue](./kibana-plugin-plugins-data-public.esquerysortvalue.md) |
| [source](./kibana-plugin-plugins-data-public.searchsourcefields.source.md) | NameList
| |
| [terminate\_after](./kibana-plugin-plugins-data-public.searchsourcefields.terminate_after.md) | number
| |
| [timeout](./kibana-plugin-plugins-data-public.searchsourcefields.timeout.md) | string
| |
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.query.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.query.md
index 687dafce798d1..661ce94a06afb 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.query.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.query.md
@@ -4,6 +4,8 @@
## SearchSourceFields.query property
+[Query](./kibana-plugin-plugins-data-public.query.md)
+
Signature:
```typescript
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.sort.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.sort.md
index c10f556cef6d6..32f513378e35e 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.sort.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchsourcefields.sort.md
@@ -4,6 +4,8 @@
## SearchSourceFields.sort property
+[EsQuerySortValue](./kibana-plugin-plugins-data-public.esquerysortvalue.md)
+
Signature:
```typescript
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ui_settings.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ui_settings.md
index e515c3513df6c..6ed20beb396f1 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ui_settings.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ui_settings.md
@@ -20,6 +20,7 @@ UI_SETTINGS: {
readonly COURIER_MAX_CONCURRENT_SHARD_REQUESTS: "courier:maxConcurrentShardRequests";
readonly COURIER_BATCH_SEARCHES: "courier:batchSearches";
readonly SEARCH_INCLUDE_FROZEN: "search:includeFrozen";
+ readonly SEARCH_TIMEOUT: "search:timeout";
readonly HISTOGRAM_BAR_TARGET: "histogram:barTarget";
readonly HISTOGRAM_MAX_BARS: "histogram:maxBars";
readonly HISTORY_LIMIT: "history:limit";
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getdefaultsearchparams.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getdefaultsearchparams.md
index 9de005c1fd0dd..e718ca42ca30f 100644
--- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getdefaultsearchparams.md
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getdefaultsearchparams.md
@@ -7,24 +7,26 @@
Signature:
```typescript
-export declare function getDefaultSearchParams(config: SharedGlobalConfig): {
- timeout: string;
+export declare function getDefaultSearchParams(uiSettingsClient: IUiSettingsClient): Promise<{
+ maxConcurrentShardRequests: number | undefined;
+ ignoreThrottled: boolean;
ignoreUnavailable: boolean;
- restTotalHitsAsInt: boolean;
-};
+ trackTotalHits: boolean;
+}>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
-| config | SharedGlobalConfig
| |
+| uiSettingsClient | IUiSettingsClient
| |
Returns:
-`{
- timeout: string;
+`Promise<{
+ maxConcurrentShardRequests: number | undefined;
+ ignoreThrottled: boolean;
ignoreUnavailable: boolean;
- restTotalHitsAsInt: boolean;
-}`
+ trackTotalHits: boolean;
+}>`
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md
new file mode 100644
index 0000000000000..d7e2a597ff33d
--- /dev/null
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md
@@ -0,0 +1,30 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [getShardTimeout](./kibana-plugin-plugins-data-server.getshardtimeout.md)
+
+## getShardTimeout() function
+
+Signature:
+
+```typescript
+export declare function getShardTimeout(config: SharedGlobalConfig): {
+ timeout: string;
+} | {
+ timeout?: undefined;
+};
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| config | SharedGlobalConfig
| |
+
+Returns:
+
+`{
+ timeout: string;
+} | {
+ timeout?: undefined;
+}`
+
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md
index 70c32adeab9fd..f5b587d86b349 100644
--- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md
@@ -26,11 +26,13 @@
| Function | Description |
| --- | --- |
-| [getDefaultSearchParams(config)](./kibana-plugin-plugins-data-server.getdefaultsearchparams.md) | |
+| [getDefaultSearchParams(uiSettingsClient)](./kibana-plugin-plugins-data-server.getdefaultsearchparams.md) | |
+| [getShardTimeout(config)](./kibana-plugin-plugins-data-server.getshardtimeout.md) | |
| [getTime(indexPattern, timeRange, options)](./kibana-plugin-plugins-data-server.gettime.md) | |
| [parseInterval(interval)](./kibana-plugin-plugins-data-server.parseinterval.md) | |
| [plugin(initializerContext)](./kibana-plugin-plugins-data-server.plugin.md) | Static code to be shared externally |
| [shouldReadFieldFromDocValues(aggregatable, esType)](./kibana-plugin-plugins-data-server.shouldreadfieldfromdocvalues.md) | |
+| [toSnakeCase(obj)](./kibana-plugin-plugins-data-server.tosnakecase.md) | |
| [usageProvider(core)](./kibana-plugin-plugins-data-server.usageprovider.md) | |
## Interfaces
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md
index 2d9104ef894bc..455c5ecdd8195 100644
--- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md
@@ -8,7 +8,7 @@
```typescript
start(core: CoreStart): {
- search: ISearchStart>;
+ search: ISearchStart>;
fieldFormats: {
fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise;
};
@@ -27,7 +27,7 @@ start(core: CoreStart): {
Returns:
`{
- search: ISearchStart>;
+ search: ISearchStart>;
fieldFormats: {
fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise;
};
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.tosnakecase.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.tosnakecase.md
new file mode 100644
index 0000000000000..eda9e9c312e59
--- /dev/null
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.tosnakecase.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [toSnakeCase](./kibana-plugin-plugins-data-server.tosnakecase.md)
+
+## toSnakeCase() function
+
+Signature:
+
+```typescript
+export declare function toSnakeCase(obj: Record): import("lodash").Dictionary;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| obj | Record<string, any>
| |
+
+Returns:
+
+`import("lodash").Dictionary`
+
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.ui_settings.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.ui_settings.md
index e419b64cd43aa..2d4ce75b956df 100644
--- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.ui_settings.md
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.ui_settings.md
@@ -20,6 +20,7 @@ UI_SETTINGS: {
readonly COURIER_MAX_CONCURRENT_SHARD_REQUESTS: "courier:maxConcurrentShardRequests";
readonly COURIER_BATCH_SEARCHES: "courier:batchSearches";
readonly SEARCH_INCLUDE_FROZEN: "search:includeFrozen";
+ readonly SEARCH_TIMEOUT: "search:timeout";
readonly HISTOGRAM_BAR_TARGET: "histogram:barTarget";
readonly HISTOGRAM_MAX_BARS: "histogram:maxBars";
readonly HISTORY_LIMIT: "history:limit";
diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc
index a64a0330ae43f..ed20166c87f29 100644
--- a/docs/management/advanced-options.asciidoc
+++ b/docs/management/advanced-options.asciidoc
@@ -225,6 +225,7 @@ be inconsistent because different shards might be in different refresh states.
`search:includeFrozen`:: Includes {ref}/frozen-indices.html[frozen indices] in results.
Searching through frozen indices
might increase the search time. This setting is off by default. Users must opt-in to include frozen indices.
+`search:timeout`:: Change the maximum timeout for a search session or set to 0 to disable the timeout and allow queries to run to completion.
[float]
[[kibana-siem-settings]]
diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc
index 4a931aabd3646..f03022e9e9f00 100644
--- a/docs/setup/settings.asciidoc
+++ b/docs/setup/settings.asciidoc
@@ -20,12 +20,12 @@ which may cause a delay before pages start being served.
Set to `false` to disable Console. *Default: `true`*
| `cpu.cgroup.path.override:`
- | Override for cgroup cpu path when mounted in a
-manner that is inconsistent with `/proc/self/cgroup`.
+ | *deprecated* This setting has been renamed to `ops.cGroupOverrides.cpuPath`
+and the old name will no longer be supported as of 8.0.
| `cpuacct.cgroup.path.override:`
- | Override for cgroup cpuacct path when mounted
-in a manner that is inconsistent with `/proc/self/cgroup`.
+ | *deprecated* This setting has been renamed to `ops.cGroupOverrides.cpuAcctPath`
+and the old name will no longer be supported as of 8.0.
| `csp.rules:`
| A https://w3c.github.io/webappsec-csp/[content-security-policy] template
@@ -438,6 +438,14 @@ not saved in {es}. *Default: `data`*
| Set the interval in milliseconds to sample
system and process performance metrics. The minimum value is 100. *Default: `5000`*
+| `ops.cGroupOverrides.cpuPath:`
+ | Override for cgroup cpu path when mounted in a
+manner that is inconsistent with `/proc/self/cgroup`.
+
+| `ops.cGroupOverrides.cpuAcctPath:`
+ | Override for cgroup cpuacct path when mounted
+in a manner that is inconsistent with `/proc/self/cgroup`.
+
| `server.basePath:`
| Enables you to specify a path to mount {kib} at if you are
running behind a proxy. Use the `server.rewriteBasePath` setting to tell {kib}
diff --git a/docs/user/dashboard/dashboard-drilldown.asciidoc b/docs/user/dashboard/dashboard-drilldown.asciidoc
new file mode 100644
index 0000000000000..84701cae2ecc6
--- /dev/null
+++ b/docs/user/dashboard/dashboard-drilldown.asciidoc
@@ -0,0 +1,76 @@
+[[dashboard-drilldown]]
+=== Dashboard drilldown
+
+The dashboard drilldown allows you to navigate from one dashboard to another dashboard.
+For example, you might have a dashboard that shows the overall status of multiple data centers.
+You can create a drilldown that navigates from this dashboard to a dashboard
+that shows a single data center or server.
+
+This example shows a dashboard panel that contains a pie chart with a configured dashboard drilldown:
+
+[role="screenshot"]
+image::images/drilldown_on_piechart.gif[Drilldown on pie chart that navigates to another dashboard]
+
+[float]
+[[drilldowns-example]]
+==== Try it: Create a dashboard drilldown
+
+Create the *Host Overview* drilldown shown above.
+
+*Set up the dashboards*
+
+. Add the <> data set.
+
+. Create a new dashboard, called `Host Overview`, and include these visualizations
+from the sample data set:
++
+[%hardbreaks]
+*[Logs] Heatmap*
+*[Logs] Visitors by OS*
+*[Logs] Host, Visits, and Bytes Table*
+*[Logs] Total Requests and Bytes*
++
+TIP: If you don’t see data for a panel, try changing the time range.
+
+. Open the *[Logs] Web traffic* dashboard.
+
+. Set a search and filter.
++
+[%hardbreaks]
+Search: `extension.keyword:( “gz” or “css” or “deb”)`
+Filter: `geo.src : CN`
+
+
+*Create the drilldown*
+
+
+. In the dashboard menu bar, click *Edit*.
+
+. In *[Logs] Visitors by OS*, open the panel menu, and then select *Create drilldown*.
+
+. Pick *Go to dashboard* action.
+
+. Give the drilldown a name.
+
+. Select *Host Overview* as the destination dashboard.
+
+. Keep both filters enabled so that the drilldown carries over the global filters and date range.
++
+Your input should look similar to this:
++
+[role="screenshot"]
+image::images/drilldown_create.png[Create drilldown with entries for drilldown name and destination]
+
+. Click *Create drilldown.*
+
+. Save the dashboard.
++
+If you don’t save the drilldown, and then navigate away, the drilldown is lost.
+
+. In *[Logs] Visitors by OS*, click the `win 8` slice of the pie, and then select the name of your drilldown.
++
+[role="screenshot"]
+image::images/drilldown_on_panel.png[Drilldown on pie chart that navigates to another dashboard]
++
+You are navigated to your destination dashboard. Verify that the search query, filters,
+and time range are carried over.
diff --git a/docs/user/dashboard/dashboard.asciidoc b/docs/user/dashboard/dashboard.asciidoc
index 0c0151cc3ace2..c8bff91be91a6 100644
--- a/docs/user/dashboard/dashboard.asciidoc
+++ b/docs/user/dashboard/dashboard.asciidoc
@@ -4,9 +4,9 @@
[partintro]
--
-A _dashboard_ is a collection of panels that you use to analyze your data. On a dashboard, you can add a variety of panels that
-you can rearrange and tell a story about your data. Panels contain everything you need, including visualizations,
-interactive controls, markdown, and more.
+A _dashboard_ is a collection of panels that you use to analyze your data. On a dashboard, you can add a variety of panels that
+you can rearrange and tell a story about your data. Panels contain everything you need, including visualizations,
+interactive controls, markdown, and more.
With *Dashboard*s, you can:
@@ -18,7 +18,7 @@ With *Dashboard*s, you can:
* Create and apply filters to focus on the data you want to display.
-* Control who can use your data, and share the dashboard with a small or large audience.
+* Control who can use your data, and share the dashboard with a small or large audience.
* Generate reports based on your findings.
@@ -42,7 +42,7 @@ image::images/dashboard-read-only-badge.png[Example of Dashboard read only acces
[[types-of-panels]]
== Types of panels
-Panels contain everything you need to tell a story about you data, including visualizations,
+Panels contain everything you need to tell a story about you data, including visualizations,
interactive controls, Markdown, and more.
[cols="50, 50"]
@@ -50,30 +50,30 @@ interactive controls, Markdown, and more.
a| *Area*
-Displays data points, connected by a line, where the area between the line and axes are shaded.
+Displays data points, connected by a line, where the area between the line and axes are shaded.
Use area charts to compare two or more categories over time, and display the magnitude of trends.
| image:images/area.png[Area chart]
a| *Stacked area*
-Displays the evolution of the value of several data groups. The values of each group are displayed
-on top of each other. Use stacked area charts to visualize part-to-whole relationships, and to show
+Displays the evolution of the value of several data groups. The values of each group are displayed
+on top of each other. Use stacked area charts to visualize part-to-whole relationships, and to show
how each category contributes to the cumulative total.
| image:images/stacked_area.png[Stacked area chart]
a| *Bar*
-Displays bars side-by-side where each bar represents a category. Use bar charts to compare data across a
-large number of categories, display data that includes categories with negative values, and easily identify
+Displays bars side-by-side where each bar represents a category. Use bar charts to compare data across a
+large number of categories, display data that includes categories with negative values, and easily identify
the categories that represent the highest and lowest values. Kibana also supports horizontal bar charts.
| image:images/bar.png[Bar chart]
a| *Stacked bar*
-Displays numeric values across two or more categories. Use stacked bar charts to compare numeric values between
+Displays numeric values across two or more categories. Use stacked bar charts to compare numeric values between
levels of a categorical value. Kibana also supports stacked horizontal bar charts.
| image:images/stacked_bar.png[Stacked area chart]
@@ -81,15 +81,15 @@ levels of a categorical value. Kibana also supports stacked horizontal bar chart
a| *Line*
-Displays data points that are connected by a line. Use line charts to visualize a sequence of values, discover
+Displays data points that are connected by a line. Use line charts to visualize a sequence of values, discover
trends over time, and forecast future values.
| image:images/line.png[Line chart]
a| *Pie*
-Displays slices that represent a data category, where the slice size is proportional to the quantity it represents.
-Use pie charts to show comparisons between multiple categories, illustrate the dominance of one category over others,
+Displays slices that represent a data category, where the slice size is proportional to the quantity it represents.
+Use pie charts to show comparisons between multiple categories, illustrate the dominance of one category over others,
and show percentage or proportional data.
| image:images/pie.png[Pie chart]
@@ -103,7 +103,7 @@ Similar to the pie chart, but the central circle is removed. Use donut charts wh
a| *Tree map*
-Relates different segments of your data to the whole. Each rectangle is subdivided into smaller rectangles, or sub branches, based on
+Relates different segments of your data to the whole. Each rectangle is subdivided into smaller rectangles, or sub branches, based on
its proportion to the whole. Use treemaps to make efficient use of space to show percent total for each category.
| image:images/treemap.png[Tree map]
@@ -111,7 +111,7 @@ its proportion to the whole. Use treemaps to make efficient use of space to show
a| *Heat map*
-Displays graphical representations of data where the individual values are represented by colors. Use heat maps when your data set includes
+Displays graphical representations of data where the individual values are represented by colors. Use heat maps when your data set includes
categorical data. For example, use a heat map to see the flights of origin countries compared to destination countries using the sample flight data.
| image:images/heat_map.png[Heat map]
@@ -125,7 +125,7 @@ Displays how your metric progresses toward a fixed goal. Use the goal to display
a| *Gauge*
-Displays your data along a scale that changes color according to where your data falls on the expected scale. Use the gauge to show how metric
+Displays your data along a scale that changes color according to where your data falls on the expected scale. Use the gauge to show how metric
values relate to reference threshold values, or determine how a specified field is performing versus how it is expected to perform.
| image:images/gauge.png[Gauge]
@@ -133,7 +133,7 @@ values relate to reference threshold values, or determine how a specified field
a| *Metric*
-Displays a single numeric value for an aggregation. Use the metric visualization when you have a numeric value that is powerful enough to tell
+Displays a single numeric value for an aggregation. Use the metric visualization when you have a numeric value that is powerful enough to tell
a story about your data.
| image:images/metric.png[Metric]
@@ -141,7 +141,7 @@ a story about your data.
a| *Data table*
-Displays your raw data or aggregation results in a tabular format. Use data tables to display server configuration details, track counts, min,
+Displays your raw data or aggregation results in a tabular format. Use data tables to display server configuration details, track counts, min,
or max values for a specific field, and monitor the status of key services.
| image:images/data_table.png[Data table]
@@ -149,7 +149,7 @@ or max values for a specific field, and monitor the status of key services.
a| *Tag cloud*
-Graphical representations of how frequently a word appears in the source text. Use tag clouds to easily produce a summary of large documents and
+Graphical representations of how frequently a word appears in the source text. Use tag clouds to easily produce a summary of large documents and
create visual art for a specific topic.
| image:images/tag_cloud.png[Tag cloud]
@@ -168,16 +168,16 @@ For all your mapping needs, use <>.
[[create-panels]]
== Create panels
-To create a panel, make sure you have {ref}/getting-started-index.html[data indexed into {es}] and an <>
-to retrieve the data from {es}. If you aren’t ready to use your own data, {kib} comes with several pre-built dashboards that you can test out. For more information,
+To create a panel, make sure you have {ref}/getting-started-index.html[data indexed into {es}] and an <>
+to retrieve the data from {es}. If you aren’t ready to use your own data, {kib} comes with several pre-built dashboards that you can test out. For more information,
refer to <>.
-To begin, click *Create new*, then choose one of the following options on the
+To begin, click *Create new*, then choose one of the following options on the
*New Visualization* window:
-* Click on the type of panel you want to create, then configure the options.
+* Click on the type of panel you want to create, then configure the options.
-* Select an editor to help you create the panel.
+* Select an editor to help you create the panel.
[role="screenshot"]
image:images/Dashboard_add_new_visualization.png[Example add new visualization to dashboard]
@@ -188,19 +188,19 @@ image:images/Dashboard_add_new_visualization.png[Example add new visualization t
[[lens]]
=== Create panels with Lens
-*Lens* is the simplest and fastest way to create powerful visualizations of your data. To use *Lens*, you drag and drop as many data fields
+*Lens* is the simplest and fastest way to create powerful visualizations of your data. To use *Lens*, you drag and drop as many data fields
as you want onto the visualization builder pane, and *Lens* uses heuristics to decide how to apply each field to the visualization.
With *Lens*, you can:
* Use the automatically generated suggestions to change the visualization type.
-* Create visualizations with multiple layers and indices.
+* Create visualizations with multiple layers and indices.
* Change the aggregation and labels to customize the data.
[role="screenshot"]
image::images/lens_drag_drop.gif[Drag and drop]
-TIP: Drag-and-drop capabilities are available only when *Lens* knows how to use the data. If *Lens* is unable to automatically generate a
+TIP: Drag-and-drop capabilities are available only when *Lens* knows how to use the data. If *Lens* is unable to automatically generate a
visualization, configure the customization options for your visualization.
[float]
@@ -220,7 +220,7 @@ To filter the data fields:
[[view-data-summaries]]
==== View data summaries
-To help you decide exactly the data you want to display, get a quick summary of each field. The summary shows the distribution of
+To help you decide exactly the data you want to display, get a quick summary of each field. The summary shows the distribution of
values within the specified time range.
To view the data field summary information, navigate to the field, then click *i*.
@@ -250,10 +250,10 @@ When there is an exclamation point (!) next to a visualization type, *Lens* is u
[[customize-the-data]]
==== Customize the data
-For each visualization type, you can customize the aggregation and labels. The options available depend on the selected visualization type.
+For each visualization type, you can customize the aggregation and labels. The options available depend on the selected visualization type.
. Click a data field name in the editor, or click *Drop a field here*.
-. Change the options that appear.
+. Change the options that appear.
+
[role="screenshot"]
image::images/lens_aggregation_labels.png[Quick function options]
@@ -262,7 +262,7 @@ image::images/lens_aggregation_labels.png[Quick function options]
[[add-layers-and-indices]]
==== Add layers and indices
-To compare and analyze data from different sources, you can visualize multiple data layers and indices. Multiple layers and indices are
+To compare and analyze data from different sources, you can visualize multiple data layers and indices. Multiple layers and indices are
supported in area, line, and bar charts.
To add a layer, click *+*, then drag and drop the data fields for the new layer.
@@ -281,7 +281,7 @@ Ready to try out *Lens*? Refer to the <>.
[[tsvb]]
=== Create panels with TSVB
-*TSVB* is a time series data visualizer that allows you to use the full power of the Elasticsearch aggregation framework. To use *TSVB*,
+*TSVB* is a time series data visualizer that allows you to use the full power of the Elasticsearch aggregation framework. To use *TSVB*,
you can combine an infinite number of <> to display your data.
With *TSVB*, you can:
@@ -295,15 +295,15 @@ image::images/tsvb.png[TSVB UI]
[float]
[[configure-the-data]]
-==== Configure the data
+==== Configure the data
-With *TSVB*, you can add and display multiple data sets to compare and analyze. {kib} uses many types of <> that you can use to build
+With *TSVB*, you can add and display multiple data sets to compare and analyze. {kib} uses many types of <> that you can use to build
complex summaries of that data.
. Select *Data*. If you are using *Table*, select *Columns*.
-. From the *Aggregation* drop down, select the aggregation you want to visualize.
+. From the *Aggregation* drop down, select the aggregation you want to visualize.
+
-If you don’t see any data, change the <>.
+If you don’t see any data, change the <>.
+
To add multiple aggregations, click *+*.
. From the *Group by* drop down, select how you want to group or split the data.
@@ -315,14 +315,14 @@ When you have more than one aggregation, the last value is displayed, which is i
[[change-the-data-display]]
==== Change the data display
-To find the best way to display your data, *TSVB* supports several types of panels and charts.
+To find the best way to display your data, *TSVB* supports several types of panels and charts.
To change the *Time Series* chart type:
. Click *Data > Options*.
. Select the *Chart type*.
-To change the panel type, click on the panel options:
+To change the panel type, click on the panel options:
[role="screenshot"]
image::images/tsvb_change_display.gif[TSVB change the panel type]
@@ -331,7 +331,7 @@ image::images/tsvb_change_display.gif[TSVB change the panel type]
[[custommize-the-data]]
==== Customize the data
-View data in a different <>, and change the data label name and colors. The options available depend on the panel type.
+View data in a different <>, and change the data label name and colors. The options available depend on the panel type.
To change the index pattern, click *Panel options*, then enter the new *Index Pattern*.
@@ -361,7 +361,7 @@ image::images/tsvb_annotations.png[TSVB annotations]
[[filter-the-panel]]
==== Filter the panel
-The data that displays on the panel is based on the <> and <>.
+The data that displays on the panel is based on the <> and <>.
You can filter the data on the panels using the <>.
Click *Panel options*, then enter the syntax in the *Panel Filter* field.
@@ -372,7 +372,7 @@ If you want to ignore filters from all of {kib}, select *Yes* for *Ignore global
[[vega]]
=== Create custom panels with Vega
-Build custom visualizations using *Vega* and *Vega-Lite*, backed by one or more data sources including {es}, Elastic Map Service,
+Build custom visualizations using *Vega* and *Vega-Lite*, backed by one or more data sources including {es}, Elastic Map Service,
URL, or static data. Use the {kib} extensions to embed *Vega* in your dashboard, and add interactive tools.
Use *Vega* and *Vega-Lite* when you want to create a visualization for:
@@ -405,7 +405,7 @@ For more information about *Vega* and *Vega-Lite*, refer to:
[[timelion]]
=== Create panels with Timelion
-*Timelion* is a time series data visualizer that enables you to combine independent data sources within a single visualization.
+*Timelion* is a time series data visualizer that enables you to combine independent data sources within a single visualization.
*Timelion* is driven by a simple expression language that you use to:
@@ -422,9 +422,41 @@ Ready to try out Timelion? For step-by-step tutorials, refer to:
* <>
* <>
+[float]
+[[timelion-deprecation]]
+==== Timelion app deprecation
+
+Deprecated since 7.0, the Timelion app will be removed in 8.0. If you have any Timelion worksheets, you must migrate them to a dashboard.
+
+NOTE: Only the Timelion app is deprecated. {kib} continues to support Timelion
+visualizations on dashboards and in Visualize and Canvas.
+
+To migrate a Timelion worksheet to a dashboard:
+
+. Open the menu, click **Dashboard**, then click **Create dashboard**.
+
+. On the dashboard, click **Create New**, then select the Timelion visualization.
+
+. On a new tab, open the Timelion app, select the chart you want to copy, and copy its expression.
++
+[role="screenshot"]
+image::images/timelion-copy-expression.png[]
+
+. Return to the other tab and paste the copied expression to the *Timelion Expression* field and click **Update**.
++
+[role="screenshot"]
+image::images/timelion-vis-paste-expression.png[]
+
+. Save the new visualization, give it a name, and click **Save and Return**.
++
+Your Timelion visualization will appear on the dashboard. Repeat this for all your charts on each worksheet.
++
+[role="screenshot"]
+image::images/timelion-dashboard.png[]
+
[float]
[[save-panels]]
-=== Save panels
+== Save panels
When you’ve finished making changes, save the panels.
@@ -436,7 +468,7 @@ When you’ve finished making changes, save the panels.
[[add-existing-panels]]
== Add existing panels
-Add panels that you’ve already created to your dashboard.
+Add panels that you’ve already created to your dashboard.
On the dashboard, click *Add an existing*, then select the panel you want to add.
@@ -445,7 +477,7 @@ When a panel contains a stored query, both queries are applied.
[role="screenshot"]
image:images/Dashboard_add_visualization.png[Example add visualization to dashboard]
-To make changes to the panel, put the dashboard in *Edit* mode, then select the edit option from the panel menu.
+To make changes to the panel, put the dashboard in *Edit* mode, then select the edit option from the panel menu.
The changes you make appear in every dashboard that uses the panel, except if you edit the panel title. Changes to the panel title appear only on the dashboard where you made the change.
[float]
@@ -463,6 +495,8 @@ include::edit-dashboards.asciidoc[]
include::explore-dashboard-data.asciidoc[]
+include::drilldowns.asciidoc[]
+
include::share-dashboards.asciidoc[]
include::tutorials.asciidoc[]
diff --git a/docs/user/dashboard/drilldowns.asciidoc b/docs/user/dashboard/drilldowns.asciidoc
index 5fca974d58135..85230f1b6f70d 100644
--- a/docs/user/dashboard/drilldowns.asciidoc
+++ b/docs/user/dashboard/drilldowns.asciidoc
@@ -1,106 +1,51 @@
-[float]
[[drilldowns]]
-=== Use drilldowns for dashboard actions
+== Use drilldowns for dashboard actions
Drilldowns, also known as custom actions, allow you to configure a
workflow for analyzing and troubleshooting your data.
-Using a drilldown, you can navigate from one dashboard to another,
+For example, using a drilldown, you can navigate from one dashboard to another,
taking the current time range, filters, and other parameters with you,
so the context remains the same. You can continue your analysis from a new perspective.
-For example, you might have a dashboard that shows the overall status of multiple data centers.
-You can create a drilldown that navigates from this dashboard to a dashboard
-that shows a single data center or server.
-
-[float]
-[[how-drilldowns-work]]
-==== How drilldowns work
-
-Drilldowns are user-configurable {kib} actions that are stored with the
-dashboard metadata. Drilldowns are specific to the dashboard panel
-for which you create them—they are not shared across panels.
-A panel can have multiple drilldowns.
-
-This example shows a dashboard panel that contains a pie chart.
-Typically, clicking a pie slice applies the current filter.
-When a panel has a drilldown, clicking a pie slice opens a menu with
-the default action and your drilldowns. Refer to the <>
-for instructions on how to create this drilldown.
-
[role="screenshot"]
image::images/drilldown_on_piechart.gif[Drilldown on pie chart that navigates to another dashboard]
-Third-party developers can create drilldowns.
-Refer to https://github.com/elastic/kibana/tree/master/x-pack/examples/ui_actions_enhanced_examples[this example plugin]
-to learn how to code drilldowns.
-
-[float]
-[[create-manage-drilldowns]]
-==== Create and manage drilldowns
-
-Your dashboard must be in *Edit* mode to create a drilldown.
-Once a panel has at least one drilldown, the menu also includes a *Manage drilldowns* action
-for editing and deleting drilldowns.
-
-[role="screenshot"]
-image::images/drilldown_menu.png[Panel menu with Create drilldown and Manage drilldown actions]
+Drilldowns are specific to the dashboard panel for which you create them—they are not shared across panels. A panel can have multiple drilldowns.
[float]
-[[drilldowns-example]]
-==== Try it: Create a drilldown
-
-This example shows how to create the *Host Overview* drilldown shown earlier in this doc.
+[[actions]]
+=== Drilldown actions
-*Set up the dashboards*
+Drilldowns are user-configurable {kib} actions that are stored with the dashboard metadata.
+Kibana provides the following types of actions:
-. Add the <> data set.
+[cols="2"]
+|===
-. Create a new dashboard, called `Host Overview`, and include these visualizations
-from the sample data set:
-+
-[%hardbreaks]
-*[Logs] Heatmap*
-*[Logs] Visitors by OS*
-*[Logs] Host, Visits, and Bytes Table*
-*[Logs] Total Requests and Bytes*
-+
-TIP: If you don’t see data for a panel, try changing the time range.
+a| <>
-. Open the *[Logs] Web traffic* dashboard.
+| Navigate to a dashboard.
-. Set a search and filter.
-+
-[%hardbreaks]
-Search: `extension.keyword:( “gz” or “css” or “deb”)`
-Filter: `geo.src : CN`
+a| <>
-*Create the drilldown*
+| Navigate to external or internal URL.
-. In the dashboard menu bar, click *Edit*.
+|===
-. In *[Logs] Visitors by OS*, open the panel menu, and then select *Create drilldown*.
+[NOTE]
+==============================================
+Some action types are paid commercial features, while others are free.
+For a comparison of the Elastic subscription levels,
+see https://www.elastic.co/subscriptions[the subscription page].
+==============================================
-. Give the drilldown a name.
-
-. Select *Host Overview* as the destination dashboard.
-
-. Keep both filters enabled so that the drilldown carries over the global filters and date range.
-+
-Your input should look similar to this:
-+
-[role="screenshot"]
-image::images/drilldown_create.png[Create drilldown with entries for drilldown name and destination]
-
-. Click *Create drilldown.*
+[float]
+[[code-drilldowns]]
+=== Code drilldowns
+Third-party developers can create drilldowns.
+Refer to {kib-repo}blob/{branch}/x-pack/examples/ui_actions_enhanced_examples[this example plugin]
+to learn how to code drilldowns.
-. Save the dashboard.
-+
-If you don’t save the drilldown, and then navigate away, the drilldown is lost.
+include::dashboard-drilldown.asciidoc[]
+include::url-drilldown.asciidoc[]
-. In *[Logs] Visitors by OS*, click the `win 8` slice of the pie, and then select the name of your drilldown.
-+
-[role="screenshot"]
-image::images/drilldown_on_panel.png[Drilldown on pie chart that navigates to another dashboard]
-+
-You are navigated to your destination dashboard. Verify that the search query, filters,
-and time range are carried over.
diff --git a/docs/user/dashboard/explore-dashboard-data.asciidoc b/docs/user/dashboard/explore-dashboard-data.asciidoc
index a0564f5bceb3d..238dfb79e900b 100644
--- a/docs/user/dashboard/explore-dashboard-data.asciidoc
+++ b/docs/user/dashboard/explore-dashboard-data.asciidoc
@@ -16,5 +16,3 @@ The data that displays depends on the element that you inspect.
image:images/Dashboard_inspect.png[Inspect in dashboard]
include::explore-underlying-data.asciidoc[]
-
-include::drilldowns.asciidoc[]
diff --git a/docs/user/dashboard/images/drilldown_pick_an_action.png b/docs/user/dashboard/images/drilldown_pick_an_action.png
new file mode 100644
index 0000000000000..c99e931e3fbe1
Binary files /dev/null and b/docs/user/dashboard/images/drilldown_pick_an_action.png differ
diff --git a/docs/user/dashboard/images/url_drilldown_github.png b/docs/user/dashboard/images/url_drilldown_github.png
new file mode 100644
index 0000000000000..d2eaec311948e
Binary files /dev/null and b/docs/user/dashboard/images/url_drilldown_github.png differ
diff --git a/docs/user/dashboard/images/url_drilldown_go_to_github.gif b/docs/user/dashboard/images/url_drilldown_go_to_github.gif
new file mode 100644
index 0000000000000..7cca3f72d5a68
Binary files /dev/null and b/docs/user/dashboard/images/url_drilldown_go_to_github.gif differ
diff --git a/docs/user/dashboard/images/url_drilldown_pick_an_action.png b/docs/user/dashboard/images/url_drilldown_pick_an_action.png
new file mode 100644
index 0000000000000..c99e931e3fbe1
Binary files /dev/null and b/docs/user/dashboard/images/url_drilldown_pick_an_action.png differ
diff --git a/docs/user/dashboard/images/url_drilldown_popup.png b/docs/user/dashboard/images/url_drilldown_popup.png
new file mode 100644
index 0000000000000..392edd16ea328
Binary files /dev/null and b/docs/user/dashboard/images/url_drilldown_popup.png differ
diff --git a/docs/user/dashboard/images/url_drilldown_trigger_picker.png b/docs/user/dashboard/images/url_drilldown_trigger_picker.png
new file mode 100644
index 0000000000000..2fe930f35dce8
Binary files /dev/null and b/docs/user/dashboard/images/url_drilldown_trigger_picker.png differ
diff --git a/docs/user/dashboard/images/url_drilldown_url_template.png b/docs/user/dashboard/images/url_drilldown_url_template.png
new file mode 100644
index 0000000000000..d8515afe66a80
Binary files /dev/null and b/docs/user/dashboard/images/url_drilldown_url_template.png differ
diff --git a/docs/user/dashboard/url-drilldown.asciidoc b/docs/user/dashboard/url-drilldown.asciidoc
new file mode 100644
index 0000000000000..16f82477756b7
--- /dev/null
+++ b/docs/user/dashboard/url-drilldown.asciidoc
@@ -0,0 +1,221 @@
+[[url-drilldown]]
+=== URL drilldown
+
+The URL drilldown allows you to navigate from a dashboard to an internal or external URL.
+The destination URL can be dynamic, depending on the dashboard context or user’s interaction with a visualization.
+
+For example, you might have a dashboard that shows data from a Github repository.
+You can create a drilldown that navigates from this dashboard to Github.
+
+[role="screenshot"]
+image:images/url_drilldown_go_to_github.gif[Drilldown on pie chart that navigates to Github]
+
+NOTE: URL drilldown is available with the https://www.elastic.co/subscriptions[Gold subscription] and higher.
+
+[float]
+[[try-it]]
+==== Try it: Create a URL drilldown
+
+This example shows how to create the "Show on Github" drilldown shown above.
+
+. Add the <> data set.
+. Open the *[Logs] Web traffic* dashboard. This isn’t data from Github, but it should work for demonstration purposes.
+. In the dashboard menu bar, click *Edit*.
+. In *[Logs] Visitors by OS*, open the panel menu, and then select *Create drilldown*.
+. Give the drilldown a name: *Show on Github*.
+. Select a drilldown action: *Go to URL*.
++
+[role="screenshot"]
+image:images/url_drilldown_pick_an_action.png[Action picker]
+. Enter a URL template:
++
+[source, bash]
+----
+https://github.com/elastic/kibana/issues?q=is:issue+is:open+{{event.value}}
+----
++
+This example URL navigates to {kib} issues on Github. `{{event.value}}` will be substituted with a value associated with a clicked pie slice. In _preview_ `{{event.value}}` is substituted with a <> value.
+[role="screenshot"]
+image:images/url_drilldown_url_template.png[URL template input]
+. Click *Create drilldown*.
+. Save the dashboard.
++
+If you don’t save the drilldown, and then navigate away, the drilldown is lost.
+
+. In *[Logs] Visitors by OS*, click any slice of the pie, and then select the drilldown *Show on Github*.
++
+[role="screenshot"]
+image:images/url_drilldown_popup.png[URL drilldown popup]
++
+You are navigated to the issue list in the {kib} repository. Verify that value from a pie slice you’ve clicked on is carried over to Github.
++
+[role="screenshot"]
+image:images/url_drilldown_github.png[Github]
+
+[float]
+[[trigger-picker]]
+==== Picking a trigger for a URL drilldown
+
+Some panels support multiple user interactions (called triggers) for which you can configure a URL drilldown. The list of supported variables in the URL template depends on the trigger you selected.
+In the preceding example, you configured a URL drilldown on a pie chart. The only trigger that pie chart supports is clicking on a pie slice, so you didn’t have to pick a trigger.
+
+However, the sample *[Logs] Unique Visitors vs. Average Bytes* chart supports both clicking on a data point and selecting a range. When you create a URL drilldown for this chart, you have the following choices:
+
+[role="screenshot"]
+image:images/url_drilldown_trigger_picker.png[Trigger picker: Single click and Range selection]
+
+Variables in the URL template differ per trigger.
+For example, *Single click* has `{{event.value}}` and *Range selection* has `{{event.from}}` and `{{event.to}}`.
+You can create multiple URL drilldowns per panel and attach them to different triggers.
+
+[float]
+[[templating]]
+==== URL templating language
+
+The URL template input uses Handlebars — a simple templating language. Handlebars templates look like regular text with embedded Handlebars expressions.
+
+[source, bash]
+----
+https://github.com/elastic/kibana/issues?q={{event.value}}
+----
+
+A Handlebars expression is a `{{`, some contents, followed by a `}}`. When the drilldown is executed, these expressions are replaced by values from the dashboard and interaction context.
+
+Refer to Handlebars https://handlebarsjs.com/guide/expressions.html#expressions[documentation] to learn about advanced use cases.
+
+[[helpers]]
+In addition to https://handlebarsjs.com/guide/builtin-helpers.html[built-in] Handlebars helpers, you can use the following custom helpers:
+
+
+|===
+|Helper |Use case
+
+|json
+a|Serialize variables in JSON format.
+
+Example:
+
+`{{json event}}` +
+`{{json event.key event.value}}` +
+`{{json filters=context.panel.filters}}`
+
+
+|rison
+a|Serialize variables in https://github.com/w33ble/rison-node[rison] format. Rison is a common format for {kib} apps for storing state in the URL.
+
+Example:
+
+`{{rison event}}` +
+`{{rison event.key event.value}}` +
+`{{rison filters=context.panel.filters}}`
+
+
+|date
+a|Format dates. Supports relative dates expressions (for example, "now-15d"). Refer to the https://momentjs.com/docs/#/displaying/format/[moment] docs for different formatting options.
+
+Example:
+
+`{{ date event.from “YYYY MM DD”}}` +
+`{{date “now-15”}}`
+|===
+
+
+[float]
+[[variables]]
+==== URL template variables
+
+The URL drilldown template has three sources for variables:
+
+* *Global* static variables that don’t change depending on the place where the URL drilldown is used or which user interaction executed the drilldown. For example: `{{kibanaUrl}}`.
+* *Context* variables that change depending on where the drilldown is created and used. These variables are extracted from a context of a panel on a dashboard. For example, `{{context.panel.filters}}` gives access to filters that applied to the current panel.
+* *Event* variables that depend on the trigger context. These variables are dynamically extracted from the interaction context when the drilldown is executed.
+
+[[values-in-preview]]
+A subtle but important difference between *context* and *event* variables is that *context* variables use real values in previews when creating a URL drilldown.
+For example, `{{context.panel.filters}}` are previewed with the current filters that applied to a panel.
+*Event* variables are extracted during drilldown execution from a user interaction with a panel (for example, from a pie slice that the user clicked on).
+
+Because there is no user interaction with a panel in preview, there is no interaction context to use in a preview.
+To work around this, {kib} provides a sample interaction that relies on a picked <>.
+So in a preview, you might notice that `{{event.value}}` is replaced with `{{event.value}}` instead of with a sample from your data.
+Such previews can help you make sure that the structure of your URL template is valid.
+However, to ensure that the configured URL drilldown works as expected with your data, you have to save the dashboard and test in the panel.
+
+You can access the full list of variables available for the current panel and selected trigger by clicking *Add variable* in the top-right corner of a URL template input.
+
+[float]
+[[variables-reference]]
+==== Variables reference
+
+
+|===
+|Source |Variable |Description
+
+|*Global*
+| kibanaUrl
+| {kib} base URL. Useful for creating URL drilldowns that navigate within {kib}.
+
+| *Context*
+| context.panel
+| Context provided by current dashboard panel.
+
+|
+| context.panel.id
+| ID of a panel.
+
+|
+| context.panel.title
+| Title of a panel.
+
+|
+| context.panel.filters
+| List of {kib} filters applied to a panel. +
+Tip: Use in combination with <> helper for
+internal {kib} navigations with carrying over current filters.
+
+|
+| context.panel.query.query
+| Current query string.
+
+|
+| context.panel.query.lang
+| Current query language.
+
+|
+| context.panel.timeRange.from +
+context.panel.timeRange.to
+| Current time picker values. +
+Tip: Use in combination with <> helper to format date.
+
+|
+| context.panel.timeRange.indexPatternId +
+context.panel.timeRange.indexPatternIds
+|Index pattern ids used by a panel.
+
+|
+| context.panel.savedObjectId
+| ID of saved object behind a panel.
+
+| *Single click*
+| event.value
+| Value behind clicked data point.
+
+|
+| event.key
+| Field name behind clicked data point
+
+|
+| event.negate
+| Boolean, indicating whether clicked data point resulted in negative filter.
+
+| *Range selection*
+| event.from +
+event.to
+| `from` and `to` values of selected range. Depending on your data, could be either a date or number. +
+Tip: Consider using <> helper for date formatting.
+
+|
+| event.key
+| Aggregation field behind the selected range, if available.
+
+|===
diff --git a/docs/user/reporting/reporting-troubleshooting.asciidoc b/docs/user/reporting/reporting-troubleshooting.asciidoc
index dc4ffdfebdae9..82f0aa7ca0f19 100644
--- a/docs/user/reporting/reporting-troubleshooting.asciidoc
+++ b/docs/user/reporting/reporting-troubleshooting.asciidoc
@@ -7,6 +7,7 @@
Having trouble? Here are solutions to common problems you might encounter while using Reporting.
+* <>
* <>
* <>
* <>
@@ -15,6 +16,11 @@ Having trouble? Here are solutions to common problems you might encounter while
* <>
* <>
+[float]
+[[reporting-diagnostics]]
+=== Reporting Diagnostics
+Reporting comes with a built-in utility to try to automatically find common issues. When Kibana is running, navigate to the Report Listing page, and click the "Run reporting diagnostics..." button. This will open up a diagnostic tool that checks various parts of the Kibana deployment to come up with any relevant recommendations.
+
[float]
[[reporting-troubleshooting-system-dependencies]]
=== System dependencies
diff --git a/kibana.d.ts b/kibana.d.ts
index d64752abd8b60..517bda374af9d 100644
--- a/kibana.d.ts
+++ b/kibana.d.ts
@@ -39,8 +39,6 @@ export namespace Legacy {
export type KibanaConfig = LegacyKibanaServer.KibanaConfig;
export type Request = LegacyKibanaServer.Request;
export type ResponseToolkit = LegacyKibanaServer.ResponseToolkit;
- export type SavedObjectsClient = LegacyKibanaServer.SavedObjectsClient;
- export type SavedObjectsService = LegacyKibanaServer.SavedObjectsLegacyService;
export type Server = LegacyKibanaServer.Server;
export type InitPluginFunction = LegacyKibanaPluginSpec.InitPluginFunction;
diff --git a/package.json b/package.json
index ff487510f7a32..7468a49d56959 100644
--- a/package.json
+++ b/package.json
@@ -63,7 +63,7 @@
"uiFramework:createComponent": "cd packages/kbn-ui-framework && yarn createComponent",
"uiFramework:documentComponent": "cd packages/kbn-ui-framework && yarn documentComponent",
"kbn:watch": "node scripts/kibana --dev --logging.json=false",
- "build:types": "tsc --p tsconfig.types.json",
+ "build:types": "rm -rf ./target/types && tsc --p tsconfig.types.json",
"docs:acceptApiChanges": "node --max-old-space-size=6144 scripts/check_published_api_changes.js --accept",
"kbn:bootstrap": "node scripts/build_ts_refs && node scripts/register_git_hook",
"spec_to_console": "node scripts/spec_to_console",
@@ -231,7 +231,7 @@
"@babel/parser": "^7.11.2",
"@babel/types": "^7.11.0",
"@elastic/apm-rum": "^5.5.0",
- "@elastic/charts": "21.0.1",
+ "@elastic/charts": "21.1.2",
"@elastic/ems-client": "7.9.3",
"@elastic/eslint-config-kibana": "0.15.0",
"@elastic/eslint-plugin-eui": "0.0.2",
diff --git a/packages/kbn-config-schema/package.json b/packages/kbn-config-schema/package.json
index 10b1741d98441..9abe7f31dd060 100644
--- a/packages/kbn-config-schema/package.json
+++ b/packages/kbn-config-schema/package.json
@@ -11,7 +11,7 @@
},
"devDependencies": {
"typescript": "4.0.2",
- "tsd": "^0.7.4"
+ "tsd": "^0.13.1"
},
"peerDependencies": {
"lodash": "^4.17.15",
diff --git a/packages/kbn-ui-framework/src/components/local_nav/_local_search.scss b/packages/kbn-ui-framework/src/components/local_nav/_local_search.scss
index 130807790e987..740ae664c7f5b 100644
--- a/packages/kbn-ui-framework/src/components/local_nav/_local_search.scss
+++ b/packages/kbn-ui-framework/src/components/local_nav/_local_search.scss
@@ -26,13 +26,6 @@
border-radius: 0;
border-left-width: 0;
}
-
-.kuiLocalSearchAssistedInput {
- display: flex;
- flex: 1 1 100%;
- position: relative;
-}
-
/**
* 1. em used for right padding so documentation link and query string
* won't overlap if the user increases their default browser font size
diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json
index 4b2e88d155245..bbe7b1bc2e8da 100644
--- a/packages/kbn-ui-shared-deps/package.json
+++ b/packages/kbn-ui-shared-deps/package.json
@@ -9,7 +9,7 @@
"kbn:watch": "node scripts/build --dev --watch"
},
"dependencies": {
- "@elastic/charts": "21.0.1",
+ "@elastic/charts": "21.1.2",
"@elastic/eui": "28.2.0",
"@elastic/numeral": "^2.5.0",
"@kbn/i18n": "1.0.0",
diff --git a/packages/kbn-ui-shared-deps/webpack.config.js b/packages/kbn-ui-shared-deps/webpack.config.js
index c81da4689052a..fa80dfdeef20f 100644
--- a/packages/kbn-ui-shared-deps/webpack.config.js
+++ b/packages/kbn-ui-shared-deps/webpack.config.js
@@ -32,22 +32,10 @@ exports.getWebpackConfig = ({ dev = false } = {}) => ({
mode: dev ? 'development' : 'production',
entry: {
'kbn-ui-shared-deps': './entry.js',
- 'kbn-ui-shared-deps.v7.dark': [
- '@elastic/eui/dist/eui_theme_dark.css',
- '@elastic/charts/dist/theme_only_dark.css',
- ],
- 'kbn-ui-shared-deps.v7.light': [
- '@elastic/eui/dist/eui_theme_light.css',
- '@elastic/charts/dist/theme_only_light.css',
- ],
- 'kbn-ui-shared-deps.v8.dark': [
- '@elastic/eui/dist/eui_theme_amsterdam_dark.css',
- '@elastic/charts/dist/theme_only_dark.css',
- ],
- 'kbn-ui-shared-deps.v8.light': [
- '@elastic/eui/dist/eui_theme_amsterdam_light.css',
- '@elastic/charts/dist/theme_only_light.css',
- ],
+ 'kbn-ui-shared-deps.v7.dark': ['@elastic/eui/dist/eui_theme_dark.css'],
+ 'kbn-ui-shared-deps.v7.light': ['@elastic/eui/dist/eui_theme_light.css'],
+ 'kbn-ui-shared-deps.v8.dark': ['@elastic/eui/dist/eui_theme_amsterdam_dark.css'],
+ 'kbn-ui-shared-deps.v8.light': ['@elastic/eui/dist/eui_theme_amsterdam_light.css'],
},
context: __dirname,
devtool: dev ? '#cheap-source-map' : false,
diff --git a/packages/kbn-utility-types/package.json b/packages/kbn-utility-types/package.json
index a999eb41eb781..d1d7a1c0397cf 100644
--- a/packages/kbn-utility-types/package.json
+++ b/packages/kbn-utility-types/package.json
@@ -16,7 +16,7 @@
"utility-types": "^3.10.0"
},
"devDependencies": {
- "del-cli": "^3.0.0",
- "tsd": "^0.7.4"
+ "del-cli": "^3.0.1",
+ "tsd": "^0.13.1"
}
}
diff --git a/packages/kbn-utility-types/test-d/union_to_intersection.ts b/packages/kbn-utility-types/test-d/union_to_intersection.ts
index ba385268475e7..8b49436bdd953 100644
--- a/packages/kbn-utility-types/test-d/union_to_intersection.ts
+++ b/packages/kbn-utility-types/test-d/union_to_intersection.ts
@@ -17,12 +17,12 @@
* under the License.
*/
-import { expectType } from 'tsd';
+import { expectAssignable } from 'tsd';
import { UnionToIntersection } from '../index';
type INTERSECTED = UnionToIntersection<{ foo: 'bar' } | { baz: 'qux' }>;
-expectType({
+expectAssignable({
foo: 'bar',
baz: 'qux',
});
diff --git a/packages/kbn-utility-types/test-d/unwrap_observable.ts b/packages/kbn-utility-types/test-d/unwrap_observable.ts
index af4fa9abf6ec7..e9791cfd36beb 100644
--- a/packages/kbn-utility-types/test-d/unwrap_observable.ts
+++ b/packages/kbn-utility-types/test-d/unwrap_observable.ts
@@ -17,9 +17,9 @@
* under the License.
*/
-import { expectType } from 'tsd';
+import { expectAssignable } from 'tsd';
import { UnwrapObservable, ObservableLike } from '../index';
type STRING = UnwrapObservable>;
-expectType('adf');
+expectAssignable('adf');
diff --git a/packages/kbn-utility-types/test-d/unwrap_promise.ts b/packages/kbn-utility-types/test-d/unwrap_promise.ts
index 9c4b1bc76b805..b61b24e4b3f15 100644
--- a/packages/kbn-utility-types/test-d/unwrap_promise.ts
+++ b/packages/kbn-utility-types/test-d/unwrap_promise.ts
@@ -17,11 +17,11 @@
* under the License.
*/
-import { expectType } from 'tsd';
+import { expectAssignable } from 'tsd';
import { UnwrapPromise } from '../index';
type STRING = UnwrapPromise>;
type TUPLE = UnwrapPromise>;
-expectType('adf');
-expectType([1, 2]);
+expectAssignable('adf');
+expectAssignable([1, 2]);
diff --git a/packages/kbn-utility-types/test-d/values.ts b/packages/kbn-utility-types/test-d/values.ts
index 9e50cfebde1db..69bee9c3c9655 100644
--- a/packages/kbn-utility-types/test-d/values.ts
+++ b/packages/kbn-utility-types/test-d/values.ts
@@ -17,22 +17,22 @@
* under the License.
*/
-import { expectType } from 'tsd';
+import { expectAssignable } from 'tsd';
import { Values } from '../index';
// Arrays
type STRING = Values;
type ASDF_FOO = Values>;
-expectType('adf');
-expectType('asdf');
-expectType('foo');
+expectAssignable('adf');
+expectAssignable('asdf');
+expectAssignable('foo');
// Objects
type STRING2 = Values>;
type FOO = Values>;
type BAR = Values<{ foo: 'bar' }>;
-expectType('adf');
-expectType('foo');
-expectType('bar');
+expectAssignable('adf');
+expectAssignable('foo');
+expectAssignable('bar');
diff --git a/rfcs/text/0010_service_status.md b/rfcs/text/0010_service_status.md
index ded594930a367..76195c4f1ab89 100644
--- a/rfcs/text/0010_service_status.md
+++ b/rfcs/text/0010_service_status.md
@@ -137,7 +137,7 @@ interface StatusSetup {
* Current status for all dependencies of the current plugin.
* Each key of the `Record` is a plugin id.
*/
- plugins$: Observable>;
+ dependencies$: Observable>;
/**
* The status of this plugin as derived from its dependencies.
diff --git a/src/legacy/utils/binder.ts b/src/cli/cluster/binder.ts
similarity index 100%
rename from src/legacy/utils/binder.ts
rename to src/cli/cluster/binder.ts
diff --git a/src/legacy/utils/binder_for.ts b/src/cli/cluster/binder_for.ts
similarity index 100%
rename from src/legacy/utils/binder_for.ts
rename to src/cli/cluster/binder_for.ts
diff --git a/src/cli/cluster/worker.ts b/src/cli/cluster/worker.ts
index 097a549187429..c8a8a067d30bf 100644
--- a/src/cli/cluster/worker.ts
+++ b/src/cli/cluster/worker.ts
@@ -21,7 +21,7 @@ import _ from 'lodash';
import cluster from 'cluster';
import { EventEmitter } from 'events';
-import { BinderFor } from '../../legacy/utils/binder_for';
+import { BinderFor } from './binder_for';
import { fromRoot } from '../../core/server/utils';
const cliPath = fromRoot('src/cli');
diff --git a/src/cli_keystore/add.js b/src/cli_keystore/add.js
index 462259ec942dd..232392f34c63b 100644
--- a/src/cli_keystore/add.js
+++ b/src/cli_keystore/add.js
@@ -18,7 +18,7 @@
*/
import { Logger } from '../cli_plugin/lib/logger';
-import { confirm, question } from '../legacy/server/utils';
+import { confirm, question } from './utils';
import { createPromiseFromStreams, createConcatStream } from '../core/server/utils';
/**
diff --git a/src/cli_keystore/add.test.js b/src/cli_keystore/add.test.js
index b5d5009667eb4..f1adee8879bc2 100644
--- a/src/cli_keystore/add.test.js
+++ b/src/cli_keystore/add.test.js
@@ -42,7 +42,7 @@ import { PassThrough } from 'stream';
import { Keystore } from '../legacy/server/keystore';
import { add } from './add';
import { Logger } from '../cli_plugin/lib/logger';
-import * as prompt from '../legacy/server/utils/prompt';
+import * as prompt from './utils/prompt';
describe('Kibana keystore', () => {
describe('add', () => {
diff --git a/src/cli_keystore/create.js b/src/cli_keystore/create.js
index 8be1eb36882f1..55fe2c151dec0 100644
--- a/src/cli_keystore/create.js
+++ b/src/cli_keystore/create.js
@@ -18,7 +18,7 @@
*/
import { Logger } from '../cli_plugin/lib/logger';
-import { confirm } from '../legacy/server/utils';
+import { confirm } from './utils';
export async function create(keystore, command, options) {
const logger = new Logger(options);
diff --git a/src/cli_keystore/create.test.js b/src/cli_keystore/create.test.js
index f48b3775ddfff..cb85475eab1cb 100644
--- a/src/cli_keystore/create.test.js
+++ b/src/cli_keystore/create.test.js
@@ -41,7 +41,7 @@ import sinon from 'sinon';
import { Keystore } from '../legacy/server/keystore';
import { create } from './create';
import { Logger } from '../cli_plugin/lib/logger';
-import * as prompt from '../legacy/server/utils/prompt';
+import * as prompt from './utils/prompt';
describe('Kibana keystore', () => {
describe('create', () => {
diff --git a/src/legacy/server/utils/index.js b/src/cli_keystore/utils/index.js
similarity index 100%
rename from src/legacy/server/utils/index.js
rename to src/cli_keystore/utils/index.js
diff --git a/src/legacy/server/utils/prompt.js b/src/cli_keystore/utils/prompt.js
similarity index 100%
rename from src/legacy/server/utils/prompt.js
rename to src/cli_keystore/utils/prompt.js
diff --git a/src/legacy/server/utils/prompt.test.js b/src/cli_keystore/utils/prompt.test.js
similarity index 100%
rename from src/legacy/server/utils/prompt.test.js
rename to src/cli_keystore/utils/prompt.test.js
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 3a444a4448467..5a9f982e106a7 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
@@ -57,6 +57,7 @@ const mockedResponse: StatusResponse = {
],
},
metrics: {
+ collected_at: new Date('2020-01-01 01:00:00'),
collection_interval_in_millis: 1000,
os: {
platform: 'darwin' as const,
diff --git a/src/core/public/core_app/styles/_globals_v7dark.scss b/src/core/public/core_app/styles/_globals_v7dark.scss
index 8ac841aab8469..9a4a965d63a38 100644
--- a/src/core/public/core_app/styles/_globals_v7dark.scss
+++ b/src/core/public/core_app/styles/_globals_v7dark.scss
@@ -3,9 +3,6 @@
// prepended to all .scss imports (from JS, when v7dark theme selected)
@import '@elastic/eui/src/themes/eui/eui_colors_dark';
-
-@import '@elastic/eui/src/global_styling/functions/index';
-@import '@elastic/eui/src/global_styling/variables/index';
-@import '@elastic/eui/src/global_styling/mixins/index';
+@import '@elastic/eui/src/themes/eui/eui_globals';
@import './mixins';
diff --git a/src/core/public/core_app/styles/_globals_v7light.scss b/src/core/public/core_app/styles/_globals_v7light.scss
index 701bbdfe03662..ddb4b5b31fa1f 100644
--- a/src/core/public/core_app/styles/_globals_v7light.scss
+++ b/src/core/public/core_app/styles/_globals_v7light.scss
@@ -3,9 +3,6 @@
// prepended to all .scss imports (from JS, when v7light theme selected)
@import '@elastic/eui/src/themes/eui/eui_colors_light';
-
-@import '@elastic/eui/src/global_styling/functions/index';
-@import '@elastic/eui/src/global_styling/variables/index';
-@import '@elastic/eui/src/global_styling/mixins/index';
+@import '@elastic/eui/src/themes/eui/eui_globals';
@import './mixins';
diff --git a/src/core/public/core_app/styles/_globals_v8dark.scss b/src/core/public/core_app/styles/_globals_v8dark.scss
index 972365e9e9d0e..9ad9108f350ff 100644
--- a/src/core/public/core_app/styles/_globals_v8dark.scss
+++ b/src/core/public/core_app/styles/_globals_v8dark.scss
@@ -3,14 +3,6 @@
// prepended to all .scss imports (from JS, when v8dark theme selected)
@import '@elastic/eui/src/themes/eui-amsterdam/eui_amsterdam_colors_dark';
-
-@import '@elastic/eui/src/global_styling/functions/index';
-@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/functions/index';
-
-@import '@elastic/eui/src/global_styling/variables/index';
-@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/variables/index';
-
-@import '@elastic/eui/src/global_styling/mixins/index';
-@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/mixins/index';
+@import '@elastic/eui/src/themes/eui-amsterdam/eui_amsterdam_globals';
@import './mixins';
diff --git a/src/core/public/core_app/styles/_globals_v8light.scss b/src/core/public/core_app/styles/_globals_v8light.scss
index dc99f4d45082e..a6b2cb84c2062 100644
--- a/src/core/public/core_app/styles/_globals_v8light.scss
+++ b/src/core/public/core_app/styles/_globals_v8light.scss
@@ -3,14 +3,6 @@
// prepended to all .scss imports (from JS, when v8light theme selected)
@import '@elastic/eui/src/themes/eui-amsterdam/eui_amsterdam_colors_light';
-
-@import '@elastic/eui/src/global_styling/functions/index';
-@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/functions/index';
-
-@import '@elastic/eui/src/global_styling/variables/index';
-@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/variables/index';
-
-@import '@elastic/eui/src/global_styling/mixins/index';
-@import '@elastic/eui/src/themes/eui-amsterdam/global_styling/mixins/index';
+@import '@elastic/eui/src/themes/eui-amsterdam/eui_amsterdam_globals';
@import './mixins';
diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts
index fc753517fd940..95ac8bba57049 100644
--- a/src/core/public/doc_links/doc_links_service.ts
+++ b/src/core/public/doc_links/doc_links_service.ts
@@ -129,7 +129,7 @@ export class DocLinksService {
},
visualize: {
guide: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/visualize.html`,
- timelionDeprecation: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/timelion.html#timelion-deprecation`,
+ timelionDeprecation: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/dashboard.html#timelion-deprecation`,
},
},
});
diff --git a/src/core/public/styles/_base.scss b/src/core/public/styles/_base.scss
index 9b06b526fc7dd..427c6b7735435 100644
--- a/src/core/public/styles/_base.scss
+++ b/src/core/public/styles/_base.scss
@@ -1,4 +1,10 @@
+// Charts themes available app-wide
+@import '@elastic/charts/dist/theme';
+@import '@elastic/eui/src/themes/charts/theme';
+
+// Grab some nav-specific EUI vars
@import '@elastic/eui/src/components/collapsible_nav/variables';
+
// Application Layout
// chrome-context
diff --git a/src/core/server/config/deprecation/core_deprecations.ts b/src/core/server/config/deprecation/core_deprecations.ts
index e4e881ab24372..2b8b8e383da24 100644
--- a/src/core/server/config/deprecation/core_deprecations.ts
+++ b/src/core/server/config/deprecation/core_deprecations.ts
@@ -113,7 +113,7 @@ const mapManifestServiceUrlDeprecation: ConfigDeprecation = (settings, fromPath,
return settings;
};
-export const coreDeprecationProvider: ConfigDeprecationProvider = ({ unusedFromRoot }) => [
+export const coreDeprecationProvider: ConfigDeprecationProvider = ({ rename, unusedFromRoot }) => [
unusedFromRoot('savedObjects.indexCheckTimeout'),
unusedFromRoot('server.xsrf.token'),
unusedFromRoot('maps.manifestServiceUrl'),
@@ -136,6 +136,8 @@ export const coreDeprecationProvider: ConfigDeprecationProvider = ({ unusedFromR
unusedFromRoot('optimize.workers'),
unusedFromRoot('optimize.profile'),
unusedFromRoot('optimize.validateSyntaxOfNodeModules'),
+ rename('cpu.cgroup.path.override', 'ops.cGroupOverrides.cpuPath'),
+ rename('cpuacct.cgroup.path.override', 'ops.cGroupOverrides.cpuAcctPath'),
configPathDeprecation,
dataPathDeprecation,
rewriteBasePathDeprecation,
diff --git a/src/core/server/index.ts b/src/core/server/index.ts
index c17d3d7546779..d127471348d9f 100644
--- a/src/core/server/index.ts
+++ b/src/core/server/index.ts
@@ -266,9 +266,7 @@ export {
SavedObjectUnsanitizedDoc,
SavedObjectsRepositoryFactory,
SavedObjectsResolveImportErrorsOptions,
- SavedObjectsSchema,
SavedObjectsSerializer,
- SavedObjectsLegacyService,
SavedObjectsUpdateOptions,
SavedObjectsUpdateResponse,
SavedObjectsAddToNamespacesOptions,
@@ -295,6 +293,7 @@ export {
SavedObjectsTypeManagementDefinition,
SavedObjectMigrationMap,
SavedObjectMigrationFn,
+ SavedObjectsUtils,
exportSavedObjectsToStream,
importSavedObjectsFromStream,
resolveSavedObjectsImportErrors,
diff --git a/src/core/server/legacy/legacy_service.mock.ts b/src/core/server/legacy/legacy_service.mock.ts
index 26ec52185a5d8..c27f5be04d965 100644
--- a/src/core/server/legacy/legacy_service.mock.ts
+++ b/src/core/server/legacy/legacy_service.mock.ts
@@ -24,13 +24,7 @@ type LegacyServiceMock = jest.Mocked & { legacyId
const createDiscoverPluginsMock = (): LegacyServiceDiscoverPlugins => ({
pluginSpecs: [],
- uiExports: {
- savedObjectSchemas: {},
- savedObjectMappings: [],
- savedObjectMigrations: {},
- savedObjectValidations: {},
- savedObjectsManagement: {},
- },
+ uiExports: {},
navLinks: [],
pluginExtendedConfig: {
get: jest.fn(),
diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts
index 880011d2e1923..6e6d5cfc24340 100644
--- a/src/core/server/legacy/legacy_service.ts
+++ b/src/core/server/legacy/legacy_service.ts
@@ -264,6 +264,7 @@ export class LegacyService implements CoreService {
getTypeRegistry: startDeps.core.savedObjects.getTypeRegistry,
},
metrics: {
+ collectionInterval: startDeps.core.metrics.collectionInterval,
getOpsMetrics$: startDeps.core.metrics.getOpsMetrics$,
},
uiSettings: { asScopedToClient: startDeps.core.uiSettings.asScopedToClient },
@@ -310,6 +311,17 @@ export class LegacyService implements CoreService {
status: {
core$: setupDeps.core.status.core$,
overall$: setupDeps.core.status.overall$,
+ set: () => {
+ throw new Error(`core.status.set is unsupported in legacy`);
+ },
+ // @ts-expect-error
+ get dependencies$() {
+ throw new Error(`core.status.dependencies$ is unsupported in legacy`);
+ },
+ // @ts-expect-error
+ get derivedStatus$() {
+ throw new Error(`core.status.derivedStatus$ is unsupported in legacy`);
+ },
},
uiSettings: {
register: setupDeps.core.uiSettings.register,
@@ -341,11 +353,9 @@ export class LegacyService implements CoreService {
registerStaticDir: setupDeps.core.http.registerStaticDir,
},
hapiServer: setupDeps.core.http.server,
- kibanaMigrator: startDeps.core.savedObjects.migrator,
uiPlugins: setupDeps.uiPlugins,
elasticsearch: setupDeps.core.elasticsearch,
rendering: setupDeps.core.rendering,
- savedObjectsClientProvider: startDeps.core.savedObjects.clientProvider,
legacy: this.legacyInternals,
},
logger: this.coreContext.logger,
diff --git a/src/core/server/legacy/types.ts b/src/core/server/legacy/types.ts
index cf08689a6d0d4..1105308fd44cf 100644
--- a/src/core/server/legacy/types.ts
+++ b/src/core/server/legacy/types.ts
@@ -24,7 +24,6 @@ import { KibanaRequest, LegacyRequest } from '../http';
import { InternalCoreSetup, InternalCoreStart } from '../internal_types';
import { PluginsServiceSetup, PluginsServiceStart, UiPlugins } from '../plugins';
import { InternalRenderingServiceSetup } from '../rendering';
-import { SavedObjectsLegacyUiExports } from '../types';
/**
* @internal
@@ -128,13 +127,13 @@ export type LegacyNavLink = Omit;
unknown?: [{ pluginSpec: LegacyPluginSpec; type: unknown }];
-};
+}
/**
* @public
diff --git a/src/core/server/metrics/collectors/cgroup.test.ts b/src/core/server/metrics/collectors/cgroup.test.ts
new file mode 100644
index 0000000000000..39f917b9f0ba1
--- /dev/null
+++ b/src/core/server/metrics/collectors/cgroup.test.ts
@@ -0,0 +1,115 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import mockFs from 'mock-fs';
+import { OsCgroupMetricsCollector } from './cgroup';
+
+describe('OsCgroupMetricsCollector', () => {
+ afterEach(() => mockFs.restore());
+
+ it('returns empty object when no cgroup file present', async () => {
+ mockFs({
+ '/proc/self': {
+ /** empty directory */
+ },
+ });
+
+ const collector = new OsCgroupMetricsCollector({});
+ expect(await collector.collect()).toEqual({});
+ });
+
+ it('collects default cgroup data', async () => {
+ mockFs({
+ '/proc/self/cgroup': `
+123:memory:/groupname
+123:cpu:/groupname
+123:cpuacct:/groupname
+ `,
+ '/sys/fs/cgroup/cpuacct/groupname/cpuacct.usage': '111',
+ '/sys/fs/cgroup/cpu/groupname/cpu.cfs_period_us': '222',
+ '/sys/fs/cgroup/cpu/groupname/cpu.cfs_quota_us': '333',
+ '/sys/fs/cgroup/cpu/groupname/cpu.stat': `
+nr_periods 444
+nr_throttled 555
+throttled_time 666
+ `,
+ });
+
+ const collector = new OsCgroupMetricsCollector({});
+ expect(await collector.collect()).toMatchInlineSnapshot(`
+ Object {
+ "cpu": Object {
+ "cfs_period_micros": 222,
+ "cfs_quota_micros": 333,
+ "control_group": "/groupname",
+ "stat": Object {
+ "number_of_elapsed_periods": 444,
+ "number_of_times_throttled": 555,
+ "time_throttled_nanos": 666,
+ },
+ },
+ "cpuacct": Object {
+ "control_group": "/groupname",
+ "usage_nanos": 111,
+ },
+ }
+ `);
+ });
+
+ it('collects override cgroup data', async () => {
+ mockFs({
+ '/proc/self/cgroup': `
+123:memory:/groupname
+123:cpu:/groupname
+123:cpuacct:/groupname
+ `,
+ '/sys/fs/cgroup/cpuacct/xxcustomcpuacctxx/cpuacct.usage': '111',
+ '/sys/fs/cgroup/cpu/xxcustomcpuxx/cpu.cfs_period_us': '222',
+ '/sys/fs/cgroup/cpu/xxcustomcpuxx/cpu.cfs_quota_us': '333',
+ '/sys/fs/cgroup/cpu/xxcustomcpuxx/cpu.stat': `
+nr_periods 444
+nr_throttled 555
+throttled_time 666
+ `,
+ });
+
+ const collector = new OsCgroupMetricsCollector({
+ cpuAcctPath: 'xxcustomcpuacctxx',
+ cpuPath: 'xxcustomcpuxx',
+ });
+ expect(await collector.collect()).toMatchInlineSnapshot(`
+ Object {
+ "cpu": Object {
+ "cfs_period_micros": 222,
+ "cfs_quota_micros": 333,
+ "control_group": "xxcustomcpuxx",
+ "stat": Object {
+ "number_of_elapsed_periods": 444,
+ "number_of_times_throttled": 555,
+ "time_throttled_nanos": 666,
+ },
+ },
+ "cpuacct": Object {
+ "control_group": "xxcustomcpuacctxx",
+ "usage_nanos": 111,
+ },
+ }
+ `);
+ });
+});
diff --git a/src/core/server/metrics/collectors/cgroup.ts b/src/core/server/metrics/collectors/cgroup.ts
new file mode 100644
index 0000000000000..867ea44dff1ae
--- /dev/null
+++ b/src/core/server/metrics/collectors/cgroup.ts
@@ -0,0 +1,194 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import fs from 'fs';
+import { join as joinPath } from 'path';
+import { MetricsCollector, OpsOsMetrics } from './types';
+
+type OsCgroupMetrics = Pick;
+
+interface OsCgroupMetricsCollectorOptions {
+ cpuPath?: string;
+ cpuAcctPath?: string;
+}
+
+export class OsCgroupMetricsCollector implements MetricsCollector {
+ /** Used to prevent unnecessary file reads on systems not using cgroups. */
+ private noCgroupPresent = false;
+ private cpuPath?: string;
+ private cpuAcctPath?: string;
+
+ constructor(private readonly options: OsCgroupMetricsCollectorOptions) {}
+
+ public async collect(): Promise {
+ try {
+ await this.initializePaths();
+ if (this.noCgroupPresent || !this.cpuAcctPath || !this.cpuPath) {
+ return {};
+ }
+
+ const [cpuAcctUsage, cpuFsPeriod, cpuFsQuota, cpuStat] = await Promise.all([
+ readCPUAcctUsage(this.cpuAcctPath),
+ readCPUFsPeriod(this.cpuPath),
+ readCPUFsQuota(this.cpuPath),
+ readCPUStat(this.cpuPath),
+ ]);
+
+ return {
+ cpuacct: {
+ control_group: this.cpuAcctPath,
+ usage_nanos: cpuAcctUsage,
+ },
+
+ cpu: {
+ control_group: this.cpuPath,
+ cfs_period_micros: cpuFsPeriod,
+ cfs_quota_micros: cpuFsQuota,
+ stat: cpuStat,
+ },
+ };
+ } catch (err) {
+ if (err.code === 'ENOENT') {
+ this.noCgroupPresent = true;
+ return {};
+ } else {
+ throw err;
+ }
+ }
+ }
+
+ public reset() {}
+
+ private async initializePaths() {
+ // Perform this setup lazily on the first collect call and then memoize the results.
+ // Makes the assumption this data doesn't change while the process is running.
+ if (this.cpuPath && this.cpuAcctPath) {
+ return;
+ }
+
+ // Only read the file if both options are undefined.
+ if (!this.options.cpuPath || !this.options.cpuAcctPath) {
+ const cgroups = await readControlGroups();
+ this.cpuPath = this.options.cpuPath || cgroups[GROUP_CPU];
+ this.cpuAcctPath = this.options.cpuAcctPath || cgroups[GROUP_CPUACCT];
+ } else {
+ this.cpuPath = this.options.cpuPath;
+ this.cpuAcctPath = this.options.cpuAcctPath;
+ }
+
+ // prevents undefined cgroup paths
+ if (!this.cpuPath || !this.cpuAcctPath) {
+ this.noCgroupPresent = true;
+ }
+ }
+}
+
+const CONTROL_GROUP_RE = new RegExp('\\d+:([^:]+):(/.*)');
+const CONTROLLER_SEPARATOR_RE = ',';
+
+const PROC_SELF_CGROUP_FILE = '/proc/self/cgroup';
+const PROC_CGROUP_CPU_DIR = '/sys/fs/cgroup/cpu';
+const PROC_CGROUP_CPUACCT_DIR = '/sys/fs/cgroup/cpuacct';
+
+const GROUP_CPUACCT = 'cpuacct';
+const CPUACCT_USAGE_FILE = 'cpuacct.usage';
+
+const GROUP_CPU = 'cpu';
+const CPU_FS_PERIOD_US_FILE = 'cpu.cfs_period_us';
+const CPU_FS_QUOTA_US_FILE = 'cpu.cfs_quota_us';
+const CPU_STATS_FILE = 'cpu.stat';
+
+async function readControlGroups() {
+ const data = await fs.promises.readFile(PROC_SELF_CGROUP_FILE);
+
+ return data
+ .toString()
+ .split(/\n/)
+ .reduce((acc, line) => {
+ const matches = line.match(CONTROL_GROUP_RE);
+
+ if (matches !== null) {
+ const controllers = matches[1].split(CONTROLLER_SEPARATOR_RE);
+ controllers.forEach((controller) => {
+ acc[controller] = matches[2];
+ });
+ }
+
+ return acc;
+ }, {} as Record);
+}
+
+async function fileContentsToInteger(path: string) {
+ const data = await fs.promises.readFile(path);
+ return parseInt(data.toString(), 10);
+}
+
+function readCPUAcctUsage(controlGroup: string) {
+ return fileContentsToInteger(joinPath(PROC_CGROUP_CPUACCT_DIR, controlGroup, CPUACCT_USAGE_FILE));
+}
+
+function readCPUFsPeriod(controlGroup: string) {
+ return fileContentsToInteger(joinPath(PROC_CGROUP_CPU_DIR, controlGroup, CPU_FS_PERIOD_US_FILE));
+}
+
+function readCPUFsQuota(controlGroup: string) {
+ return fileContentsToInteger(joinPath(PROC_CGROUP_CPU_DIR, controlGroup, CPU_FS_QUOTA_US_FILE));
+}
+
+async function readCPUStat(controlGroup: string) {
+ const stat = {
+ number_of_elapsed_periods: -1,
+ number_of_times_throttled: -1,
+ time_throttled_nanos: -1,
+ };
+
+ try {
+ const data = await fs.promises.readFile(
+ joinPath(PROC_CGROUP_CPU_DIR, controlGroup, CPU_STATS_FILE)
+ );
+ return data
+ .toString()
+ .split(/\n/)
+ .reduce((acc, line) => {
+ const fields = line.split(/\s+/);
+
+ switch (fields[0]) {
+ case 'nr_periods':
+ acc.number_of_elapsed_periods = parseInt(fields[1], 10);
+ break;
+
+ case 'nr_throttled':
+ acc.number_of_times_throttled = parseInt(fields[1], 10);
+ break;
+
+ case 'throttled_time':
+ acc.time_throttled_nanos = parseInt(fields[1], 10);
+ break;
+ }
+
+ return acc;
+ }, stat);
+ } catch (err) {
+ if (err.code === 'ENOENT') {
+ return stat;
+ }
+
+ throw err;
+ }
+}
diff --git a/src/core/server/metrics/collectors/collector.mock.ts b/src/core/server/metrics/collectors/collector.mock.ts
new file mode 100644
index 0000000000000..2a942e1fafe63
--- /dev/null
+++ b/src/core/server/metrics/collectors/collector.mock.ts
@@ -0,0 +1,33 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { MetricsCollector } from './types';
+
+const createCollector = (collectReturnValue: any = {}): jest.Mocked> => {
+ const collector: jest.Mocked> = {
+ collect: jest.fn().mockResolvedValue(collectReturnValue),
+ reset: jest.fn(),
+ };
+
+ return collector;
+};
+
+export const metricsCollectorMock = {
+ create: createCollector,
+};
diff --git a/src/core/server/metrics/collectors/index.ts b/src/core/server/metrics/collectors/index.ts
index f58ab02e63881..4540cb79be74b 100644
--- a/src/core/server/metrics/collectors/index.ts
+++ b/src/core/server/metrics/collectors/index.ts
@@ -18,6 +18,6 @@
*/
export { OpsProcessMetrics, OpsOsMetrics, OpsServerMetrics, MetricsCollector } from './types';
-export { OsMetricsCollector } from './os';
+export { OsMetricsCollector, OpsMetricsCollectorOptions } from './os';
export { ProcessMetricsCollector } from './process';
export { ServerMetricsCollector } from './server';
diff --git a/src/core/server/saved_objects/schema/index.ts b/src/core/server/metrics/collectors/os.test.mocks.ts
similarity index 77%
rename from src/core/server/saved_objects/schema/index.ts
rename to src/core/server/metrics/collectors/os.test.mocks.ts
index d30bbb8d34cd3..ee02b8c802151 100644
--- a/src/core/server/saved_objects/schema/index.ts
+++ b/src/core/server/metrics/collectors/os.test.mocks.ts
@@ -17,4 +17,9 @@
* under the License.
*/
-export { SavedObjectsSchema, SavedObjectsSchemaDefinition } from './schema';
+import { metricsCollectorMock } from './collector.mock';
+
+export const cgroupCollectorMock = metricsCollectorMock.create();
+jest.doMock('./cgroup', () => ({
+ OsCgroupMetricsCollector: jest.fn(() => cgroupCollectorMock),
+}));
diff --git a/src/core/server/metrics/collectors/os.test.ts b/src/core/server/metrics/collectors/os.test.ts
index 7d5a6da90b7d6..5e52cecb76be3 100644
--- a/src/core/server/metrics/collectors/os.test.ts
+++ b/src/core/server/metrics/collectors/os.test.ts
@@ -20,6 +20,7 @@
jest.mock('getos', () => (cb: Function) => cb(null, { dist: 'distrib', release: 'release' }));
import os from 'os';
+import { cgroupCollectorMock } from './os.test.mocks';
import { OsMetricsCollector } from './os';
describe('OsMetricsCollector', () => {
@@ -27,6 +28,8 @@ describe('OsMetricsCollector', () => {
beforeEach(() => {
collector = new OsMetricsCollector();
+ cgroupCollectorMock.collect.mockReset();
+ cgroupCollectorMock.reset.mockReset();
});
afterEach(() => {
@@ -96,4 +99,9 @@ describe('OsMetricsCollector', () => {
'15m': fifteenMinLoad,
});
});
+
+ it('calls the cgroup sub-collector', async () => {
+ await collector.collect();
+ expect(cgroupCollectorMock.collect).toHaveBeenCalled();
+ });
});
diff --git a/src/core/server/metrics/collectors/os.ts b/src/core/server/metrics/collectors/os.ts
index 59bef9d8ddd2b..eae49278405a9 100644
--- a/src/core/server/metrics/collectors/os.ts
+++ b/src/core/server/metrics/collectors/os.ts
@@ -21,10 +21,22 @@ import os from 'os';
import getosAsync, { LinuxOs } from 'getos';
import { promisify } from 'util';
import { OpsOsMetrics, MetricsCollector } from './types';
+import { OsCgroupMetricsCollector } from './cgroup';
const getos = promisify(getosAsync);
+export interface OpsMetricsCollectorOptions {
+ cpuPath?: string;
+ cpuAcctPath?: string;
+}
+
export class OsMetricsCollector implements MetricsCollector {
+ private readonly cgroupCollector: OsCgroupMetricsCollector;
+
+ constructor(options: OpsMetricsCollectorOptions = {}) {
+ this.cgroupCollector = new OsCgroupMetricsCollector(options);
+ }
+
public async collect(): Promise {
const platform = os.platform();
const load = os.loadavg();
@@ -43,20 +55,30 @@ export class OsMetricsCollector implements MetricsCollector {
used_in_bytes: os.totalmem() - os.freemem(),
},
uptime_in_millis: os.uptime() * 1000,
+ ...(await this.getDistroStats(platform)),
+ ...(await this.cgroupCollector.collect()),
};
+ return metrics;
+ }
+
+ public reset() {}
+
+ private async getDistroStats(
+ platform: string
+ ): Promise> {
if (platform === 'linux') {
try {
const distro = (await getos()) as LinuxOs;
- metrics.distro = distro.dist;
- metrics.distroRelease = `${distro.dist}-${distro.release}`;
+ return {
+ distro: distro.dist,
+ distroRelease: `${distro.dist}-${distro.release}`,
+ };
} catch (e) {
// ignore errors
}
}
- return metrics;
+ return {};
}
-
- public reset() {}
}
diff --git a/src/core/server/metrics/collectors/types.ts b/src/core/server/metrics/collectors/types.ts
index 73e8975a6b362..77ea13a1f0787 100644
--- a/src/core/server/metrics/collectors/types.ts
+++ b/src/core/server/metrics/collectors/types.ts
@@ -85,6 +85,33 @@ export interface OpsOsMetrics {
};
/** the OS uptime */
uptime_in_millis: number;
+
+ /** cpu accounting metrics, undefined when not running in a cgroup */
+ cpuacct?: {
+ /** name of this process's cgroup */
+ control_group: string;
+ /** cpu time used by this process's cgroup */
+ usage_nanos: number;
+ };
+
+ /** cpu cgroup metrics, undefined when not running in a cgroup */
+ cpu?: {
+ /** name of this process's cgroup */
+ control_group: string;
+ /** the length of the cfs period */
+ cfs_period_micros: number;
+ /** total available run-time within a cfs period */
+ cfs_quota_micros: number;
+ /** current stats on the cfs periods */
+ stat: {
+ /** number of cfs periods that elapsed */
+ number_of_elapsed_periods: number;
+ /** number of times the cgroup has been throttled */
+ number_of_times_throttled: number;
+ /** total amount of time the cgroup has been throttled for */
+ time_throttled_nanos: number;
+ };
+ };
}
/**
diff --git a/src/core/server/metrics/metrics_service.mock.ts b/src/core/server/metrics/metrics_service.mock.ts
index 769f6ee2a549a..2af653004a479 100644
--- a/src/core/server/metrics/metrics_service.mock.ts
+++ b/src/core/server/metrics/metrics_service.mock.ts
@@ -21,20 +21,18 @@ import { MetricsService } from './metrics_service';
import {
InternalMetricsServiceSetup,
InternalMetricsServiceStart,
+ MetricsServiceSetup,
MetricsServiceStart,
} from './types';
const createInternalSetupContractMock = () => {
- const setupContract: jest.Mocked = {};
- return setupContract;
-};
-
-const createStartContractMock = () => {
- const startContract: jest.Mocked = {
+ const setupContract: jest.Mocked = {
+ collectionInterval: 30000,
getOpsMetrics$: jest.fn(),
};
- startContract.getOpsMetrics$.mockReturnValue(
+ 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 },
@@ -56,11 +54,21 @@ const createStartContractMock = () => {
concurrent_connections: 1,
})
);
+ return setupContract;
+};
+
+const createSetupContractMock = () => {
+ const startContract: jest.Mocked = createInternalSetupContractMock();
return startContract;
};
const createInternalStartContractMock = () => {
- const startContract: jest.Mocked = createStartContractMock();
+ const startContract: jest.Mocked = createInternalSetupContractMock();
+ return startContract;
+};
+
+const createStartContractMock = () => {
+ const startContract: jest.Mocked = createInternalSetupContractMock();
return startContract;
};
@@ -77,7 +85,7 @@ const createMock = () => {
export const metricsServiceMock = {
create: createMock,
- createSetupContract: createStartContractMock,
+ createSetupContract: createSetupContractMock,
createStartContract: createStartContractMock,
createInternalSetupContract: createInternalSetupContractMock,
createInternalStartContract: createInternalStartContractMock,
diff --git a/src/core/server/metrics/metrics_service.ts b/src/core/server/metrics/metrics_service.ts
index f28fb21aaac0d..d4696b3aa9aaf 100644
--- a/src/core/server/metrics/metrics_service.ts
+++ b/src/core/server/metrics/metrics_service.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { Subject } from 'rxjs';
+import { ReplaySubject } from 'rxjs';
import { first } from 'rxjs/operators';
import { CoreService } from '../../types';
import { CoreContext } from '../core_context';
@@ -37,26 +37,21 @@ export class MetricsService
private readonly logger: Logger;
private metricsCollector?: OpsMetricsCollector;
private collectInterval?: NodeJS.Timeout;
- private metrics$ = new Subject();
+ private metrics$ = new ReplaySubject();
+ private service?: InternalMetricsServiceSetup;
constructor(private readonly coreContext: CoreContext) {
this.logger = coreContext.logger.get('metrics');
}
public async setup({ http }: MetricsServiceSetupDeps): Promise {
- this.metricsCollector = new OpsMetricsCollector(http.server);
- return {};
- }
-
- public async start(): Promise {
- if (!this.metricsCollector) {
- throw new Error('#setup() needs to be run first');
- }
const config = await this.coreContext.configService
.atPath(opsConfig.path)
.pipe(first())
.toPromise();
+ this.metricsCollector = new OpsMetricsCollector(http.server, config.cGroupOverrides);
+
await this.refreshMetrics();
this.collectInterval = setInterval(() => {
@@ -65,9 +60,20 @@ export class MetricsService
const metricsObservable = this.metrics$.asObservable();
- return {
+ this.service = {
+ collectionInterval: config.interval.asMilliseconds(),
getOpsMetrics$: () => metricsObservable,
};
+
+ return this.service;
+ }
+
+ public async start(): Promise {
+ if (!this.service) {
+ throw new Error('#setup() needs to be run first');
+ }
+
+ return this.service;
}
private async refreshMetrics() {
diff --git a/src/core/server/metrics/ops_config.ts b/src/core/server/metrics/ops_config.ts
index bd6ae5cc5474d..5f3f67e931c38 100644
--- a/src/core/server/metrics/ops_config.ts
+++ b/src/core/server/metrics/ops_config.ts
@@ -23,6 +23,10 @@ export const opsConfig = {
path: 'ops',
schema: schema.object({
interval: schema.duration({ defaultValue: '5s' }),
+ cGroupOverrides: schema.object({
+ cpuPath: schema.maybe(schema.string()),
+ cpuAcctPath: schema.maybe(schema.string()),
+ }),
}),
};
diff --git a/src/core/server/metrics/ops_metrics_collector.test.ts b/src/core/server/metrics/ops_metrics_collector.test.ts
index 9e76895b14578..7aa3f7cd3baf0 100644
--- a/src/core/server/metrics/ops_metrics_collector.test.ts
+++ b/src/core/server/metrics/ops_metrics_collector.test.ts
@@ -30,7 +30,7 @@ describe('OpsMetricsCollector', () => {
beforeEach(() => {
const hapiServer = httpServiceMock.createInternalSetupContract().server;
- collector = new OpsMetricsCollector(hapiServer);
+ collector = new OpsMetricsCollector(hapiServer, {});
mockOsCollector.collect.mockResolvedValue('osMetrics');
});
@@ -51,6 +51,7 @@ describe('OpsMetricsCollector', () => {
expect(mockServerCollector.collect).toHaveBeenCalledTimes(1);
expect(metrics).toEqual({
+ collected_at: expect.any(Date),
process: 'processMetrics',
os: 'osMetrics',
requests: 'serverRequestsMetrics',
diff --git a/src/core/server/metrics/ops_metrics_collector.ts b/src/core/server/metrics/ops_metrics_collector.ts
index 525515dba1457..af74caa6cb386 100644
--- a/src/core/server/metrics/ops_metrics_collector.ts
+++ b/src/core/server/metrics/ops_metrics_collector.ts
@@ -21,6 +21,7 @@ import { Server as HapiServer } from 'hapi';
import {
ProcessMetricsCollector,
OsMetricsCollector,
+ OpsMetricsCollectorOptions,
ServerMetricsCollector,
MetricsCollector,
} from './collectors';
@@ -31,9 +32,9 @@ export class OpsMetricsCollector implements MetricsCollector {
private readonly osCollector: OsMetricsCollector;
private readonly serverCollector: ServerMetricsCollector;
- constructor(server: HapiServer) {
+ constructor(server: HapiServer, opsOptions: OpsMetricsCollectorOptions) {
this.processCollector = new ProcessMetricsCollector();
- this.osCollector = new OsMetricsCollector();
+ this.osCollector = new OsMetricsCollector(opsOptions);
this.serverCollector = new ServerMetricsCollector(server);
}
@@ -44,6 +45,7 @@ export class OpsMetricsCollector implements MetricsCollector {
this.serverCollector.collect(),
]);
return {
+ collected_at: new Date(),
process,
os,
...server,
diff --git a/src/core/server/metrics/types.ts b/src/core/server/metrics/types.ts
index cbf0acacd6bab..c177b3ed25115 100644
--- a/src/core/server/metrics/types.ts
+++ b/src/core/server/metrics/types.ts
@@ -20,14 +20,15 @@
import { Observable } from 'rxjs';
import { OpsProcessMetrics, OpsOsMetrics, OpsServerMetrics } from './collectors';
-// eslint-disable-next-line @typescript-eslint/no-empty-interface
-export interface MetricsServiceSetup {}
/**
* APIs to retrieves metrics gathered and exposed by the core platform.
*
* @public
*/
-export interface MetricsServiceStart {
+export interface MetricsServiceSetup {
+ /** Interval metrics are collected in milliseconds */
+ readonly collectionInterval: number;
+
/**
* Retrieve an observable emitting the {@link OpsMetrics} gathered.
* The observable will emit an initial value during core's `start` phase, and a new value every fixed interval of time,
@@ -42,6 +43,12 @@ export interface MetricsServiceStart {
*/
getOpsMetrics$: () => Observable;
}
+/**
+ * {@inheritdoc MetricsServiceSetup}
+ *
+ * @public
+ */
+export type MetricsServiceStart = MetricsServiceSetup;
export type InternalMetricsServiceSetup = MetricsServiceSetup;
export type InternalMetricsServiceStart = MetricsServiceStart;
@@ -53,6 +60,8 @@ export type InternalMetricsServiceStart = MetricsServiceStart;
* @public
*/
export interface OpsMetrics {
+ /** Time metrics were recorded at. */
+ collected_at: Date;
/** Process related metrics */
process: OpsProcessMetrics;
/** OS related metrics */
diff --git a/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts b/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts
index 64d1256be2f30..836aabf881474 100644
--- a/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts
+++ b/src/core/server/plugins/discovery/plugin_manifest_parser.test.ts
@@ -116,6 +116,16 @@ test('logs warning if pluginId is not in camelCase format', async () => {
`);
});
+test('does not log pluginId format warning in dist mode', async () => {
+ mockReadFile.mockImplementation((path, cb) => {
+ cb(null, Buffer.from(JSON.stringify({ id: 'some_name', version: 'kibana', server: true })));
+ });
+
+ expect(loggingSystemMock.collect(logger).warn).toHaveLength(0);
+ await parseManifest(pluginPath, { ...packageInfo, dist: true }, logger);
+ expect(loggingSystemMock.collect(logger).warn.length).toBe(0);
+});
+
test('return error when plugin version is missing', async () => {
mockReadFile.mockImplementation((path, cb) => {
cb(null, Buffer.from(JSON.stringify({ id: 'someId' })));
diff --git a/src/core/server/plugins/discovery/plugin_manifest_parser.ts b/src/core/server/plugins/discovery/plugin_manifest_parser.ts
index 0d33e266c37db..cfc412cb60b50 100644
--- a/src/core/server/plugins/discovery/plugin_manifest_parser.ts
+++ b/src/core/server/plugins/discovery/plugin_manifest_parser.ts
@@ -116,7 +116,7 @@ export async function parseManifest(
);
}
- if (!isCamelCase(manifest.id)) {
+ if (!packageInfo.dist && !isCamelCase(manifest.id)) {
log.warn(`Expect plugin "id" in camelCase, but found: ${manifest.id}`);
}
diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts
index fa2659ca130a0..af0b0e19b3227 100644
--- a/src/core/server/plugins/plugin_context.ts
+++ b/src/core/server/plugins/plugin_context.ts
@@ -185,6 +185,9 @@ export function createPluginSetupContext(
status: {
core$: deps.status.core$,
overall$: deps.status.overall$,
+ set: deps.status.plugins.set.bind(null, plugin.name),
+ dependencies$: deps.status.plugins.getDependenciesStatus$(plugin.name),
+ derivedStatus$: deps.status.plugins.getDerivedStatus$(plugin.name),
},
uiSettings: {
register: deps.uiSettings.register,
@@ -233,6 +236,7 @@ export function createPluginStartContext(
getTypeRegistry: deps.savedObjects.getTypeRegistry,
},
metrics: {
+ collectionInterval: deps.metrics.collectionInterval,
getOpsMetrics$: deps.metrics.getOpsMetrics$,
},
uiSettings: {
diff --git a/src/core/server/plugins/plugins_system.test.ts b/src/core/server/plugins/plugins_system.test.ts
index 7af77491df1ab..71ac31db13f92 100644
--- a/src/core/server/plugins/plugins_system.test.ts
+++ b/src/core/server/plugins/plugins_system.test.ts
@@ -100,15 +100,27 @@ test('getPluginDependencies returns dependency tree of symbols', () => {
pluginsSystem.addPlugin(createPlugin('no-dep'));
expect(pluginsSystem.getPluginDependencies()).toMatchInlineSnapshot(`
- Map {
- Symbol(plugin-a) => Array [
- Symbol(no-dep),
- ],
- Symbol(plugin-b) => Array [
- Symbol(plugin-a),
- Symbol(no-dep),
- ],
- Symbol(no-dep) => Array [],
+ Object {
+ "asNames": Map {
+ "plugin-a" => Array [
+ "no-dep",
+ ],
+ "plugin-b" => Array [
+ "plugin-a",
+ "no-dep",
+ ],
+ "no-dep" => Array [],
+ },
+ "asOpaqueIds": Map {
+ Symbol(plugin-a) => Array [
+ Symbol(no-dep),
+ ],
+ Symbol(plugin-b) => Array [
+ Symbol(plugin-a),
+ Symbol(no-dep),
+ ],
+ Symbol(no-dep) => Array [],
+ },
}
`);
});
diff --git a/src/core/server/plugins/plugins_system.ts b/src/core/server/plugins/plugins_system.ts
index f5c1b35d678a3..b2acd9a6fd04b 100644
--- a/src/core/server/plugins/plugins_system.ts
+++ b/src/core/server/plugins/plugins_system.ts
@@ -20,10 +20,11 @@
import { CoreContext } from '../core_context';
import { Logger } from '../logging';
import { PluginWrapper } from './plugin';
-import { DiscoveredPlugin, PluginName, PluginOpaqueId } from './types';
+import { DiscoveredPlugin, PluginName } from './types';
import { createPluginSetupContext, createPluginStartContext } from './plugin_context';
import { PluginsServiceSetupDeps, PluginsServiceStartDeps } from './plugins_service';
import { withTimeout } from '../../utils';
+import { PluginDependencies } from '.';
const Sec = 1000;
/** @internal */
@@ -45,9 +46,19 @@ export class PluginsSystem {
* @returns a ReadonlyMap of each plugin and an Array of its available dependencies
* @internal
*/
- public getPluginDependencies(): ReadonlyMap {
- // Return dependency map of opaque ids
- return new Map(
+ public getPluginDependencies(): PluginDependencies {
+ const asNames = new Map(
+ [...this.plugins].map(([name, plugin]) => [
+ plugin.name,
+ [
+ ...new Set([
+ ...plugin.requiredPlugins,
+ ...plugin.optionalPlugins.filter((optPlugin) => this.plugins.has(optPlugin)),
+ ]),
+ ].map((depId) => this.plugins.get(depId)!.name),
+ ])
+ );
+ const asOpaqueIds = new Map(
[...this.plugins].map(([name, plugin]) => [
plugin.opaqueId,
[
@@ -58,6 +69,8 @@ export class PluginsSystem {
].map((depId) => this.plugins.get(depId)!.opaqueId),
])
);
+
+ return { asNames, asOpaqueIds };
}
public async setupPlugins(deps: PluginsServiceSetupDeps) {
diff --git a/src/core/server/plugins/types.ts b/src/core/server/plugins/types.ts
index eb2a9ca3daf5f..517261b5bc9bb 100644
--- a/src/core/server/plugins/types.ts
+++ b/src/core/server/plugins/types.ts
@@ -93,6 +93,12 @@ export type PluginName = string;
/** @public */
export type PluginOpaqueId = symbol;
+/** @internal */
+export interface PluginDependencies {
+ asNames: ReadonlyMap;
+ asOpaqueIds: ReadonlyMap;
+}
+
/**
* Describes the set of required and optional properties plugin can define in its
* mandatory JSON manifest file.
diff --git a/src/core/server/saved_objects/__snapshots__/utils.test.ts.snap b/src/core/server/saved_objects/__snapshots__/utils.test.ts.snap
deleted file mode 100644
index 7cd0297e57857..0000000000000
--- a/src/core/server/saved_objects/__snapshots__/utils.test.ts.snap
+++ /dev/null
@@ -1,184 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`convertLegacyTypes converts the legacy mappings using default values if no schemas are specified 1`] = `
-Array [
- Object {
- "convertToAliasScript": undefined,
- "hidden": false,
- "indexPattern": undefined,
- "management": undefined,
- "mappings": Object {
- "properties": Object {
- "fieldA": Object {
- "type": "text",
- },
- },
- },
- "migrations": Object {},
- "name": "typeA",
- "namespaceType": "single",
- },
- Object {
- "convertToAliasScript": undefined,
- "hidden": false,
- "indexPattern": undefined,
- "management": undefined,
- "mappings": Object {
- "properties": Object {
- "fieldB": Object {
- "type": "text",
- },
- },
- },
- "migrations": Object {},
- "name": "typeB",
- "namespaceType": "single",
- },
- Object {
- "convertToAliasScript": undefined,
- "hidden": false,
- "indexPattern": undefined,
- "management": undefined,
- "mappings": Object {
- "properties": Object {
- "fieldC": Object {
- "type": "text",
- },
- },
- },
- "migrations": Object {},
- "name": "typeC",
- "namespaceType": "single",
- },
-]
-`;
-
-exports[`convertLegacyTypes merges everything when all are present 1`] = `
-Array [
- Object {
- "convertToAliasScript": undefined,
- "hidden": true,
- "indexPattern": "myIndex",
- "management": undefined,
- "mappings": Object {
- "properties": Object {
- "fieldA": Object {
- "type": "text",
- },
- },
- },
- "migrations": Object {
- "1.0.0": [Function],
- "2.0.4": [Function],
- },
- "name": "typeA",
- "namespaceType": "agnostic",
- },
- Object {
- "convertToAliasScript": "some alias script",
- "hidden": false,
- "indexPattern": undefined,
- "management": undefined,
- "mappings": Object {
- "properties": Object {
- "anotherFieldB": Object {
- "type": "boolean",
- },
- "fieldB": Object {
- "type": "text",
- },
- },
- },
- "migrations": Object {},
- "name": "typeB",
- "namespaceType": "single",
- },
- Object {
- "convertToAliasScript": undefined,
- "hidden": false,
- "indexPattern": undefined,
- "management": undefined,
- "mappings": Object {
- "properties": Object {
- "fieldC": Object {
- "type": "text",
- },
- },
- },
- "migrations": Object {
- "1.5.3": [Function],
- },
- "name": "typeC",
- "namespaceType": "single",
- },
-]
-`;
-
-exports[`convertLegacyTypes merges the mappings and the schema to create the type when schema exists for the type 1`] = `
-Array [
- Object {
- "convertToAliasScript": undefined,
- "hidden": true,
- "indexPattern": "fooBar",
- "management": undefined,
- "mappings": Object {
- "properties": Object {
- "fieldA": Object {
- "type": "text",
- },
- },
- },
- "migrations": Object {},
- "name": "typeA",
- "namespaceType": "agnostic",
- },
- Object {
- "convertToAliasScript": undefined,
- "hidden": false,
- "indexPattern": "barBaz",
- "management": undefined,
- "mappings": Object {
- "properties": Object {
- "fieldB": Object {
- "type": "text",
- },
- },
- },
- "migrations": Object {},
- "name": "typeB",
- "namespaceType": "multiple",
- },
- Object {
- "convertToAliasScript": undefined,
- "hidden": false,
- "indexPattern": undefined,
- "management": undefined,
- "mappings": Object {
- "properties": Object {
- "fieldC": Object {
- "type": "text",
- },
- },
- },
- "migrations": Object {},
- "name": "typeC",
- "namespaceType": "single",
- },
- Object {
- "convertToAliasScript": undefined,
- "hidden": false,
- "indexPattern": "bazQux",
- "management": undefined,
- "mappings": Object {
- "properties": Object {
- "fieldD": Object {
- "type": "text",
- },
- },
- },
- "migrations": Object {},
- "name": "typeD",
- "namespaceType": "agnostic",
- },
-]
-`;
diff --git a/src/core/server/saved_objects/index.ts b/src/core/server/saved_objects/index.ts
index a294b28753f7b..f2bae29c4743b 100644
--- a/src/core/server/saved_objects/index.ts
+++ b/src/core/server/saved_objects/index.ts
@@ -19,8 +19,6 @@
export * from './service';
-export { SavedObjectsSchema } from './schema';
-
export * from './import';
export {
diff --git a/src/core/server/saved_objects/migrations/core/document_migrator.test.ts b/src/core/server/saved_objects/migrations/core/document_migrator.test.ts
index 4fc94d1992869..4cc4f696d307c 100644
--- a/src/core/server/saved_objects/migrations/core/document_migrator.test.ts
+++ b/src/core/server/saved_objects/migrations/core/document_migrator.test.ts
@@ -48,7 +48,6 @@ describe('DocumentMigrator', () => {
return {
kibanaVersion: '25.2.3',
typeRegistry: createRegistry(),
- validateDoc: _.noop,
log: mockLogger,
};
}
@@ -60,7 +59,6 @@ describe('DocumentMigrator', () => {
name: 'foo',
migrations: _.noop as any,
}),
- validateDoc: _.noop,
log: mockLogger,
};
expect(() => new DocumentMigrator(invalidDefinition)).toThrow(
@@ -77,7 +75,6 @@ describe('DocumentMigrator', () => {
bar: (doc) => doc,
},
}),
- validateDoc: _.noop,
log: mockLogger,
};
expect(() => new DocumentMigrator(invalidDefinition)).toThrow(
@@ -94,7 +91,6 @@ describe('DocumentMigrator', () => {
'1.2.3': 23 as any,
},
}),
- validateDoc: _.noop,
log: mockLogger,
};
expect(() => new DocumentMigrator(invalidDefinition)).toThrow(
@@ -633,27 +629,6 @@ describe('DocumentMigrator', () => {
bbb: '3.2.3',
});
});
-
- test('fails if the validate doc throws', () => {
- const migrator = new DocumentMigrator({
- ...testOpts(),
- typeRegistry: createRegistry({
- name: 'aaa',
- migrations: {
- '2.3.4': (d) => set(d, 'attributes.counter', 42),
- },
- }),
- validateDoc: (d) => {
- if ((d.attributes as any).counter === 42) {
- throw new Error('Meaningful!');
- }
- },
- });
-
- const doc = { id: '1', type: 'foo', attributes: {}, migrationVersion: {}, aaa: {} };
-
- expect(() => migrator.migrate(doc)).toThrow(/Meaningful/);
- });
});
function renameAttr(path: string, newPath: string) {
diff --git a/src/core/server/saved_objects/migrations/core/document_migrator.ts b/src/core/server/saved_objects/migrations/core/document_migrator.ts
index c50f755fda994..345704fbfd783 100644
--- a/src/core/server/saved_objects/migrations/core/document_migrator.ts
+++ b/src/core/server/saved_objects/migrations/core/document_migrator.ts
@@ -73,12 +73,9 @@ import { SavedObjectMigrationFn } from '../types';
export type TransformFn = (doc: SavedObjectUnsanitizedDoc) => SavedObjectUnsanitizedDoc;
-type ValidateDoc = (doc: SavedObjectUnsanitizedDoc) => void;
-
interface DocumentMigratorOptions {
kibanaVersion: string;
typeRegistry: ISavedObjectTypeRegistry;
- validateDoc: ValidateDoc;
log: Logger;
}
@@ -113,19 +110,16 @@ export class DocumentMigrator implements VersionedTransformer {
* @param {DocumentMigratorOptions} opts
* @prop {string} kibanaVersion - The current version of Kibana
* @prop {SavedObjectTypeRegistry} typeRegistry - The type registry to get type migrations from
- * @prop {ValidateDoc} validateDoc - A function which, given a document throws an error if it is
- * not up to date. This is used to ensure we don't let unmigrated documents slip through.
* @prop {Logger} log - The migration logger
* @memberof DocumentMigrator
*/
- constructor({ typeRegistry, kibanaVersion, log, validateDoc }: DocumentMigratorOptions) {
+ constructor({ typeRegistry, kibanaVersion, log }: DocumentMigratorOptions) {
validateMigrationDefinition(typeRegistry);
this.migrations = buildActiveMigrations(typeRegistry, log);
this.transformDoc = buildDocumentTransform({
kibanaVersion,
migrations: this.migrations,
- validateDoc,
});
}
@@ -231,21 +225,16 @@ function buildActiveMigrations(
* Creates a function which migrates and validates any document that is passed to it.
*/
function buildDocumentTransform({
- kibanaVersion,
migrations,
- validateDoc,
}: {
kibanaVersion: string;
migrations: ActiveMigrations;
- validateDoc: ValidateDoc;
}): TransformFn {
return function transformAndValidate(doc: SavedObjectUnsanitizedDoc) {
const result = doc.migrationVersion
? applyMigrations(doc, migrations)
: markAsUpToDate(doc, migrations);
- validateDoc(result);
-
// In order to keep tests a bit more stable, we won't
// tack on an empy migrationVersion to docs that have
// no migrations defined.
diff --git a/src/core/server/saved_objects/migrations/core/index_migrator.test.ts b/src/core/server/saved_objects/migrations/core/index_migrator.test.ts
index df89137a1d798..13f771c16bc67 100644
--- a/src/core/server/saved_objects/migrations/core/index_migrator.test.ts
+++ b/src/core/server/saved_objects/migrations/core/index_migrator.test.ts
@@ -369,6 +369,30 @@ describe('IndexMigrator', () => {
],
});
});
+
+ test('rejects when the migration function throws an error', async () => {
+ const { client } = testOpts;
+ const migrateDoc = jest.fn((doc: SavedObjectUnsanitizedDoc) => {
+ throw new Error('error migrating document');
+ });
+
+ testOpts.documentMigrator = {
+ migrationVersion: { foo: '1.2.3' },
+ migrate: migrateDoc,
+ };
+
+ withIndex(client, {
+ numOutOfDate: 1,
+ docs: [
+ [{ _id: 'foo:1', _source: { type: 'foo', foo: { name: 'Bar' } } }],
+ [{ _id: 'foo:2', _source: { type: 'foo', foo: { name: 'Baz' } } }],
+ ],
+ });
+
+ await expect(new IndexMigrator(testOpts).migrate()).rejects.toThrowErrorMatchingInlineSnapshot(
+ `"error migrating document"`
+ );
+ });
});
function withIndex(
diff --git a/src/core/server/saved_objects/migrations/core/migrate_raw_docs.test.ts b/src/core/server/saved_objects/migrations/core/migrate_raw_docs.test.ts
index 4c9d2e870a7bb..83dc042d2b96b 100644
--- a/src/core/server/saved_objects/migrations/core/migrate_raw_docs.test.ts
+++ b/src/core/server/saved_objects/migrations/core/migrate_raw_docs.test.ts
@@ -90,4 +90,18 @@ describe('migrateRawDocs', () => {
expect(logger.error).toBeCalledTimes(1);
});
+
+ test('rejects when the transform function throws an error', async () => {
+ const transform = jest.fn((doc: any) => {
+ throw new Error('error during transform');
+ });
+ await expect(
+ migrateRawDocs(
+ new SavedObjectsSerializer(new SavedObjectTypeRegistry()),
+ transform,
+ [{ _id: 'a:b', _source: { type: 'a', a: { name: 'AAA' } } }],
+ createSavedObjectsMigrationLoggerMock()
+ )
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`"error during transform"`);
+ });
});
diff --git a/src/core/server/saved_objects/migrations/core/migrate_raw_docs.ts b/src/core/server/saved_objects/migrations/core/migrate_raw_docs.ts
index 2bdf59d25dc74..5a5048d8ad88f 100644
--- a/src/core/server/saved_objects/migrations/core/migrate_raw_docs.ts
+++ b/src/core/server/saved_objects/migrations/core/migrate_raw_docs.ts
@@ -78,10 +78,14 @@ function transformNonBlocking(
): (doc: SavedObjectUnsanitizedDoc) => Promise {
// promises aren't enough to unblock the event loop
return (doc: SavedObjectUnsanitizedDoc) =>
- new Promise((resolve) => {
+ new Promise((resolve, reject) => {
// set immediate is though
setImmediate(() => {
- resolve(transform(doc));
+ try {
+ resolve(transform(doc));
+ } catch (e) {
+ reject(e);
+ }
});
});
}
diff --git a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts
index cc443093e30a3..7eb2cfefe4620 100644
--- a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts
+++ b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts
@@ -134,7 +134,6 @@ const mockOptions = () => {
const options: MockedOptions = {
logger: loggingSystemMock.create().get(),
kibanaVersion: '8.2.3',
- savedObjectValidations: {},
typeRegistry: createRegistry([
{
name: 'testtype',
diff --git a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts
index 85b9099308807..18a385c6994b8 100644
--- a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts
+++ b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts
@@ -28,7 +28,6 @@ import { BehaviorSubject } from 'rxjs';
import { Logger } from '../../../logging';
import { IndexMapping, SavedObjectsTypeMappingDefinitions } from '../../mappings';
import { SavedObjectUnsanitizedDoc, SavedObjectsSerializer } from '../../serialization';
-import { docValidator, PropertyValidators } from '../../validation';
import { buildActiveMappings, IndexMigrator, MigrationResult, MigrationStatus } from '../core';
import { DocumentMigrator, VersionedTransformer } from '../core/document_migrator';
import { MigrationEsClient } from '../core/';
@@ -44,7 +43,6 @@ export interface KibanaMigratorOptions {
kibanaConfig: KibanaConfigType;
kibanaVersion: string;
logger: Logger;
- savedObjectValidations: PropertyValidators;
}
export type IKibanaMigrator = Pick;
@@ -80,7 +78,6 @@ export class KibanaMigrator {
typeRegistry,
kibanaConfig,
savedObjectsConfig,
- savedObjectValidations,
kibanaVersion,
logger,
}: KibanaMigratorOptions) {
@@ -94,7 +91,6 @@ export class KibanaMigrator {
this.documentMigrator = new DocumentMigrator({
kibanaVersion,
typeRegistry,
- validateDoc: docValidator(savedObjectValidations || {}),
log: this.log,
});
// Building the active mappings (and associated md5sums) is an expensive
@@ -124,9 +120,17 @@ export class KibanaMigrator {
Array<{ status: string }>
> {
if (this.migrationResult === undefined || rerun) {
- this.status$.next({ status: 'running' });
+ // Reruns are only used by CI / EsArchiver. Publishing status updates on reruns results in slowing down CI
+ // unnecessarily, so we skip it in this case.
+ if (!rerun) {
+ this.status$.next({ status: 'running' });
+ }
+
this.migrationResult = this.runMigrationsInternal().then((result) => {
- this.status$.next({ status: 'completed', result });
+ // Similar to above, don't publish status updates when rerunning in CI.
+ if (!rerun) {
+ this.status$.next({ status: 'completed', result });
+ }
return result;
});
}
diff --git a/src/core/server/saved_objects/routes/bulk_update.ts b/src/core/server/saved_objects/routes/bulk_update.ts
index c112833b29f3f..882213644146a 100644
--- a/src/core/server/saved_objects/routes/bulk_update.ts
+++ b/src/core/server/saved_objects/routes/bulk_update.ts
@@ -40,6 +40,7 @@ export const registerBulkUpdateRoute = (router: IRouter) => {
})
)
),
+ namespace: schema.maybe(schema.string({ minLength: 1 })),
})
),
},
diff --git a/src/core/server/saved_objects/saved_objects_service.mock.ts b/src/core/server/saved_objects/saved_objects_service.mock.ts
index 6f5ecb1eb464b..e3d44c20dd190 100644
--- a/src/core/server/saved_objects/saved_objects_service.mock.ts
+++ b/src/core/server/saved_objects/saved_objects_service.mock.ts
@@ -26,8 +26,7 @@ import {
SavedObjectsServiceSetup,
SavedObjectsServiceStart,
} from './saved_objects_service';
-import { mockKibanaMigrator } from './migrations/kibana/kibana_migrator.mock';
-import { savedObjectsClientProviderMock } from './service/lib/scoped_client_provider.mock';
+
import { savedObjectsRepositoryMock } from './service/lib/repository.mock';
import { savedObjectsClientMock } from './service/saved_objects_client.mock';
import { typeRegistryMock } from './saved_objects_type_registry.mock';
@@ -54,11 +53,7 @@ const createStartContractMock = () => {
};
const createInternalStartContractMock = () => {
- const internalStartContract: jest.Mocked = {
- ...createStartContractMock(),
- clientProvider: savedObjectsClientProviderMock.create(),
- migrator: mockKibanaMigrator.create(),
- };
+ const internalStartContract: jest.Mocked = createStartContractMock();
return internalStartContract;
};
diff --git a/src/core/server/saved_objects/saved_objects_service.test.ts b/src/core/server/saved_objects/saved_objects_service.test.ts
index 8df6a07318c45..d6b30889eba5f 100644
--- a/src/core/server/saved_objects/saved_objects_service.test.ts
+++ b/src/core/server/saved_objects/saved_objects_service.test.ts
@@ -33,7 +33,6 @@ import { Env } from '../config';
import { configServiceMock } from '../mocks';
import { elasticsearchServiceMock } from '../elasticsearch/elasticsearch_service.mock';
import { elasticsearchClientMock } from '../elasticsearch/client/mocks';
-import { legacyServiceMock } from '../legacy/legacy_service.mock';
import { httpServiceMock } from '../http/http_service.mock';
import { httpServerMock } from '../http/http_server.mocks';
import { SavedObjectsClientFactoryProvider } from './service/lib';
@@ -65,7 +64,6 @@ describe('SavedObjectsService', () => {
return {
http: httpServiceMock.createInternalSetupContract(),
elasticsearch: elasticsearchMock,
- legacyPlugins: legacyServiceMock.createDiscoverPlugins(),
};
};
@@ -239,8 +237,7 @@ describe('SavedObjectsService', () => {
await soService.setup(createSetupDeps());
expect(migratorInstanceMock.runMigrations).toHaveBeenCalledTimes(0);
- const startContract = await soService.start(createStartDeps());
- expect(startContract.migrator).toBe(migratorInstanceMock);
+ await soService.start(createStartDeps());
expect(migratorInstanceMock.runMigrations).toHaveBeenCalledTimes(1);
});
diff --git a/src/core/server/saved_objects/saved_objects_service.ts b/src/core/server/saved_objects/saved_objects_service.ts
index f05e912b12ad8..5cc59d55a254e 100644
--- a/src/core/server/saved_objects/saved_objects_service.ts
+++ b/src/core/server/saved_objects/saved_objects_service.ts
@@ -23,12 +23,10 @@ import { CoreService } from '../../types';
import {
SavedObjectsClient,
SavedObjectsClientProvider,
- ISavedObjectsClientProvider,
SavedObjectsClientProviderOptions,
} from './';
import { KibanaMigrator, IKibanaMigrator } from './migrations';
import { CoreContext } from '../core_context';
-import { LegacyServiceDiscoverPlugins } from '../legacy';
import {
ElasticsearchClient,
IClusterClient,
@@ -49,9 +47,7 @@ import {
SavedObjectsClientWrapperFactory,
} from './service/lib/scoped_client_provider';
import { Logger } from '../logging';
-import { convertLegacyTypes } from './utils';
import { SavedObjectTypeRegistry, ISavedObjectTypeRegistry } from './saved_objects_type_registry';
-import { PropertyValidators } from './validation';
import { SavedObjectsSerializer } from './serialization';
import { registerRoutes } from './routes';
import { ServiceStatus } from '../status';
@@ -67,9 +63,6 @@ import { createMigrationEsClient } from './migrations/core/';
* the factory provided to `setClientFactory` and wrapped by all wrappers
* registered through `addClientWrapper`.
*
- * All the setup APIs will throw if called after the service has started, and therefor cannot be used
- * from legacy plugin code. Legacy plugins should use the legacy savedObject service until migrated.
- *
* @example
* ```ts
* import { SavedObjectsClient, CoreSetup } from 'src/core/server';
@@ -155,9 +148,6 @@ export interface SavedObjectsServiceSetup {
* }
* }
* ```
- *
- * @remarks The type definition is an aggregation of the legacy savedObjects `schema`, `mappings` and `migration` concepts.
- * This API is the single entry point to register saved object types in the new platform.
*/
registerType: (type: SavedObjectsType) => void;
@@ -230,16 +220,7 @@ export interface SavedObjectsServiceStart {
getTypeRegistry: () => ISavedObjectTypeRegistry;
}
-export interface InternalSavedObjectsServiceStart extends SavedObjectsServiceStart {
- /**
- * @deprecated Exposed only for injecting into Legacy
- */
- migrator: IKibanaMigrator;
- /**
- * @deprecated Exposed only for injecting into Legacy
- */
- clientProvider: ISavedObjectsClientProvider;
-}
+export type InternalSavedObjectsServiceStart = SavedObjectsServiceStart;
/**
* Factory provided when invoking a {@link SavedObjectsClientFactoryProvider | client factory provider}
@@ -271,7 +252,6 @@ export interface SavedObjectsRepositoryFactory {
/** @internal */
export interface SavedObjectsSetupDeps {
http: InternalHttpServiceSetup;
- legacyPlugins: LegacyServiceDiscoverPlugins;
elasticsearch: InternalElasticsearchServiceSetup;
}
@@ -296,9 +276,8 @@ export class SavedObjectsService
private clientFactoryProvider?: SavedObjectsClientFactoryProvider;
private clientFactoryWrappers: WrappedClientFactoryWrapper[] = [];
- private migrator$ = new Subject();
+ private migrator$ = new Subject();
private typeRegistry = new SavedObjectTypeRegistry();
- private validations: PropertyValidators = {};
private started = false;
constructor(private readonly coreContext: CoreContext) {
@@ -310,13 +289,6 @@ export class SavedObjectsService
this.setupDeps = setupDeps;
- const legacyTypes = convertLegacyTypes(
- setupDeps.legacyPlugins.uiExports,
- setupDeps.legacyPlugins.pluginExtendedConfig
- );
- legacyTypes.forEach((type) => this.typeRegistry.registerType(type));
- this.validations = setupDeps.legacyPlugins.uiExports.savedObjectValidations || {};
-
const savedObjectsConfig = await this.coreContext.configService
.atPath('savedObjects')
.pipe(first())
@@ -471,8 +443,6 @@ export class SavedObjectsService
this.started = true;
return {
- migrator,
- clientProvider,
getScopedClient: clientProvider.getClient.bind(clientProvider),
createScopedRepository: repositoryFactory.createScopedRepository,
createInternalRepository: repositoryFactory.createInternalRepository,
@@ -488,13 +458,12 @@ export class SavedObjectsService
savedObjectsConfig: SavedObjectsMigrationConfigType,
client: IClusterClient,
migrationsRetryDelay?: number
- ): KibanaMigrator {
+ ): IKibanaMigrator {
return new KibanaMigrator({
typeRegistry: this.typeRegistry,
logger: this.logger,
kibanaVersion: this.coreContext.env.packageInfo.version,
savedObjectsConfig,
- savedObjectValidations: this.validations,
kibanaConfig,
client: createMigrationEsClient(client.asInternalUser, this.logger, migrationsRetryDelay),
});
diff --git a/src/core/server/saved_objects/schema/schema.test.ts b/src/core/server/saved_objects/schema/schema.test.ts
deleted file mode 100644
index f2daa13e43fce..0000000000000
--- a/src/core/server/saved_objects/schema/schema.test.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { SavedObjectsSchema, SavedObjectsSchemaDefinition } from './schema';
-
-describe('#isNamespaceAgnostic', () => {
- const expectResult = (expected: boolean, schemaDefinition?: SavedObjectsSchemaDefinition) => {
- const schema = new SavedObjectsSchema(schemaDefinition);
- const result = schema.isNamespaceAgnostic('foo');
- expect(result).toBe(expected);
- };
-
- it(`returns false when no schema is defined`, () => {
- expectResult(false);
- });
-
- it(`returns false for unknown types`, () => {
- expectResult(false, { bar: {} });
- });
-
- it(`returns false for non-namespace-agnostic type`, () => {
- expectResult(false, { foo: { isNamespaceAgnostic: false } });
- expectResult(false, { foo: { isNamespaceAgnostic: undefined } });
- });
-
- it(`returns true for explicitly namespace-agnostic type`, () => {
- expectResult(true, { foo: { isNamespaceAgnostic: true } });
- });
-});
-
-describe('#isSingleNamespace', () => {
- const expectResult = (expected: boolean, schemaDefinition?: SavedObjectsSchemaDefinition) => {
- const schema = new SavedObjectsSchema(schemaDefinition);
- const result = schema.isSingleNamespace('foo');
- expect(result).toBe(expected);
- };
-
- it(`returns true when no schema is defined`, () => {
- expectResult(true);
- });
-
- it(`returns true for unknown types`, () => {
- expectResult(true, { bar: {} });
- });
-
- it(`returns false for explicitly namespace-agnostic type`, () => {
- expectResult(false, { foo: { isNamespaceAgnostic: true } });
- });
-
- it(`returns false for explicitly multi-namespace type`, () => {
- expectResult(false, { foo: { multiNamespace: true } });
- });
-
- it(`returns true for non-namespace-agnostic and non-multi-namespace type`, () => {
- expectResult(true, { foo: { isNamespaceAgnostic: false, multiNamespace: false } });
- expectResult(true, { foo: { isNamespaceAgnostic: false, multiNamespace: undefined } });
- expectResult(true, { foo: { isNamespaceAgnostic: undefined, multiNamespace: false } });
- expectResult(true, { foo: { isNamespaceAgnostic: undefined, multiNamespace: undefined } });
- });
-});
-
-describe('#isMultiNamespace', () => {
- const expectResult = (expected: boolean, schemaDefinition?: SavedObjectsSchemaDefinition) => {
- const schema = new SavedObjectsSchema(schemaDefinition);
- const result = schema.isMultiNamespace('foo');
- expect(result).toBe(expected);
- };
-
- it(`returns false when no schema is defined`, () => {
- expectResult(false);
- });
-
- it(`returns false for unknown types`, () => {
- expectResult(false, { bar: {} });
- });
-
- it(`returns false for explicitly namespace-agnostic type`, () => {
- expectResult(false, { foo: { isNamespaceAgnostic: true } });
- });
-
- it(`returns false for non-multi-namespace type`, () => {
- expectResult(false, { foo: { multiNamespace: false } });
- expectResult(false, { foo: { multiNamespace: undefined } });
- });
-
- it(`returns true for non-namespace-agnostic and explicitly multi-namespace type`, () => {
- expectResult(true, { foo: { isNamespaceAgnostic: false, multiNamespace: true } });
- expectResult(true, { foo: { isNamespaceAgnostic: undefined, multiNamespace: true } });
- });
-});
diff --git a/src/core/server/saved_objects/schema/schema.ts b/src/core/server/saved_objects/schema/schema.ts
deleted file mode 100644
index ba1905158e822..0000000000000
--- a/src/core/server/saved_objects/schema/schema.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { LegacyConfig } from '../../legacy';
-
-/**
- * @deprecated
- * @internal
- **/
-interface SavedObjectsSchemaTypeDefinition {
- isNamespaceAgnostic?: boolean;
- multiNamespace?: boolean;
- hidden?: boolean;
- indexPattern?: ((config: LegacyConfig) => string) | string;
- convertToAliasScript?: string;
-}
-
-/**
- * @deprecated
- * @internal
- **/
-export interface SavedObjectsSchemaDefinition {
- [type: string]: SavedObjectsSchemaTypeDefinition;
-}
-
-/**
- * @deprecated This is only used by the {@link SavedObjectsLegacyService | legacy savedObjects service}
- * @internal
- **/
-export class SavedObjectsSchema {
- private readonly definition?: SavedObjectsSchemaDefinition;
- constructor(schemaDefinition?: SavedObjectsSchemaDefinition) {
- this.definition = schemaDefinition;
- }
-
- public isHiddenType(type: string) {
- if (this.definition && this.definition.hasOwnProperty(type)) {
- return Boolean(this.definition[type].hidden);
- }
-
- return false;
- }
-
- public getIndexForType(config: LegacyConfig, type: string): string | undefined {
- if (this.definition != null && this.definition.hasOwnProperty(type)) {
- const { indexPattern } = this.definition[type];
- return typeof indexPattern === 'function' ? indexPattern(config) : indexPattern;
- } else {
- return undefined;
- }
- }
-
- public getConvertToAliasScript(type: string): string | undefined {
- if (this.definition != null && this.definition.hasOwnProperty(type)) {
- return this.definition[type].convertToAliasScript;
- }
- }
-
- public isNamespaceAgnostic(type: string) {
- // if no plugins have registered a Saved Objects Schema,
- // this.schema will be undefined, and no types are namespace agnostic
- if (!this.definition) {
- return false;
- }
-
- const typeSchema = this.definition[type];
- if (!typeSchema) {
- return false;
- }
- return Boolean(typeSchema.isNamespaceAgnostic);
- }
-
- public isSingleNamespace(type: string) {
- // if no plugins have registered a Saved Objects Schema,
- // this.schema will be undefined, and all types are namespace isolated
- if (!this.definition) {
- return true;
- }
-
- const typeSchema = this.definition[type];
- if (!typeSchema) {
- return true;
- }
- return !Boolean(typeSchema.isNamespaceAgnostic) && !Boolean(typeSchema.multiNamespace);
- }
-
- public isMultiNamespace(type: string) {
- // if no plugins have registered a Saved Objects Schema,
- // this.schema will be undefined, and no types are multi-namespace
- if (!this.definition) {
- return false;
- }
-
- const typeSchema = this.definition[type];
- if (!typeSchema) {
- return false;
- }
- return !Boolean(typeSchema.isNamespaceAgnostic) && Boolean(typeSchema.multiNamespace);
- }
-}
diff --git a/src/core/server/saved_objects/service/index.ts b/src/core/server/saved_objects/service/index.ts
index 9f625b4732e26..c33a9f2f3b157 100644
--- a/src/core/server/saved_objects/service/index.ts
+++ b/src/core/server/saved_objects/service/index.ts
@@ -17,37 +17,6 @@
* under the License.
*/
-import { Readable } from 'stream';
-import { SavedObjectsClientProvider } from './lib';
-import { SavedObjectsClient } from './saved_objects_client';
-import { SavedObjectsExportOptions } from '../export';
-import { SavedObjectsImportOptions, SavedObjectsImportResponse } from '../import';
-import { SavedObjectsSchema } from '../schema';
-import { SavedObjectsResolveImportErrorsOptions } from '../import/types';
-
-/**
- * @internal
- * @deprecated
- */
-export interface SavedObjectsLegacyService {
- // ATTENTION: these types are incomplete
- addScopedSavedObjectsClientWrapperFactory: SavedObjectsClientProvider['addClientWrapperFactory'];
- setScopedSavedObjectsClientFactory: SavedObjectsClientProvider['setClientFactory'];
- getScopedSavedObjectsClient: SavedObjectsClientProvider['getClient'];
- SavedObjectsClient: typeof SavedObjectsClient;
- types: string[];
- schema: SavedObjectsSchema;
- getSavedObjectsRepository(...rest: any[]): any;
- importExport: {
- objectLimit: number;
- importSavedObjects(options: SavedObjectsImportOptions): Promise;
- resolveImportErrors(
- options: SavedObjectsResolveImportErrorsOptions
- ): Promise;
- getSortedObjectsForExport(options: SavedObjectsExportOptions): Promise;
- };
-}
-
export {
SavedObjectsRepository,
SavedObjectsClientProvider,
@@ -58,6 +27,7 @@ export {
SavedObjectsErrorHelpers,
SavedObjectsClientFactory,
SavedObjectsClientFactoryProvider,
+ SavedObjectsUtils,
} from './lib';
export * from './saved_objects_client';
diff --git a/src/core/server/saved_objects/service/lib/index.ts b/src/core/server/saved_objects/service/lib/index.ts
index e103120388e35..eae8c5ef2e10c 100644
--- a/src/core/server/saved_objects/service/lib/index.ts
+++ b/src/core/server/saved_objects/service/lib/index.ts
@@ -30,3 +30,5 @@ export {
} from './scoped_client_provider';
export { SavedObjectsErrorHelpers } from './errors';
+
+export { SavedObjectsUtils } from './utils';
diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js
index b1d6028465713..7d30875b90796 100644
--- a/src/core/server/saved_objects/service/lib/repository.test.js
+++ b/src/core/server/saved_objects/service/lib/repository.test.js
@@ -153,30 +153,35 @@ describe('SavedObjectsRepository', () => {
typeRegistry: registry,
kibanaVersion: '2.0.0',
log: {},
- validateDoc: jest.fn(),
});
- const getMockGetResponse = ({ type, id, references, namespace, originId }) => ({
- // NOTE: Elasticsearch returns more fields (_index, _type) but the SavedObjectsRepository method ignores these
- found: true,
- _id: `${registry.isSingleNamespace(type) && namespace ? `${namespace}:` : ''}${type}:${id}`,
- ...mockVersionProps,
- _source: {
- ...(registry.isSingleNamespace(type) && { namespace }),
- ...(registry.isMultiNamespace(type) && { namespaces: [namespace ?? 'default'] }),
- ...(originId && { originId }),
- type,
- [type]: { title: 'Testing' },
- references,
- specialProperty: 'specialValue',
- ...mockTimestampFields,
- },
- });
+ const getMockGetResponse = (
+ { type, id, references, namespace: objectNamespace, originId },
+ namespace
+ ) => {
+ const namespaceId = objectNamespace === 'default' ? undefined : objectNamespace ?? namespace;
+ return {
+ // NOTE: Elasticsearch returns more fields (_index, _type) but the SavedObjectsRepository method ignores these
+ found: true,
+ _id: `${
+ registry.isSingleNamespace(type) && namespaceId ? `${namespaceId}:` : ''
+ }${type}:${id}`,
+ ...mockVersionProps,
+ _source: {
+ ...(registry.isSingleNamespace(type) && { namespace: namespaceId }),
+ ...(registry.isMultiNamespace(type) && { namespaces: [namespaceId ?? 'default'] }),
+ ...(originId && { originId }),
+ type,
+ [type]: { title: 'Testing' },
+ references,
+ specialProperty: 'specialValue',
+ ...mockTimestampFields,
+ },
+ };
+ };
const getMockMgetResponse = (objects, namespace) => ({
- docs: objects.map((obj) =>
- obj.found === false ? obj : getMockGetResponse({ ...obj, namespace })
- ),
+ docs: objects.map((obj) => (obj.found === false ? obj : getMockGetResponse(obj, namespace))),
});
expect.extend({
@@ -587,6 +592,16 @@ describe('SavedObjectsRepository', () => {
);
});
+ it(`normalizes options.namespace from 'default' to undefined`, async () => {
+ await bulkCreateSuccess([obj1, obj2], { namespace: 'default' });
+ const expected = expect.not.objectContaining({ namespace: 'default' });
+ const body = [expect.any(Object), expected, expect.any(Object), expected];
+ expect(client.bulk).toHaveBeenCalledWith(
+ expect.objectContaining({ body }),
+ expect.anything()
+ );
+ });
+
it(`doesn't add namespace to request body for any types that are not single-namespace`, async () => {
const objects = [
{ ...obj1, type: NAMESPACE_AGNOSTIC_TYPE },
@@ -654,19 +669,19 @@ describe('SavedObjectsRepository', () => {
});
it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => {
- const getId = (type, id) => `${namespace}:${type}:${id}`;
+ const getId = (type, id) => `${namespace}:${type}:${id}`; // test that the raw document ID equals this (e.g., has a namespace prefix)
await bulkCreateSuccess([obj1, obj2], { namespace });
expectClientCallArgsAction([obj1, obj2], { method: 'create', getId });
});
it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => {
- const getId = (type, id) => `${type}:${id}`;
+ const getId = (type, id) => `${type}:${id}`; // test that the raw document ID equals this (e.g., does not have a namespace prefix)
await bulkCreateSuccess([obj1, obj2]);
expectClientCallArgsAction([obj1, obj2], { method: 'create', getId });
});
it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => {
- const getId = (type, id) => `${type}:${id}`;
+ const getId = (type, id) => `${type}:${id}`; // test that the raw document ID equals this (e.g., does not have a namespace prefix)
const objects = [
{ ...obj1, type: NAMESPACE_AGNOSTIC_TYPE },
{ ...obj2, type: MULTI_NAMESPACE_TYPE },
@@ -973,19 +988,25 @@ describe('SavedObjectsRepository', () => {
describe('client calls', () => {
it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => {
- const getId = (type, id) => `${namespace}:${type}:${id}`;
+ const getId = (type, id) => `${namespace}:${type}:${id}`; // test that the raw document ID equals this (e.g., has a namespace prefix)
await bulkGetSuccess([obj1, obj2], { namespace });
_expectClientCallArgs([obj1, obj2], { getId });
});
it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => {
- const getId = (type, id) => `${type}:${id}`;
+ const getId = (type, id) => `${type}:${id}`; // test that the raw document ID equals this (e.g., does not have a namespace prefix)
await bulkGetSuccess([obj1, obj2]);
_expectClientCallArgs([obj1, obj2], { getId });
});
+ it(`normalizes options.namespace from 'default' to undefined`, async () => {
+ const getId = (type, id) => `${type}:${id}`; // test that the raw document ID equals this (e.g., does not have a namespace prefix)
+ await bulkGetSuccess([obj1, obj2], { namespace: 'default' });
+ _expectClientCallArgs([obj1, obj2], { getId });
+ });
+
it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => {
- const getId = (type, id) => `${type}:${id}`;
+ const getId = (type, id) => `${type}:${id}`; // test that the raw document ID equals this (e.g., does not have a namespace prefix)
let objects = [obj1, obj2].map((obj) => ({ ...obj, type: NAMESPACE_AGNOSTIC_TYPE }));
await bulkGetSuccess(objects, { namespace });
_expectClientCallArgs(objects, { getId });
@@ -1328,32 +1349,66 @@ describe('SavedObjectsRepository', () => {
});
it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => {
- const getId = (type, id) => `${namespace}:${type}:${id}`;
+ const getId = (type, id) => `${namespace}:${type}:${id}`; // test that the raw document ID equals this (e.g., has a namespace prefix)
await bulkUpdateSuccess([obj1, obj2], { namespace });
expectClientCallArgsAction([obj1, obj2], { method: 'update', getId });
+
+ jest.clearAllMocks();
+ // test again with object namespace string that supersedes the operation's namespace ID
+ await bulkUpdateSuccess([
+ { ...obj1, namespace },
+ { ...obj2, namespace },
+ ]);
+ expectClientCallArgsAction([obj1, obj2], { method: 'update', getId });
});
it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => {
- const getId = (type, id) => `${type}:${id}`;
+ const getId = (type, id) => `${type}:${id}`; // test that the raw document ID equals this (e.g., does not have a namespace prefix)
await bulkUpdateSuccess([obj1, obj2]);
expectClientCallArgsAction([obj1, obj2], { method: 'update', getId });
+
+ jest.clearAllMocks();
+ // test again with object namespace string that supersedes the operation's namespace ID
+ await bulkUpdateSuccess(
+ [
+ { ...obj1, namespace: 'default' },
+ { ...obj2, namespace: 'default' },
+ ],
+ { namespace }
+ );
+ expectClientCallArgsAction([obj1, obj2], { method: 'update', getId });
});
- it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => {
+ it(`normalizes options.namespace from 'default' to undefined`, async () => {
const getId = (type, id) => `${type}:${id}`;
- const objects1 = [{ ...obj1, type: NAMESPACE_AGNOSTIC_TYPE }];
- await bulkUpdateSuccess(objects1, { namespace });
- expectClientCallArgsAction(objects1, { method: 'update', getId });
- client.bulk.mockClear();
+ await bulkUpdateSuccess([obj1, obj2], { namespace: 'default' });
+ expectClientCallArgsAction([obj1, obj2], { method: 'update', getId });
+ });
+
+ it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => {
+ const getId = (type, id) => `${type}:${id}`; // test that the raw document ID equals this (e.g., does not have a namespace prefix)
const overrides = {
// bulkUpdate uses a preflight `get` request for multi-namespace saved objects, and specifies that version on `update`
// we aren't testing for this here, but we need to include Jest assertions so this test doesn't fail
if_primary_term: expect.any(Number),
if_seq_no: expect.any(Number),
};
- const objects2 = [{ ...obj2, type: MULTI_NAMESPACE_TYPE }];
- await bulkUpdateSuccess(objects2, { namespace });
- expectClientCallArgsAction(objects2, { method: 'update', getId, overrides }, 2);
+ const _obj1 = { ...obj1, type: NAMESPACE_AGNOSTIC_TYPE };
+ const _obj2 = { ...obj2, type: MULTI_NAMESPACE_TYPE };
+
+ await bulkUpdateSuccess([_obj1], { namespace });
+ expectClientCallArgsAction([_obj1], { method: 'update', getId });
+ client.bulk.mockClear();
+ await bulkUpdateSuccess([_obj2], { namespace });
+ expectClientCallArgsAction([_obj2], { method: 'update', getId, overrides }, 2);
+
+ jest.clearAllMocks();
+ // test again with object namespace string that supersedes the operation's namespace ID
+ await bulkUpdateSuccess([{ ..._obj1, namespace }]);
+ expectClientCallArgsAction([_obj1], { method: 'update', getId });
+ client.bulk.mockClear();
+ await bulkUpdateSuccess([{ ..._obj2, namespace }]);
+ expectClientCallArgsAction([_obj2], { method: 'update', getId, overrides }, 2);
});
});
@@ -1582,19 +1637,25 @@ describe('SavedObjectsRepository', () => {
});
it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => {
- const getId = (type, id) => `${namespace}:${type}:${id}`;
+ const getId = (type, id) => `${namespace}:${type}:${id}`; // test that the raw document ID equals this (e.g., has a namespace prefix)
await checkConflictsSuccess([obj1, obj2], { namespace });
_expectClientCallArgs([obj1, obj2], { getId });
});
it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => {
- const getId = (type, id) => `${type}:${id}`;
+ const getId = (type, id) => `${type}:${id}`; // test that the raw document ID equals this (e.g., does not have a namespace prefix)
await checkConflictsSuccess([obj1, obj2]);
_expectClientCallArgs([obj1, obj2], { getId });
});
+ it(`normalizes options.namespace from 'default' to undefined`, async () => {
+ const getId = (type, id) => `${type}:${id}`; // test that the raw document ID equals this (e.g., does not have a namespace prefix)
+ await checkConflictsSuccess([obj1, obj2], { namespace: 'default' });
+ _expectClientCallArgs([obj1, obj2], { getId });
+ });
+
it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => {
- const getId = (type, id) => `${type}:${id}`;
+ const getId = (type, id) => `${type}:${id}`; // test that the raw document ID equals this (e.g., does not have a namespace prefix)
// obj3 is multi-namespace, and obj6 is namespace-agnostic
await checkConflictsSuccess([obj3, obj6], { namespace });
_expectClientCallArgs([obj3, obj6], { getId });
@@ -1817,6 +1878,16 @@ describe('SavedObjectsRepository', () => {
);
});
+ it(`normalizes options.namespace from 'default' to undefined`, async () => {
+ await createSuccess(type, attributes, { id, namespace: 'default' });
+ expect(client.create).toHaveBeenCalledWith(
+ expect.objectContaining({
+ id: `${type}:${id}`,
+ }),
+ expect.anything()
+ );
+ });
+
it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => {
await createSuccess(NAMESPACE_AGNOSTIC_TYPE, attributes, { id, namespace });
expect(client.create).toHaveBeenCalledWith(
@@ -1853,11 +1924,7 @@ describe('SavedObjectsRepository', () => {
});
it(`throws when there is a conflict with an existing multi-namespace saved object (get)`, async () => {
- const response = getMockGetResponse({
- type: MULTI_NAMESPACE_TYPE,
- id,
- namespace: 'bar-namespace',
- });
+ const response = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id }, 'bar-namespace');
client.get.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise(response)
);
@@ -1960,7 +2027,7 @@ describe('SavedObjectsRepository', () => {
const deleteSuccess = async (type, id, options) => {
if (registry.isMultiNamespace(type)) {
- const mockGetResponse = getMockGetResponse({ type, id, namespace: options?.namespace });
+ const mockGetResponse = getMockGetResponse({ type, id }, options?.namespace);
client.get.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise(mockGetResponse)
);
@@ -2036,6 +2103,14 @@ describe('SavedObjectsRepository', () => {
);
});
+ it(`normalizes options.namespace from 'default' to undefined`, async () => {
+ await deleteSuccess(type, id, { namespace: 'default' });
+ expect(client.delete).toHaveBeenCalledWith(
+ expect.objectContaining({ id: `${type}:${id}` }),
+ expect.anything()
+ );
+ });
+
it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => {
await deleteSuccess(NAMESPACE_AGNOSTIC_TYPE, id, { namespace });
expect(client.delete).toHaveBeenCalledWith(
@@ -2086,7 +2161,7 @@ describe('SavedObjectsRepository', () => {
});
it(`throws when the type is multi-namespace and the document exists, but not in this namespace`, async () => {
- const response = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id, namespace });
+ const response = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id }, namespace);
client.get.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise(response)
);
@@ -2661,14 +2736,16 @@ describe('SavedObjectsRepository', () => {
const originId = 'some-origin-id';
const getSuccess = async (type, id, options, includeOriginId) => {
- const response = getMockGetResponse({
- type,
- id,
- namespace: options?.namespace,
- // "includeOriginId" is not an option for the operation; however, if the existing saved object contains an originId attribute, the
- // operation will return it in the result. This flag is just used for test purposes to modify the mock cluster call response.
- ...(includeOriginId && { originId }),
- });
+ const response = getMockGetResponse(
+ {
+ type,
+ id,
+ // "includeOriginId" is not an option for the operation; however, if the existing saved object contains an originId attribute, the
+ // operation will return it in the result. This flag is just used for test purposes to modify the mock cluster call response.
+ ...(includeOriginId && { originId }),
+ },
+ options?.namespace
+ );
client.get.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise(response)
);
@@ -2703,6 +2780,16 @@ describe('SavedObjectsRepository', () => {
);
});
+ it(`normalizes options.namespace from 'default' to undefined`, async () => {
+ await getSuccess(type, id, { namespace: 'default' });
+ expect(client.get).toHaveBeenCalledWith(
+ expect.objectContaining({
+ id: `${type}:${id}`,
+ }),
+ expect.anything()
+ );
+ });
+
it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => {
await getSuccess(NAMESPACE_AGNOSTIC_TYPE, id, { namespace });
expect(client.get).toHaveBeenCalledWith(
@@ -2757,7 +2844,7 @@ describe('SavedObjectsRepository', () => {
});
it(`throws when type is multi-namespace and the document exists, but not in this namespace`, async () => {
- const response = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id, namespace });
+ const response = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id }, namespace);
client.get.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise(response)
);
@@ -2813,7 +2900,7 @@ describe('SavedObjectsRepository', () => {
const incrementCounterSuccess = async (type, id, field, options) => {
const isMultiNamespace = registry.isMultiNamespace(type);
if (isMultiNamespace) {
- const response = getMockGetResponse({ type, id, namespace: options?.namespace });
+ const response = getMockGetResponse({ type, id }, options?.namespace);
client.get.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise(response)
);
@@ -2884,6 +2971,16 @@ describe('SavedObjectsRepository', () => {
);
});
+ it(`normalizes options.namespace from 'default' to undefined`, async () => {
+ await incrementCounterSuccess(type, id, field, { namespace: 'default' });
+ expect(client.update).toHaveBeenCalledWith(
+ expect.objectContaining({
+ id: `${type}:${id}`,
+ }),
+ expect.anything()
+ );
+ });
+
it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => {
await incrementCounterSuccess(NAMESPACE_AGNOSTIC_TYPE, id, field, { namespace });
expect(client.update).toHaveBeenCalledWith(
@@ -2950,11 +3047,7 @@ describe('SavedObjectsRepository', () => {
});
it(`throws when there is a conflict with an existing multi-namespace saved object (get)`, async () => {
- const response = getMockGetResponse({
- type: MULTI_NAMESPACE_TYPE,
- id,
- namespace: 'bar-namespace',
- });
+ const response = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id }, 'bar-namespace');
client.get.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise(response)
);
@@ -3247,7 +3340,7 @@ describe('SavedObjectsRepository', () => {
expect(client.update).not.toHaveBeenCalled();
});
- it(`throws when type is not namespace-agnostic`, async () => {
+ it(`throws when type is not multi-namespace`, async () => {
const test = async (type) => {
const message = `${type} doesn't support multiple namespaces`;
await expectBadRequestError(type, id, [namespace1, namespace2], message);
@@ -3389,7 +3482,7 @@ describe('SavedObjectsRepository', () => {
const updateSuccess = async (type, id, attributes, options, includeOriginId) => {
if (registry.isMultiNamespace(type)) {
- const mockGetResponse = getMockGetResponse({ type, id, namespace: options?.namespace });
+ const mockGetResponse = getMockGetResponse({ type, id }, options?.namespace);
client.get.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise(mockGetResponse)
);
@@ -3520,6 +3613,14 @@ describe('SavedObjectsRepository', () => {
);
});
+ it(`normalizes options.namespace from 'default' to undefined`, async () => {
+ await updateSuccess(type, id, attributes, { references, namespace: 'default' });
+ expect(client.update).toHaveBeenCalledWith(
+ expect.objectContaining({ id: expect.stringMatching(`${type}:${id}`) }),
+ expect.anything()
+ );
+ });
+
it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => {
await updateSuccess(NAMESPACE_AGNOSTIC_TYPE, id, attributes, { namespace });
expect(client.update).toHaveBeenCalledWith(
@@ -3590,7 +3691,7 @@ describe('SavedObjectsRepository', () => {
});
it(`throws when type is multi-namespace and the document exists, but not in this namespace`, async () => {
- const response = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id, namespace });
+ const response = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id }, namespace);
client.get.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise(response)
);
diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts
index dd25989725f3e..125f97e7feb11 100644
--- a/src/core/server/saved_objects/service/lib/repository.ts
+++ b/src/core/server/saved_objects/service/lib/repository.ts
@@ -31,7 +31,7 @@ import { getSearchDsl } from './search_dsl';
import { includedFields } from './included_fields';
import { SavedObjectsErrorHelpers, DecoratedError } from './errors';
import { decodeRequestVersion, encodeVersion, encodeHitVersion } from '../../version';
-import { KibanaMigrator } from '../../migrations';
+import { IKibanaMigrator } from '../../migrations';
import {
SavedObjectsSerializer,
SavedObjectSanitizedDoc,
@@ -67,6 +67,7 @@ import {
} from '../../types';
import { SavedObjectTypeRegistry } from '../../saved_objects_type_registry';
import { validateConvertFilterToKueryNode } from './filter_utils';
+import { SavedObjectsUtils } from './utils';
// BEWARE: The SavedObjectClient depends on the implementation details of the SavedObjectsRepository
// so any breaking changes to this repository are considered breaking changes to the SavedObjectsClient.
@@ -85,7 +86,7 @@ export interface SavedObjectsRepositoryOptions {
client: ElasticsearchClient;
typeRegistry: SavedObjectTypeRegistry;
serializer: SavedObjectsSerializer;
- migrator: KibanaMigrator;
+ migrator: IKibanaMigrator;
allowedTypes: string[];
}
@@ -120,7 +121,7 @@ export type ISavedObjectsRepository = Pick>,
options: SavedObjectsCreateOptions = {}
): Promise> {
- const { namespace, overwrite = false, refresh = DEFAULT_REFRESH_SETTING } = options;
+ const { overwrite = false, refresh = DEFAULT_REFRESH_SETTING } = options;
+ const namespace = normalizeNamespace(options.namespace);
const time = this._getCurrentTime();
let bulkGetRequestIndexCounter = 0;
@@ -468,7 +470,7 @@ export class SavedObjectsRepository {
return { errors: [] };
}
- const { namespace } = options;
+ const namespace = normalizeNamespace(options.namespace);
let bulkGetRequestIndexCounter = 0;
const expectedBulkGetResults: Either[] = objects.map((object) => {
@@ -551,7 +553,8 @@ export class SavedObjectsRepository {
throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id);
}
- const { namespace, refresh = DEFAULT_REFRESH_SETTING } = options;
+ const { refresh = DEFAULT_REFRESH_SETTING } = options;
+ const namespace = normalizeNamespace(options.namespace);
const rawId = this._serializer.generateRawId(namespace, type, id);
let preflightResult: SavedObjectsRawDoc | undefined;
@@ -560,7 +563,7 @@ export class SavedObjectsRepository {
preflightResult = await this.preflightCheckIncludesNamespace(type, id, namespace);
const existingNamespaces = getSavedObjectNamespaces(undefined, preflightResult);
const remainingNamespaces = existingNamespaces?.filter(
- (x) => x !== getNamespaceString(namespace)
+ (x) => x !== SavedObjectsUtils.namespaceIdToString(namespace)
);
if (remainingNamespaces?.length) {
@@ -658,7 +661,7 @@ export class SavedObjectsRepository {
}
`,
lang: 'painless',
- params: { namespace: getNamespaceString(namespace) },
+ params: { namespace },
},
conflicts: 'proceed',
...getSearchDsl(this._mappings, this._registry, {
@@ -814,7 +817,7 @@ export class SavedObjectsRepository {
objects: SavedObjectsBulkGetObject[] = [],
options: SavedObjectsBaseOptions = {}
): Promise> {
- const { namespace } = options;
+ const namespace = normalizeNamespace(options.namespace);
if (objects.length === 0) {
return { saved_objects: [] };
@@ -884,7 +887,9 @@ export class SavedObjectsRepository {
const { originId, updated_at: updatedAt } = doc._source;
let namespaces = [];
if (!this._registry.isNamespaceAgnostic(type)) {
- namespaces = doc._source.namespaces ?? [getNamespaceString(doc._source.namespace)];
+ namespaces = doc._source.namespaces ?? [
+ SavedObjectsUtils.namespaceIdToString(doc._source.namespace),
+ ];
}
return {
@@ -920,7 +925,7 @@ export class SavedObjectsRepository {
throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id);
}
- const { namespace } = options;
+ const namespace = normalizeNamespace(options.namespace);
const { body, statusCode } = await this.client.get>(
{
@@ -941,7 +946,9 @@ export class SavedObjectsRepository {
let namespaces: string[] = [];
if (!this._registry.isNamespaceAgnostic(type)) {
- namespaces = body._source.namespaces ?? [getNamespaceString(body._source.namespace)];
+ namespaces = body._source.namespaces ?? [
+ SavedObjectsUtils.namespaceIdToString(body._source.namespace),
+ ];
}
return {
@@ -978,7 +985,8 @@ export class SavedObjectsRepository {
throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id);
}
- const { version, namespace, references, refresh = DEFAULT_REFRESH_SETTING } = options;
+ const { version, references, refresh = DEFAULT_REFRESH_SETTING } = options;
+ const namespace = normalizeNamespace(options.namespace);
let preflightResult: SavedObjectsRawDoc | undefined;
if (this._registry.isMultiNamespace(type)) {
@@ -1016,7 +1024,9 @@ export class SavedObjectsRepository {
const { originId } = body.get._source;
let namespaces = [];
if (!this._registry.isNamespaceAgnostic(type)) {
- namespaces = body.get._source.namespaces ?? [getNamespaceString(body.get._source.namespace)];
+ namespaces = body.get._source.namespaces ?? [
+ SavedObjectsUtils.namespaceIdToString(body.get._source.namespace),
+ ];
}
return {
@@ -1060,6 +1070,7 @@ export class SavedObjectsRepository {
}
const { version, namespace, refresh = DEFAULT_REFRESH_SETTING } = options;
+ // we do not need to normalize the namespace to its ID format, since it will be converted to a namespace string before being used
const rawId = this._serializer.generateRawId(undefined, type, id);
const preflightResult = await this.preflightCheckIncludesNamespace(type, id, namespace);
@@ -1122,6 +1133,7 @@ export class SavedObjectsRepository {
}
const { namespace, refresh = DEFAULT_REFRESH_SETTING } = options;
+ // we do not need to normalize the namespace to its ID format, since it will be converted to a namespace string before being used
const rawId = this._serializer.generateRawId(undefined, type, id);
const preflightResult = await this.preflightCheckIncludesNamespace(type, id, namespace);
@@ -1208,7 +1220,7 @@ export class SavedObjectsRepository {
options: SavedObjectsBulkUpdateOptions = {}
): Promise> {
const time = this._getCurrentTime();
- const { namespace } = options;
+ const namespace = normalizeNamespace(options.namespace);
let bulkGetRequestIndexCounter = 0;
const expectedBulkGetResults: Either[] = objects.map((object) => {
@@ -1225,7 +1237,9 @@ export class SavedObjectsRepository {
};
}
- const { attributes, references, version } = object;
+ const { attributes, references, version, namespace: objectNamespace } = object;
+ // `objectNamespace` is a namespace string, while `namespace` is a namespace ID.
+ // The object namespace string, if defined, will supersede the operation's namespace ID.
const documentToSave = {
[type]: attributes,
@@ -1242,16 +1256,24 @@ export class SavedObjectsRepository {
id,
version,
documentToSave,
+ objectNamespace,
...(requiresNamespacesCheck && { esRequestIndex: bulkGetRequestIndexCounter++ }),
},
};
});
+ const getNamespaceId = (objectNamespace?: string) =>
+ objectNamespace !== undefined
+ ? SavedObjectsUtils.namespaceStringToId(objectNamespace)
+ : namespace;
+ const getNamespaceString = (objectNamespace?: string) =>
+ objectNamespace ?? SavedObjectsUtils.namespaceIdToString(namespace);
+
const bulkGetDocs = expectedBulkGetResults
.filter(isRight)
.filter(({ value }) => value.esRequestIndex !== undefined)
- .map(({ value: { type, id } }) => ({
- _id: this._serializer.generateRawId(namespace, type, id),
+ .map(({ value: { type, id, objectNamespace } }) => ({
+ _id: this._serializer.generateRawId(getNamespaceId(objectNamespace), type, id),
_index: this.getIndexForType(type),
_source: ['type', 'namespaces'],
}));
@@ -1276,14 +1298,25 @@ export class SavedObjectsRepository {
return expectedBulkGetResult;
}
- const { esRequestIndex, id, type, version, documentToSave } = expectedBulkGetResult.value;
+ const {
+ esRequestIndex,
+ id,
+ type,
+ version,
+ documentToSave,
+ objectNamespace,
+ } = expectedBulkGetResult.value;
+
let namespaces;
let versionProperties;
if (esRequestIndex !== undefined) {
const indexFound = bulkGetResponse?.statusCode !== 404;
const actualResult = indexFound ? bulkGetResponse?.body.docs[esRequestIndex] : undefined;
const docFound = indexFound && actualResult.found === true;
- if (!docFound || !this.rawDocExistsInNamespace(actualResult, namespace)) {
+ if (
+ !docFound ||
+ !this.rawDocExistsInNamespace(actualResult, getNamespaceId(objectNamespace))
+ ) {
return {
tag: 'Left' as 'Left',
error: {
@@ -1294,12 +1327,13 @@ export class SavedObjectsRepository {
};
}
namespaces = actualResult._source.namespaces ?? [
- getNamespaceString(actualResult._source.namespace),
+ SavedObjectsUtils.namespaceIdToString(actualResult._source.namespace),
];
versionProperties = getExpectedVersionProperties(version, actualResult);
} else {
if (this._registry.isSingleNamespace(type)) {
- namespaces = [getNamespaceString(namespace)];
+ // if `objectNamespace` is undefined, fall back to `options.namespace`
+ namespaces = [getNamespaceString(objectNamespace)];
}
versionProperties = getExpectedVersionProperties(version);
}
@@ -1315,7 +1349,7 @@ export class SavedObjectsRepository {
bulkUpdateParams.push(
{
update: {
- _id: this._serializer.generateRawId(namespace, type, id),
+ _id: this._serializer.generateRawId(getNamespaceId(objectNamespace), type, id),
_index: this.getIndexForType(type),
...versionProperties,
},
@@ -1401,7 +1435,8 @@ export class SavedObjectsRepository {
throw SavedObjectsErrorHelpers.createUnsupportedTypeError(type);
}
- const { migrationVersion, namespace, refresh = DEFAULT_REFRESH_SETTING } = options;
+ const { migrationVersion, refresh = DEFAULT_REFRESH_SETTING } = options;
+ const namespace = normalizeNamespace(options.namespace);
const time = this._getCurrentTime();
let savedObjectNamespace;
@@ -1495,7 +1530,7 @@ export class SavedObjectsRepository {
const savedObject = this._serializer.rawToSavedObject(raw);
const { namespace, type } = savedObject;
if (this._registry.isSingleNamespace(type)) {
- savedObject.namespaces = [getNamespaceString(namespace)];
+ savedObject.namespaces = [SavedObjectsUtils.namespaceIdToString(namespace)];
}
return omit(savedObject, 'namespace') as SavedObject;
}
@@ -1518,7 +1553,7 @@ export class SavedObjectsRepository {
}
const namespaces = raw._source.namespaces;
- return namespaces?.includes(getNamespaceString(namespace)) ?? false;
+ return namespaces?.includes(SavedObjectsUtils.namespaceIdToString(namespace)) ?? false;
}
/**
@@ -1623,14 +1658,6 @@ function getExpectedVersionProperties(version?: string, document?: SavedObjectsR
return {};
}
-/**
- * Returns the string representation of a namespace.
- * The default namespace is undefined, and is represented by the string 'default'.
- */
-function getNamespaceString(namespace?: string) {
- return namespace ?? 'default';
-}
-
/**
* Returns a string array of namespaces for a given saved object. If the saved object is undefined, the result is an array that contains the
* current namespace. Value may be undefined if an existing saved object has no namespaces attribute; this should not happen in normal
@@ -1646,9 +1673,16 @@ function getSavedObjectNamespaces(
if (document) {
return document._source?.namespaces;
}
- return [getNamespaceString(namespace)];
+ return [SavedObjectsUtils.namespaceIdToString(namespace)];
}
+/**
+ * Ensure that a namespace is always in its namespace ID representation.
+ * This allows `'default'` to be used interchangeably with `undefined`.
+ */
+const normalizeNamespace = (namespace?: string) =>
+ namespace === undefined ? namespace : SavedObjectsUtils.namespaceStringToId(namespace);
+
/**
* Extracts the contents of a decorated error to return the attributes for bulk operations.
*/
diff --git a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts
index ad1a08187dc32..3ff72a86c2f89 100644
--- a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts
+++ b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts
@@ -21,6 +21,7 @@ import { esKuery, KueryNode } from '../../../../../../plugins/data/server';
import { getRootPropertiesObjects, IndexMapping } from '../../../mappings';
import { ISavedObjectTypeRegistry } from '../../../saved_objects_type_registry';
+import { DEFAULT_NAMESPACE_STRING } from '../utils';
/**
* Gets the types based on the type. Uses mappings to support
@@ -73,7 +74,7 @@ function getFieldsForTypes(
*/
function getClauseForType(
registry: ISavedObjectTypeRegistry,
- namespaces: string[] = ['default'],
+ namespaces: string[] = [DEFAULT_NAMESPACE_STRING],
type: string
) {
if (namespaces.length === 0) {
@@ -88,11 +89,11 @@ function getClauseForType(
};
} else if (registry.isSingleNamespace(type)) {
const should: Array> = [];
- const eligibleNamespaces = namespaces.filter((namespace) => namespace !== 'default');
+ const eligibleNamespaces = namespaces.filter((x) => x !== DEFAULT_NAMESPACE_STRING);
if (eligibleNamespaces.length > 0) {
should.push({ terms: { namespace: eligibleNamespaces } });
}
- if (namespaces.includes('default')) {
+ if (namespaces.includes(DEFAULT_NAMESPACE_STRING)) {
should.push({ bool: { must_not: [{ exists: { field: 'namespace' } }] } });
}
if (should.length === 0) {
@@ -162,9 +163,7 @@ export function getQueryParams({
// would result in no results being returned, as the wildcard is treated as a literal, and not _actually_ as a wildcard.
// We had a good discussion around the tradeoffs here: https://github.com/elastic/kibana/pull/67644#discussion_r441055716
const normalizedNamespaces = namespaces
- ? Array.from(
- new Set(namespaces.map((namespace) => (namespace === '*' ? 'default' : namespace)))
- )
+ ? Array.from(new Set(namespaces.map((x) => (x === '*' ? DEFAULT_NAMESPACE_STRING : x))))
: undefined;
const bool: any = {
diff --git a/src/core/server/saved_objects/service/lib/utils.test.ts b/src/core/server/saved_objects/service/lib/utils.test.ts
new file mode 100644
index 0000000000000..ea4fa68242bea
--- /dev/null
+++ b/src/core/server/saved_objects/service/lib/utils.test.ts
@@ -0,0 +1,57 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { SavedObjectsUtils } from './utils';
+
+describe('SavedObjectsUtils', () => {
+ const { namespaceIdToString, namespaceStringToId } = SavedObjectsUtils;
+
+ describe('#namespaceIdToString', () => {
+ it('converts `undefined` to default namespace string', () => {
+ expect(namespaceIdToString(undefined)).toEqual('default');
+ });
+
+ it('leaves other namespace IDs as-is', () => {
+ expect(namespaceIdToString('foo')).toEqual('foo');
+ });
+
+ it('throws an error when a namespace ID is an empty string', () => {
+ expect(() => namespaceIdToString('')).toThrowError('namespace cannot be an empty string');
+ });
+ });
+
+ describe('#namespaceStringToId', () => {
+ it('converts default namespace string to `undefined`', () => {
+ expect(namespaceStringToId('default')).toBeUndefined();
+ });
+
+ it('leaves other namespace strings as-is', () => {
+ expect(namespaceStringToId('foo')).toEqual('foo');
+ });
+
+ it('throws an error when a namespace string is falsy', () => {
+ const test = (arg: any) =>
+ expect(() => namespaceStringToId(arg)).toThrowError('namespace must be a non-empty string');
+
+ test(undefined);
+ test(null);
+ test('');
+ });
+ });
+});
diff --git a/src/core/server/saved_objects/service/lib/utils.ts b/src/core/server/saved_objects/service/lib/utils.ts
new file mode 100644
index 0000000000000..6101ad57cc401
--- /dev/null
+++ b/src/core/server/saved_objects/service/lib/utils.ts
@@ -0,0 +1,53 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+export const DEFAULT_NAMESPACE_STRING = 'default';
+
+/**
+ * @public
+ */
+export class SavedObjectsUtils {
+ /**
+ * Converts a given saved object namespace ID to its string representation. All namespace IDs have an identical string representation, with
+ * the exception of the `undefined` namespace ID (which has a namespace string of `'default'`).
+ *
+ * @param namespace The namespace ID, which must be either a non-empty string or `undefined`.
+ */
+ public static namespaceIdToString = (namespace?: string) => {
+ if (namespace === '') {
+ throw new TypeError('namespace cannot be an empty string');
+ }
+
+ return namespace ?? DEFAULT_NAMESPACE_STRING;
+ };
+
+ /**
+ * Converts a given saved object namespace string to its ID representation. All namespace strings have an identical ID representation, with
+ * the exception of the `'default'` namespace string (which has a namespace ID of `undefined`).
+ *
+ * @param namespace The namespace string, which must be non-empty.
+ */
+ public static namespaceStringToId = (namespace: string) => {
+ if (!namespace) {
+ throw new TypeError('namespace must be a non-empty string');
+ }
+
+ return namespace !== DEFAULT_NAMESPACE_STRING ? namespace : undefined;
+ };
+}
diff --git a/src/core/server/saved_objects/service/saved_objects_client.ts b/src/core/server/saved_objects/service/saved_objects_client.ts
index 347c760f841bc..8c96116de49cb 100644
--- a/src/core/server/saved_objects/service/saved_objects_client.ts
+++ b/src/core/server/saved_objects/service/saved_objects_client.ts
@@ -80,6 +80,13 @@ export interface SavedObjectsBulkUpdateObject
type: string;
/** {@inheritdoc SavedObjectAttributes} */
attributes: Partial;
+ /**
+ * Optional namespace string to use when searching for this object. If this is defined, it will supersede the namespace ID that is in
+ * {@link SavedObjectsBulkUpdateOptions}.
+ *
+ * Note: the default namespace's string representation is `'default'`, and its ID representation is `undefined`.
+ **/
+ namespace?: string;
}
/**
diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts
index 000153cd542fa..50c118ca64ffb 100644
--- a/src/core/server/saved_objects/types.ts
+++ b/src/core/server/saved_objects/types.ts
@@ -18,9 +18,8 @@
*/
import { SavedObjectsClient } from './service/saved_objects_client';
-import { SavedObjectsTypeMappingDefinition, SavedObjectsTypeMappingDefinitions } from './mappings';
+import { SavedObjectsTypeMappingDefinition } from './mappings';
import { SavedObjectMigrationMap } from './migrations';
-import { PropertyValidators } from './validation';
export {
SavedObjectsImportResponse,
@@ -34,9 +33,6 @@ export {
SavedObjectsImportRetry,
} from './import/types';
-import { LegacyConfig } from '../legacy';
-import { SavedObjectUnsanitizedDoc } from './serialization';
-import { SavedObjectsMigrationLogger } from './migrations/core/migration_logger';
import { SavedObject } from '../../types';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
@@ -269,92 +265,3 @@ export interface SavedObjectsTypeManagementDefinition {
*/
getInAppUrl?: (savedObject: SavedObject) => { path: string; uiCapabilitiesPath: string };
}
-
-/**
- * @internal
- * @deprecated
- */
-export interface SavedObjectsLegacyUiExports {
- savedObjectMappings: SavedObjectsLegacyMapping[];
- savedObjectMigrations: SavedObjectsLegacyMigrationDefinitions;
- savedObjectSchemas: SavedObjectsLegacySchemaDefinitions;
- savedObjectValidations: PropertyValidators;
- savedObjectsManagement: SavedObjectsLegacyManagementDefinition;
-}
-
-/**
- * @internal
- * @deprecated
- */
-export interface SavedObjectsLegacyMapping {
- pluginId: string;
- properties: SavedObjectsTypeMappingDefinitions;
-}
-
-/**
- * @internal
- * @deprecated Use {@link SavedObjectsTypeManagementDefinition | management definition} when registering
- * from new platform plugins
- */
-export interface SavedObjectsLegacyManagementDefinition {
- [key: string]: SavedObjectsLegacyManagementTypeDefinition;
-}
-
-/**
- * @internal
- * @deprecated
- */
-export interface SavedObjectsLegacyManagementTypeDefinition {
- isImportableAndExportable?: boolean;
- defaultSearchField?: string;
- icon?: string;
- getTitle?: (savedObject: SavedObject) => string;
- getEditUrl?: (savedObject: SavedObject) => string;
- getInAppUrl?: (savedObject: SavedObject) => { path: string; uiCapabilitiesPath: string };
-}
-
-/**
- * @internal
- * @deprecated
- */
-export interface SavedObjectsLegacyMigrationDefinitions {
- [type: string]: SavedObjectLegacyMigrationMap;
-}
-
-/**
- * @internal
- * @deprecated
- */
-export interface SavedObjectLegacyMigrationMap {
- [version: string]: SavedObjectLegacyMigrationFn;
-}
-
-/**
- * @internal
- * @deprecated
- */
-export type SavedObjectLegacyMigrationFn = (
- doc: SavedObjectUnsanitizedDoc,
- log: SavedObjectsMigrationLogger
-) => SavedObjectUnsanitizedDoc;
-
-/**
- * @internal
- * @deprecated
- */
-interface SavedObjectsLegacyTypeSchema {
- isNamespaceAgnostic?: boolean;
- /** Cannot be used in conjunction with `isNamespaceAgnostic` */
- multiNamespace?: boolean;
- hidden?: boolean;
- indexPattern?: ((config: LegacyConfig) => string) | string;
- convertToAliasScript?: string;
-}
-
-/**
- * @internal
- * @deprecated
- */
-export interface SavedObjectsLegacySchemaDefinitions {
- [type: string]: SavedObjectsLegacyTypeSchema;
-}
diff --git a/src/core/server/saved_objects/utils.test.ts b/src/core/server/saved_objects/utils.test.ts
deleted file mode 100644
index 21229bee489c2..0000000000000
--- a/src/core/server/saved_objects/utils.test.ts
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { legacyServiceMock } from '../legacy/legacy_service.mock';
-import { convertLegacyTypes, convertTypesToLegacySchema } from './utils';
-import { SavedObjectsLegacyUiExports, SavedObjectsType } from './types';
-import { LegacyConfig, SavedObjectMigrationContext } from 'kibana/server';
-import { SavedObjectUnsanitizedDoc } from './serialization';
-
-describe('convertLegacyTypes', () => {
- let legacyConfig: ReturnType;
-
- beforeEach(() => {
- legacyConfig = legacyServiceMock.createLegacyConfig();
- });
-
- it('converts the legacy mappings using default values if no schemas are specified', () => {
- const uiExports: SavedObjectsLegacyUiExports = {
- savedObjectMappings: [
- {
- pluginId: 'pluginA',
- properties: {
- typeA: {
- properties: {
- fieldA: { type: 'text' },
- },
- },
- typeB: {
- properties: {
- fieldB: { type: 'text' },
- },
- },
- },
- },
- {
- pluginId: 'pluginB',
- properties: {
- typeC: {
- properties: {
- fieldC: { type: 'text' },
- },
- },
- },
- },
- ],
- savedObjectMigrations: {},
- savedObjectSchemas: {},
- savedObjectValidations: {},
- savedObjectsManagement: {},
- };
-
- const converted = convertLegacyTypes(uiExports, legacyConfig);
- expect(converted).toMatchSnapshot();
- });
-
- it('merges the mappings and the schema to create the type when schema exists for the type', () => {
- const uiExports: SavedObjectsLegacyUiExports = {
- savedObjectMappings: [
- {
- pluginId: 'pluginA',
- properties: {
- typeA: {
- properties: {
- fieldA: { type: 'text' },
- },
- },
- },
- },
- {
- pluginId: 'pluginB',
- properties: {
- typeB: {
- properties: {
- fieldB: { type: 'text' },
- },
- },
- },
- },
- {
- pluginId: 'pluginC',
- properties: {
- typeC: {
- properties: {
- fieldC: { type: 'text' },
- },
- },
- },
- },
- {
- pluginId: 'pluginD',
- properties: {
- typeD: {
- properties: {
- fieldD: { type: 'text' },
- },
- },
- },
- },
- ],
- savedObjectMigrations: {},
- savedObjectSchemas: {
- typeA: {
- indexPattern: 'fooBar',
- hidden: true,
- isNamespaceAgnostic: true,
- },
- typeB: {
- indexPattern: 'barBaz',
- hidden: false,
- multiNamespace: true,
- },
- typeD: {
- indexPattern: 'bazQux',
- hidden: false,
- // if both isNamespaceAgnostic and multiNamespace are true, the resulting namespaceType is 'agnostic'
- isNamespaceAgnostic: true,
- multiNamespace: true,
- },
- },
- savedObjectValidations: {},
- savedObjectsManagement: {},
- };
-
- const converted = convertLegacyTypes(uiExports, legacyConfig);
- expect(converted).toMatchSnapshot();
- });
-
- it('invokes indexPattern to retrieve the index when it is a function', () => {
- const indexPatternAccessor: (config: LegacyConfig) => string = jest.fn((config) => {
- config.get('foo.bar');
- return 'myIndex';
- });
-
- const uiExports: SavedObjectsLegacyUiExports = {
- savedObjectMappings: [
- {
- pluginId: 'pluginA',
- properties: {
- typeA: {
- properties: {
- fieldA: { type: 'text' },
- },
- },
- },
- },
- ],
- savedObjectMigrations: {},
- savedObjectSchemas: {
- typeA: {
- indexPattern: indexPatternAccessor,
- hidden: true,
- isNamespaceAgnostic: true,
- },
- },
- savedObjectValidations: {},
- savedObjectsManagement: {},
- };
-
- const converted = convertLegacyTypes(uiExports, legacyConfig);
-
- expect(indexPatternAccessor).toHaveBeenCalledWith(legacyConfig);
- expect(legacyConfig.get).toHaveBeenCalledWith('foo.bar');
- expect(converted.length).toEqual(1);
- expect(converted[0].indexPattern).toEqual('myIndex');
- });
-
- it('import migrations from the uiExports', () => {
- const migrationsA = {
- '1.0.0': jest.fn(),
- '2.0.4': jest.fn(),
- };
- const migrationsB = {
- '1.5.3': jest.fn(),
- };
-
- const uiExports: SavedObjectsLegacyUiExports = {
- savedObjectMappings: [
- {
- pluginId: 'pluginA',
- properties: {
- typeA: {
- properties: {
- fieldA: { type: 'text' },
- },
- },
- },
- },
- {
- pluginId: 'pluginB',
- properties: {
- typeB: {
- properties: {
- fieldC: { type: 'text' },
- },
- },
- },
- },
- ],
- savedObjectMigrations: {
- typeA: migrationsA,
- typeB: migrationsB,
- },
- savedObjectSchemas: {},
- savedObjectValidations: {},
- savedObjectsManagement: {},
- };
-
- const converted = convertLegacyTypes(uiExports, legacyConfig);
- expect(converted.length).toEqual(2);
- expect(Object.keys(converted[0]!.migrations!)).toEqual(Object.keys(migrationsA));
- expect(Object.keys(converted[1]!.migrations!)).toEqual(Object.keys(migrationsB));
- });
-
- it('converts the migration to the new format', () => {
- const legacyMigration = jest.fn();
- const migrationsA = {
- '1.0.0': legacyMigration,
- };
-
- const uiExports: SavedObjectsLegacyUiExports = {
- savedObjectMappings: [
- {
- pluginId: 'pluginA',
- properties: {
- typeA: {
- properties: {
- fieldA: { type: 'text' },
- },
- },
- },
- },
- ],
- savedObjectMigrations: {
- typeA: migrationsA,
- },
- savedObjectSchemas: {},
- savedObjectValidations: {},
- savedObjectsManagement: {},
- };
-
- const converted = convertLegacyTypes(uiExports, legacyConfig);
- expect(Object.keys(converted[0]!.migrations!)).toEqual(['1.0.0']);
-
- const migration = converted[0]!.migrations!['1.0.0']!;
-
- const doc = {} as SavedObjectUnsanitizedDoc;
- const context = { log: {} } as SavedObjectMigrationContext;
- migration(doc, context);
-
- expect(legacyMigration).toHaveBeenCalledTimes(1);
- expect(legacyMigration).toHaveBeenCalledWith(doc, context.log);
- });
-
- it('imports type management information', () => {
- const uiExports: SavedObjectsLegacyUiExports = {
- savedObjectMappings: [
- {
- pluginId: 'pluginA',
- properties: {
- typeA: {
- properties: {
- fieldA: { type: 'text' },
- },
- },
- },
- },
- {
- pluginId: 'pluginB',
- properties: {
- typeB: {
- properties: {
- fieldB: { type: 'text' },
- },
- },
- typeC: {
- properties: {
- fieldC: { type: 'text' },
- },
- },
- },
- },
- ],
- savedObjectsManagement: {
- typeA: {
- isImportableAndExportable: true,
- icon: 'iconA',
- defaultSearchField: 'searchFieldA',
- getTitle: (savedObject) => savedObject.id,
- },
- typeB: {
- isImportableAndExportable: false,
- icon: 'iconB',
- getEditUrl: (savedObject) => `/some-url/${savedObject.id}`,
- getInAppUrl: (savedObject) => ({ path: 'path', uiCapabilitiesPath: 'ui-path' }),
- },
- },
- savedObjectMigrations: {},
- savedObjectSchemas: {},
- savedObjectValidations: {},
- };
-
- const converted = convertLegacyTypes(uiExports, legacyConfig);
- expect(converted.length).toEqual(3);
- const [typeA, typeB, typeC] = converted;
-
- expect(typeA.management).toEqual({
- importableAndExportable: true,
- icon: 'iconA',
- defaultSearchField: 'searchFieldA',
- getTitle: uiExports.savedObjectsManagement.typeA.getTitle,
- });
-
- expect(typeB.management).toEqual({
- importableAndExportable: false,
- icon: 'iconB',
- getEditUrl: uiExports.savedObjectsManagement.typeB.getEditUrl,
- getInAppUrl: uiExports.savedObjectsManagement.typeB.getInAppUrl,
- });
-
- expect(typeC.management).toBeUndefined();
- });
-
- it('merges everything when all are present', () => {
- const uiExports: SavedObjectsLegacyUiExports = {
- savedObjectMappings: [
- {
- pluginId: 'pluginA',
- properties: {
- typeA: {
- properties: {
- fieldA: { type: 'text' },
- },
- },
- typeB: {
- properties: {
- fieldB: { type: 'text' },
- anotherFieldB: { type: 'boolean' },
- },
- },
- },
- },
- {
- pluginId: 'pluginB',
- properties: {
- typeC: {
- properties: {
- fieldC: { type: 'text' },
- },
- },
- },
- },
- ],
- savedObjectMigrations: {
- typeA: {
- '1.0.0': jest.fn(),
- '2.0.4': jest.fn(),
- },
- typeC: {
- '1.5.3': jest.fn(),
- },
- },
- savedObjectSchemas: {
- typeA: {
- indexPattern: jest.fn((config) => {
- config.get('foo.bar');
- return 'myIndex';
- }),
- hidden: true,
- isNamespaceAgnostic: true,
- },
- typeB: {
- convertToAliasScript: 'some alias script',
- hidden: false,
- },
- },
- savedObjectValidations: {},
- savedObjectsManagement: {},
- };
-
- const converted = convertLegacyTypes(uiExports, legacyConfig);
- expect(converted).toMatchSnapshot();
- });
-});
-
-describe('convertTypesToLegacySchema', () => {
- it('converts types to the legacy schema format', () => {
- const types: SavedObjectsType[] = [
- {
- name: 'typeA',
- hidden: false,
- namespaceType: 'agnostic',
- mappings: { properties: {} },
- convertToAliasScript: 'some script',
- },
- {
- name: 'typeB',
- hidden: true,
- namespaceType: 'single',
- indexPattern: 'myIndex',
- mappings: { properties: {} },
- },
- {
- name: 'typeC',
- hidden: false,
- namespaceType: 'multiple',
- mappings: { properties: {} },
- },
- ];
- expect(convertTypesToLegacySchema(types)).toEqual({
- typeA: {
- hidden: false,
- isNamespaceAgnostic: true,
- multiNamespace: false,
- convertToAliasScript: 'some script',
- },
- typeB: {
- hidden: true,
- isNamespaceAgnostic: false,
- multiNamespace: false,
- indexPattern: 'myIndex',
- },
- typeC: {
- hidden: false,
- isNamespaceAgnostic: false,
- multiNamespace: true,
- },
- });
- });
-});
diff --git a/src/core/server/saved_objects/utils.ts b/src/core/server/saved_objects/utils.ts
deleted file mode 100644
index af7c08d1fbfcc..0000000000000
--- a/src/core/server/saved_objects/utils.ts
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { LegacyConfig } from '../legacy';
-import { SavedObjectMigrationMap } from './migrations';
-import {
- SavedObjectsNamespaceType,
- SavedObjectsType,
- SavedObjectsLegacyUiExports,
- SavedObjectLegacyMigrationMap,
- SavedObjectsLegacyManagementTypeDefinition,
- SavedObjectsTypeManagementDefinition,
-} from './types';
-import { SavedObjectsSchemaDefinition } from './schema';
-
-/**
- * Converts the legacy savedObjects mappings, schema, and migrations
- * to actual {@link SavedObjectsType | saved object types}
- */
-export const convertLegacyTypes = (
- {
- savedObjectMappings = [],
- savedObjectMigrations = {},
- savedObjectSchemas = {},
- savedObjectsManagement = {},
- }: SavedObjectsLegacyUiExports,
- legacyConfig: LegacyConfig
-): SavedObjectsType[] => {
- return savedObjectMappings.reduce((types, { properties }) => {
- return [
- ...types,
- ...Object.entries(properties).map(([type, mappings]) => {
- const schema = savedObjectSchemas[type];
- const migrations = savedObjectMigrations[type];
- const management = savedObjectsManagement[type];
- const namespaceType = (schema?.isNamespaceAgnostic
- ? 'agnostic'
- : schema?.multiNamespace
- ? 'multiple'
- : 'single') as SavedObjectsNamespaceType;
- return {
- name: type,
- hidden: schema?.hidden ?? false,
- namespaceType,
- mappings,
- indexPattern:
- typeof schema?.indexPattern === 'function'
- ? schema.indexPattern(legacyConfig)
- : schema?.indexPattern,
- convertToAliasScript: schema?.convertToAliasScript,
- migrations: convertLegacyMigrations(migrations ?? {}),
- management: management ? convertLegacyTypeManagement(management) : undefined,
- };
- }),
- ];
- }, [] as SavedObjectsType[]);
-};
-
-/**
- * Convert {@link SavedObjectsType | saved object types} to the legacy {@link SavedObjectsSchemaDefinition | schema} format
- */
-export const convertTypesToLegacySchema = (
- types: SavedObjectsType[]
-): SavedObjectsSchemaDefinition => {
- return types.reduce((schema, type) => {
- return {
- ...schema,
- [type.name]: {
- isNamespaceAgnostic: type.namespaceType === 'agnostic',
- multiNamespace: type.namespaceType === 'multiple',
- hidden: type.hidden,
- indexPattern: type.indexPattern,
- convertToAliasScript: type.convertToAliasScript,
- },
- };
- }, {} as SavedObjectsSchemaDefinition);
-};
-
-const convertLegacyMigrations = (
- legacyMigrations: SavedObjectLegacyMigrationMap
-): SavedObjectMigrationMap => {
- return Object.entries(legacyMigrations).reduce((migrated, [version, migrationFn]) => {
- return {
- ...migrated,
- [version]: (doc, context) => migrationFn(doc, context.log),
- };
- }, {} as SavedObjectMigrationMap);
-};
-
-const convertLegacyTypeManagement = (
- legacyTypeManagement: SavedObjectsLegacyManagementTypeDefinition
-): SavedObjectsTypeManagementDefinition => {
- return {
- importableAndExportable: legacyTypeManagement.isImportableAndExportable,
- defaultSearchField: legacyTypeManagement.defaultSearchField,
- icon: legacyTypeManagement.icon,
- getTitle: legacyTypeManagement.getTitle,
- getEditUrl: legacyTypeManagement.getEditUrl,
- getInAppUrl: legacyTypeManagement.getInAppUrl,
- };
-};
diff --git a/src/core/server/saved_objects/validation/index.ts b/src/core/server/saved_objects/validation/index.ts
deleted file mode 100644
index b1b33f91d3fd4..0000000000000
--- a/src/core/server/saved_objects/validation/index.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/*
- * This is the core logic for validating saved object properties. The saved object client
- * and migrations consume this in order to validate saved object documents prior to
- * persisting them.
- */
-
-interface SavedObjectDoc {
- type: string;
- [prop: string]: any;
-}
-
-/**
- * A dictionary of property name -> validation function. The property name
- * is generally the document's type (e.g. "dashboard"), but will also
- * match other properties.
- *
- * For example, the "acl" and "dashboard" validators both apply to the
- * following saved object: { type: "dashboard", attributes: {}, acl: "sdlaj3w" }
- *
- * @export
- * @interface Validators
- */
-export interface PropertyValidators {
- [prop: string]: ValidateDoc;
-}
-
-export type ValidateDoc = (doc: SavedObjectDoc) => void;
-
-/**
- * Creates a function which uses a dictionary of property validators to validate
- * individual saved object documents.
- *
- * @export
- * @param {Validators} validators
- * @param {SavedObjectDoc} doc
- */
-export function docValidator(validators: PropertyValidators = {}): ValidateDoc {
- return function validateDoc(doc: SavedObjectDoc) {
- Object.keys(doc)
- .concat(doc.type)
- .forEach((prop) => {
- const validator = validators[prop];
- if (validator) {
- validator(doc);
- }
- });
- };
-}
diff --git a/src/core/server/saved_objects/validation/readme.md b/src/core/server/saved_objects/validation/readme.md
deleted file mode 100644
index 3b9f17c37fd0b..0000000000000
--- a/src/core/server/saved_objects/validation/readme.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# Saved Object Validations
-
-The saved object client supports validation of documents during create / bulkCreate operations.
-
-This allows us tighter control over what documents get written to the saved object index, and helps us keep the index in a healthy state.
-
-## Creating validations
-
-Plugin authors can write their own validations by adding a `validations` property to their uiExports. A validation is nothing more than a dictionary of `{[prop: string]: validationFunction}` where:
-
-* `prop` - a root-property on a saved object document
-* `validationFunction` - a function that takes a document and throws an error if it does not meet expectations.
-
-## Example
-
-```js
-// In myFanciPlugin...
-uiExports: {
- validations: {
- myProperty(doc) {
- if (doc.attributes.someField === undefined) {
- throw new Error(`Document ${doc.id} did not define "someField"`);
- }
- },
-
- someOtherProp(doc) {
- if (doc.attributes.counter < 0) {
- throw new Error(`Document ${doc.id} cannot have a negative counter.`);
- }
- },
- },
-},
-```
-
-In this example, `myFanciPlugin` defines validations for two properties: `myProperty` and `someOtherProp`.
-
-This means that no other plugin can define validations for myProperty or someOtherProp.
-
-The `myProperty` validation would run for any doc that has a `type="myProperty"` or for any doc that has a root-level property of `myProperty`. e.g. it would apply to all documents in the following array:
-
-```js
-[
- {
- type: 'foo',
- attributes: { stuff: 'here' },
- myProperty: 'shazm!',
- },
- {
- type: 'myProperty',
- attributes: { shazm: true },
- },
-];
-```
-
-Validating properties other than just 'type' allows us to support potential future saved object scenarios in which plugins might want to annotate other plugin documents, such as a security plugin adding an acl to another document:
-
-```js
-{
- type: 'dashboard',
- attributes: { stuff: 'here' },
- acl: '342343',
-}
-```
diff --git a/src/core/server/saved_objects/validation/validation.test.ts b/src/core/server/saved_objects/validation/validation.test.ts
deleted file mode 100644
index 71e220280ba5f..0000000000000
--- a/src/core/server/saved_objects/validation/validation.test.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { docValidator } from './index';
-
-describe('docValidator', () => {
- test('does not run validators that have no application to the doc', () => {
- const validators = {
- foo: () => {
- throw new Error('Boom!');
- },
- };
- expect(() => docValidator(validators)({ type: 'shoo', bar: 'hi' })).not.toThrow();
- });
-
- test('validates the doc type', () => {
- const validators = {
- foo: () => {
- throw new Error('Boom!');
- },
- };
- expect(() => docValidator(validators)({ type: 'foo' })).toThrow(/Boom!/);
- });
-
- test('validates various props', () => {
- const validators = {
- a: jest.fn(),
- b: jest.fn(),
- c: jest.fn(),
- };
- docValidator(validators)({ type: 'a', b: 'foo' });
-
- expect(validators.c).not.toHaveBeenCalled();
-
- expect(validators.a.mock.calls).toEqual([[{ type: 'a', b: 'foo' }]]);
- expect(validators.b.mock.calls).toEqual([[{ type: 'a', b: 'foo' }]]);
- });
-});
diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md
index 081554cd17f25..ec457704e89c7 100644
--- a/src/core/server/server.api.md
+++ b/src/core/server/server.api.md
@@ -1411,19 +1411,30 @@ export interface LegacyServiceStartDeps {
plugins: Record;
}
-// Warning: (ae-forgotten-export) The symbol "SavedObjectsLegacyUiExports" needs to be exported by the entry point index.d.ts
-//
// @internal @deprecated (undocumented)
-export type LegacyUiExports = SavedObjectsLegacyUiExports & {
+export interface LegacyUiExports {
+ // Warning: (ae-forgotten-export) The symbol "VarsProvider" needs to be exported by the entry point index.d.ts
+ //
+ // (undocumented)
defaultInjectedVarProviders?: VarsProvider[];
+ // Warning: (ae-forgotten-export) The symbol "VarsReplacer" needs to be exported by the entry point index.d.ts
+ //
+ // (undocumented)
injectedVarsReplacers?: VarsReplacer[];
+ // Warning: (ae-forgotten-export) The symbol "LegacyNavLinkSpec" needs to be exported by the entry point index.d.ts
+ //
+ // (undocumented)
navLinkSpecs?: LegacyNavLinkSpec[] | null;
+ // Warning: (ae-forgotten-export) The symbol "LegacyAppSpec" needs to be exported by the entry point index.d.ts
+ //
+ // (undocumented)
uiAppSpecs?: Array;
+ // (undocumented)
unknown?: [{
pluginSpec: LegacyPluginSpec;
type: unknown;
}];
-};
+}
// Warning: (ae-forgotten-export) The symbol "lifecycleResponseFactory" needs to be exported by the entry point index.d.ts
//
@@ -1520,10 +1531,10 @@ export interface LogRecord {
timestamp: Date;
}
-// Warning: (ae-missing-release-tag) "MetricsServiceSetup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export interface MetricsServiceSetup {
+ readonly collectionInterval: number;
+ getOpsMetrics$: () => Observable;
}
// @public @deprecated (undocumented)
@@ -1610,6 +1621,7 @@ export interface OnPreRoutingToolkit {
// @public
export interface OpsMetrics {
+ collected_at: Date;
concurrent_connections: OpsServerMetrics['concurrent_connections'];
os: OpsOsMetrics;
process: OpsProcessMetrics;
@@ -1619,6 +1631,20 @@ export interface OpsMetrics {
// @public
export interface OpsOsMetrics {
+ cpu?: {
+ control_group: string;
+ cfs_period_micros: number;
+ cfs_quota_micros: number;
+ stat: {
+ number_of_elapsed_periods: number;
+ number_of_times_throttled: number;
+ time_throttled_nanos: number;
+ };
+ };
+ cpuacct?: {
+ control_group: string;
+ usage_nanos: number;
+ };
distro?: string;
distroRelease?: string;
load: {
@@ -2021,6 +2047,7 @@ export interface SavedObjectsBulkResponse {
export interface SavedObjectsBulkUpdateObject extends Pick {
attributes: Partial;
id: string;
+ namespace?: string;
type: string;
}
@@ -2437,33 +2464,6 @@ export interface SavedObjectsIncrementCounterOptions extends SavedObjectsBaseOpt
refresh?: MutatingOperationRefreshSetting;
}
-// @internal @deprecated (undocumented)
-export interface SavedObjectsLegacyService {
- // Warning: (ae-forgotten-export) The symbol "SavedObjectsClientProvider" needs to be exported by the entry point index.d.ts
- //
- // (undocumented)
- addScopedSavedObjectsClientWrapperFactory: SavedObjectsClientProvider['addClientWrapperFactory'];
- // (undocumented)
- getSavedObjectsRepository(...rest: any[]): any;
- // (undocumented)
- getScopedSavedObjectsClient: SavedObjectsClientProvider['getClient'];
- // (undocumented)
- importExport: {
- objectLimit: number;
- importSavedObjects(options: SavedObjectsImportOptions): Promise;
- resolveImportErrors(options: SavedObjectsResolveImportErrorsOptions): Promise;
- getSortedObjectsForExport(options: SavedObjectsExportOptions): Promise;
- };
- // (undocumented)
- SavedObjectsClient: typeof SavedObjectsClient;
- // (undocumented)
- schema: SavedObjectsSchema;
- // (undocumented)
- setScopedSavedObjectsClientFactory: SavedObjectsClientProvider['setClientFactory'];
- // (undocumented)
- types: string[];
-}
-
// @public
export interface SavedObjectsMappingProperties {
// (undocumented)
@@ -2517,10 +2517,10 @@ export class SavedObjectsRepository {
bulkUpdate(objects: Array>, options?: SavedObjectsBulkUpdateOptions): Promise>;
checkConflicts(objects?: SavedObjectsCheckConflictsObject[], options?: SavedObjectsBaseOptions): Promise;
create(type: string, attributes: T, options?: SavedObjectsCreateOptions): Promise>;
- // Warning: (ae-forgotten-export) The symbol "KibanaMigrator" needs to be exported by the entry point index.d.ts
+ // Warning: (ae-forgotten-export) The symbol "IKibanaMigrator" needs to be exported by the entry point index.d.ts
//
// @internal
- static createRepository(migrator: KibanaMigrator, typeRegistry: SavedObjectTypeRegistry, indexName: string, client: ElasticsearchClient, includedHiddenTypes?: string[], injectedConstructor?: any): ISavedObjectsRepository;
+ static createRepository(migrator: IKibanaMigrator, typeRegistry: SavedObjectTypeRegistry, indexName: string, client: ElasticsearchClient, includedHiddenTypes?: string[], injectedConstructor?: any): ISavedObjectsRepository;
delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>;
deleteByNamespace(namespace: string, options?: SavedObjectsDeleteByNamespaceOptions): Promise;
deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise;
@@ -2548,24 +2548,6 @@ export interface SavedObjectsResolveImportErrorsOptions {
typeRegistry: ISavedObjectTypeRegistry;
}
-// @internal @deprecated (undocumented)
-export class SavedObjectsSchema {
- // Warning: (ae-forgotten-export) The symbol "SavedObjectsSchemaDefinition" needs to be exported by the entry point index.d.ts
- constructor(schemaDefinition?: SavedObjectsSchemaDefinition);
- // (undocumented)
- getConvertToAliasScript(type: string): string | undefined;
- // (undocumented)
- getIndexForType(config: LegacyConfig, type: string): string | undefined;
- // (undocumented)
- isHiddenType(type: string): boolean;
- // (undocumented)
- isMultiNamespace(type: string): boolean;
- // (undocumented)
- isNamespaceAgnostic(type: string): boolean;
- // (undocumented)
- isSingleNamespace(type: string): boolean;
-}
-
// @public
export class SavedObjectsSerializer {
// @internal
@@ -2649,6 +2631,12 @@ export interface SavedObjectsUpdateResponse extends Omit string;
+ static namespaceStringToId: (namespace: string) => string | undefined;
+}
+
// @public
export class SavedObjectTypeRegistry {
getAllTypes(): SavedObjectsType[];
@@ -2797,10 +2785,17 @@ export type SharedGlobalConfig = RecursiveReadonly<{
// @public
export type StartServicesAccessor = () => Promise<[CoreStart, TPluginsStart, TStart]>;
+// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "ServiceStatusSetup"
+// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "ServiceStatusSetup"
+//
// @public
export interface StatusServiceSetup {
core$: Observable;
+ dependencies$: Observable>;
+ // Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "StatusSetup"
+ derivedStatus$: Observable;
overall$: Observable;
+ set(status$: Observable): void;
}
// @public
@@ -2888,13 +2883,9 @@ export const validBodyOutput: readonly ["data", "stream"];
// Warnings were encountered during analysis:
//
// src/core/server/http/router/response.ts:316:3 - (ae-forgotten-export) The symbol "KibanaResponse" needs to be exported by the entry point index.d.ts
-// src/core/server/legacy/types.ts:132:3 - (ae-forgotten-export) The symbol "VarsProvider" needs to be exported by the entry point index.d.ts
-// src/core/server/legacy/types.ts:133:3 - (ae-forgotten-export) The symbol "VarsReplacer" needs to be exported by the entry point index.d.ts
-// src/core/server/legacy/types.ts:134:3 - (ae-forgotten-export) The symbol "LegacyNavLinkSpec" needs to be exported by the entry point index.d.ts
-// src/core/server/legacy/types.ts:135:3 - (ae-forgotten-export) The symbol "LegacyAppSpec" needs to be exported by the entry point index.d.ts
-// src/core/server/legacy/types.ts:136:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts
-// src/core/server/plugins/types.ts:266:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts
-// src/core/server/plugins/types.ts:266:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts
-// src/core/server/plugins/types.ts:268:3 - (ae-forgotten-export) The symbol "PathConfigType" needs to be exported by the entry point index.d.ts
+// src/core/server/legacy/types.ts:135:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts
+// src/core/server/plugins/types.ts:272:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts
+// src/core/server/plugins/types.ts:272:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts
+// src/core/server/plugins/types.ts:274:3 - (ae-forgotten-export) The symbol "PathConfigType" needs to be exported by the entry point index.d.ts
```
diff --git a/src/core/server/server.test.ts b/src/core/server/server.test.ts
index 417f66a2988c2..8bf16d9130ef5 100644
--- a/src/core/server/server.test.ts
+++ b/src/core/server/server.test.ts
@@ -49,7 +49,7 @@ const rawConfigService = rawConfigServiceMock.create({});
beforeEach(() => {
mockConfigService.atPath.mockReturnValue(new BehaviorSubject({ autoListen: true }));
mockPluginsService.discover.mockResolvedValue({
- pluginTree: new Map(),
+ pluginTree: { asOpaqueIds: new Map(), asNames: new Map() },
uiPlugins: { internal: new Map(), public: new Map(), browserConfigs: new Map() },
});
});
@@ -98,7 +98,7 @@ test('injects legacy dependency to context#setup()', async () => {
[pluginB, [pluginA]],
]);
mockPluginsService.discover.mockResolvedValue({
- pluginTree: pluginDependencies,
+ pluginTree: { asOpaqueIds: pluginDependencies, asNames: new Map() },
uiPlugins: { internal: new Map(), public: new Map(), browserConfigs: new Map() },
});
diff --git a/src/core/server/server.ts b/src/core/server/server.ts
index cc6d8171e7a03..a02b0f51b559f 100644
--- a/src/core/server/server.ts
+++ b/src/core/server/server.ts
@@ -121,10 +121,13 @@ export class Server {
const contextServiceSetup = this.context.setup({
// We inject a fake "legacy plugin" with dependencies on every plugin so that legacy plugins:
- // 1) Can access context from any NP plugin
+ // 1) Can access context from any KP plugin
// 2) Can register context providers that will only be available to other legacy plugins and will not leak into
// New Platform plugins.
- pluginDependencies: new Map([...pluginTree, [this.legacy.legacyId, [...pluginTree.keys()]]]),
+ pluginDependencies: new Map([
+ ...pluginTree.asOpaqueIds,
+ [this.legacy.legacyId, [...pluginTree.asOpaqueIds.keys()]],
+ ]),
});
const auditTrailSetup = this.auditTrail.setup();
@@ -142,7 +145,6 @@ export class Server {
const savedObjectsSetup = await this.savedObjects.setup({
http: httpSetup,
elasticsearch: elasticsearchServiceSetup,
- legacyPlugins,
});
const uiSettingsSetup = await this.uiSettings.setup({
@@ -154,6 +156,7 @@ export class Server {
const statusSetup = await this.status.setup({
elasticsearch: elasticsearchServiceSetup,
+ pluginDependencies: pluginTree.asNames,
savedObjects: savedObjectsSetup,
});
diff --git a/src/core/server/status/get_summary_status.test.ts b/src/core/server/status/get_summary_status.test.ts
index 7516e82ee784d..d97083162b502 100644
--- a/src/core/server/status/get_summary_status.test.ts
+++ b/src/core/server/status/get_summary_status.test.ts
@@ -94,6 +94,38 @@ describe('getSummaryStatus', () => {
describe('summary', () => {
describe('when a single service is at highest level', () => {
it('returns all information about that single service', () => {
+ expect(
+ getSummaryStatus(
+ Object.entries({
+ s1: degraded,
+ s2: {
+ level: ServiceStatusLevels.unavailable,
+ summary: 'Lorem ipsum',
+ meta: {
+ custom: { data: 'here' },
+ },
+ },
+ })
+ )
+ ).toEqual({
+ level: ServiceStatusLevels.unavailable,
+ summary: '[s2]: Lorem ipsum',
+ detail: 'See the status page for more information',
+ meta: {
+ affectedServices: {
+ s2: {
+ level: ServiceStatusLevels.unavailable,
+ summary: 'Lorem ipsum',
+ meta: {
+ custom: { data: 'here' },
+ },
+ },
+ },
+ },
+ });
+ });
+
+ it('allows the single service to override the detail and documentationUrl fields', () => {
expect(
getSummaryStatus(
Object.entries({
@@ -115,7 +147,17 @@ describe('getSummaryStatus', () => {
detail: 'Vivamus pulvinar sem ac luctus ultrices.',
documentationUrl: 'http://helpmenow.com/problem1',
meta: {
- custom: { data: 'here' },
+ affectedServices: {
+ s2: {
+ level: ServiceStatusLevels.unavailable,
+ summary: 'Lorem ipsum',
+ detail: 'Vivamus pulvinar sem ac luctus ultrices.',
+ documentationUrl: 'http://helpmenow.com/problem1',
+ meta: {
+ custom: { data: 'here' },
+ },
+ },
+ },
},
});
});
diff --git a/src/core/server/status/get_summary_status.ts b/src/core/server/status/get_summary_status.ts
index 748a54f0bf8bb..8d97cdbd9b15b 100644
--- a/src/core/server/status/get_summary_status.ts
+++ b/src/core/server/status/get_summary_status.ts
@@ -23,62 +23,60 @@ import { ServiceStatus, ServiceStatusLevels, ServiceStatusLevel } from './types'
* Returns a single {@link ServiceStatus} that summarizes the most severe status level from a group of statuses.
* @param statuses
*/
-export const getSummaryStatus = (statuses: Array<[string, ServiceStatus]>): ServiceStatus => {
- const grouped = groupByLevel(statuses);
- const highestSeverityLevel = getHighestSeverityLevel(grouped.keys());
- const highestSeverityGroup = grouped.get(highestSeverityLevel)!;
+export const getSummaryStatus = (
+ statuses: Array<[string, ServiceStatus]>,
+ { allAvailableSummary = `All services are available` }: { allAvailableSummary?: string } = {}
+): ServiceStatus => {
+ const { highestLevel, highestStatuses } = highestLevelSummary(statuses);
- if (highestSeverityLevel === ServiceStatusLevels.available) {
+ if (highestLevel === ServiceStatusLevels.available) {
return {
level: ServiceStatusLevels.available,
- summary: `All services are available`,
+ summary: allAvailableSummary,
};
- } else if (highestSeverityGroup.size === 1) {
- const [serviceName, status] = [...highestSeverityGroup.entries()][0];
+ } else if (highestStatuses.length === 1) {
+ const [serviceName, status] = highestStatuses[0]! as [string, ServiceStatus];
return {
...status,
summary: `[${serviceName}]: ${status.summary!}`,
+ // TODO: include URL to status page
+ detail: status.detail ?? `See the status page for more information`,
+ meta: {
+ affectedServices: { [serviceName]: status },
+ },
};
} else {
return {
- level: highestSeverityLevel,
- summary: `[${highestSeverityGroup.size}] services are ${highestSeverityLevel.toString()}`,
+ level: highestLevel,
+ summary: `[${highestStatuses.length}] services are ${highestLevel.toString()}`,
// TODO: include URL to status page
detail: `See the status page for more information`,
meta: {
- affectedServices: Object.fromEntries([...highestSeverityGroup]),
+ affectedServices: Object.fromEntries(highestStatuses),
},
};
}
};
-const groupByLevel = (
- statuses: Array<[string, ServiceStatus]>
-): Map> => {
- const byLevel = new Map>();
+type StatusPair = [string, ServiceStatus];
- for (const [serviceName, status] of statuses) {
- let levelMap = byLevel.get(status.level);
- if (!levelMap) {
- levelMap = new Map();
- byLevel.set(status.level, levelMap);
- }
+const highestLevelSummary = (
+ statuses: StatusPair[]
+): { highestLevel: ServiceStatusLevel; highestStatuses: StatusPair[] } => {
+ let highestLevel: ServiceStatusLevel = ServiceStatusLevels.available;
+ let highestStatuses: StatusPair[] = [];
- levelMap.set(serviceName, status);
+ for (const pair of statuses) {
+ if (pair[1].level === highestLevel) {
+ highestStatuses.push(pair);
+ } else if (pair[1].level > highestLevel) {
+ highestLevel = pair[1].level;
+ highestStatuses = [pair];
+ }
}
- return byLevel;
-};
-
-const getHighestSeverityLevel = (levels: Iterable): ServiceStatusLevel => {
- const sorted = [...levels].sort((a, b) => {
- if (a < b) {
- return -1;
- } else if (a > b) {
- return 1;
- } else {
- return 0;
- }
- });
- return sorted[sorted.length - 1] ?? ServiceStatusLevels.available;
+ return {
+ highestLevel,
+ highestStatuses,
+ };
};
diff --git a/src/core/server/status/plugins_status.test.ts b/src/core/server/status/plugins_status.test.ts
new file mode 100644
index 0000000000000..a75dc8c283698
--- /dev/null
+++ b/src/core/server/status/plugins_status.test.ts
@@ -0,0 +1,338 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { PluginName } from '../plugins';
+import { PluginsStatusService } from './plugins_status';
+import { of, Observable, BehaviorSubject } from 'rxjs';
+import { ServiceStatusLevels, CoreStatus, ServiceStatus } from './types';
+import { first } from 'rxjs/operators';
+import { ServiceStatusLevelSnapshotSerializer } from './test_utils';
+
+expect.addSnapshotSerializer(ServiceStatusLevelSnapshotSerializer);
+
+describe('PluginStatusService', () => {
+ const coreAllAvailable$: Observable = of({
+ elasticsearch: { level: ServiceStatusLevels.available, summary: 'elasticsearch avail' },
+ savedObjects: { level: ServiceStatusLevels.available, summary: 'savedObjects avail' },
+ });
+ const coreOneDegraded$: Observable = of({
+ elasticsearch: { level: ServiceStatusLevels.available, summary: 'elasticsearch avail' },
+ savedObjects: { level: ServiceStatusLevels.degraded, summary: 'savedObjects degraded' },
+ });
+ const coreOneCriticalOneDegraded$: Observable = of({
+ elasticsearch: { level: ServiceStatusLevels.critical, summary: 'elasticsearch critical' },
+ savedObjects: { level: ServiceStatusLevels.degraded, summary: 'savedObjects degraded' },
+ });
+ const pluginDependencies: Map = new Map([
+ ['a', []],
+ ['b', ['a']],
+ ['c', ['a', 'b']],
+ ]);
+
+ describe('getDerivedStatus$', () => {
+ it(`defaults to core's most severe status`, async () => {
+ const serviceAvailable = new PluginsStatusService({
+ core$: coreAllAvailable$,
+ pluginDependencies,
+ });
+ expect(await serviceAvailable.getDerivedStatus$('a').pipe(first()).toPromise()).toEqual({
+ level: ServiceStatusLevels.available,
+ summary: 'All dependencies are available',
+ });
+
+ const serviceDegraded = new PluginsStatusService({
+ core$: coreOneDegraded$,
+ pluginDependencies,
+ });
+ expect(await serviceDegraded.getDerivedStatus$('a').pipe(first()).toPromise()).toEqual({
+ level: ServiceStatusLevels.degraded,
+ summary: '[savedObjects]: savedObjects degraded',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ });
+
+ const serviceCritical = new PluginsStatusService({
+ core$: coreOneCriticalOneDegraded$,
+ pluginDependencies,
+ });
+ expect(await serviceCritical.getDerivedStatus$('a').pipe(first()).toPromise()).toEqual({
+ level: ServiceStatusLevels.critical,
+ summary: '[elasticsearch]: elasticsearch critical',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ });
+ });
+
+ it(`provides a summary status when core and dependencies are at same severity level`, async () => {
+ const service = new PluginsStatusService({ core$: coreOneDegraded$, pluginDependencies });
+ service.set('a', of({ level: ServiceStatusLevels.degraded, summary: 'a is degraded' }));
+ expect(await service.getDerivedStatus$('b').pipe(first()).toPromise()).toEqual({
+ level: ServiceStatusLevels.degraded,
+ summary: '[2] services are degraded',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ });
+ });
+
+ it(`allows dependencies status to take precedence over lower severity core statuses`, async () => {
+ const service = new PluginsStatusService({ core$: coreOneDegraded$, pluginDependencies });
+ service.set('a', of({ level: ServiceStatusLevels.unavailable, summary: 'a is not working' }));
+ expect(await service.getDerivedStatus$('b').pipe(first()).toPromise()).toEqual({
+ level: ServiceStatusLevels.unavailable,
+ summary: '[a]: a is not working',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ });
+ });
+
+ it(`allows core status to take precedence over lower severity dependencies statuses`, async () => {
+ const service = new PluginsStatusService({
+ core$: coreOneCriticalOneDegraded$,
+ pluginDependencies,
+ });
+ service.set('a', of({ level: ServiceStatusLevels.unavailable, summary: 'a is not working' }));
+ expect(await service.getDerivedStatus$('b').pipe(first()).toPromise()).toEqual({
+ level: ServiceStatusLevels.critical,
+ summary: '[elasticsearch]: elasticsearch critical',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ });
+ });
+
+ it(`allows a severe dependency status to take precedence over a less severe dependency status`, async () => {
+ const service = new PluginsStatusService({ core$: coreOneDegraded$, pluginDependencies });
+ service.set('a', of({ level: ServiceStatusLevels.degraded, summary: 'a is degraded' }));
+ service.set('b', of({ level: ServiceStatusLevels.unavailable, summary: 'b is not working' }));
+ expect(await service.getDerivedStatus$('c').pipe(first()).toPromise()).toEqual({
+ level: ServiceStatusLevels.unavailable,
+ summary: '[b]: b is not working',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ });
+ });
+ });
+
+ describe('getAll$', () => {
+ it('defaults to empty record if no plugins', async () => {
+ const service = new PluginsStatusService({
+ core$: coreAllAvailable$,
+ pluginDependencies: new Map(),
+ });
+ expect(await service.getAll$().pipe(first()).toPromise()).toEqual({});
+ });
+
+ it('defaults to core status when no plugin statuses are set', async () => {
+ const serviceAvailable = new PluginsStatusService({
+ core$: coreAllAvailable$,
+ pluginDependencies,
+ });
+ expect(await serviceAvailable.getAll$().pipe(first()).toPromise()).toEqual({
+ a: { level: ServiceStatusLevels.available, summary: 'All dependencies are available' },
+ b: { level: ServiceStatusLevels.available, summary: 'All dependencies are available' },
+ c: { level: ServiceStatusLevels.available, summary: 'All dependencies are available' },
+ });
+
+ const serviceDegraded = new PluginsStatusService({
+ core$: coreOneDegraded$,
+ pluginDependencies,
+ });
+ expect(await serviceDegraded.getAll$().pipe(first()).toPromise()).toEqual({
+ a: {
+ level: ServiceStatusLevels.degraded,
+ summary: '[savedObjects]: savedObjects degraded',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ },
+ b: {
+ level: ServiceStatusLevels.degraded,
+ summary: '[2] services are degraded',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ },
+ c: {
+ level: ServiceStatusLevels.degraded,
+ summary: '[3] services are degraded',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ },
+ });
+
+ const serviceCritical = new PluginsStatusService({
+ core$: coreOneCriticalOneDegraded$,
+ pluginDependencies,
+ });
+ expect(await serviceCritical.getAll$().pipe(first()).toPromise()).toEqual({
+ a: {
+ level: ServiceStatusLevels.critical,
+ summary: '[elasticsearch]: elasticsearch critical',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ },
+ b: {
+ level: ServiceStatusLevels.critical,
+ summary: '[2] services are critical',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ },
+ c: {
+ level: ServiceStatusLevels.critical,
+ summary: '[3] services are critical',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ },
+ });
+ });
+
+ it('uses the manually set status level if plugin specifies one', async () => {
+ const service = new PluginsStatusService({ core$: coreOneDegraded$, pluginDependencies });
+ service.set('a', of({ level: ServiceStatusLevels.available, summary: 'a status' }));
+
+ expect(await service.getAll$().pipe(first()).toPromise()).toEqual({
+ a: { level: ServiceStatusLevels.available, summary: 'a status' }, // a is available depsite savedObjects being degraded
+ b: {
+ level: ServiceStatusLevels.degraded,
+ summary: '[savedObjects]: savedObjects degraded',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ },
+ c: {
+ level: ServiceStatusLevels.degraded,
+ summary: '[2] services are degraded',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ },
+ });
+ });
+
+ it('updates when a new plugin status observable is set', async () => {
+ const service = new PluginsStatusService({
+ core$: coreAllAvailable$,
+ pluginDependencies: new Map([['a', []]]),
+ });
+ const statusUpdates: Array> = [];
+ const subscription = service
+ .getAll$()
+ .subscribe((pluginStatuses) => statusUpdates.push(pluginStatuses));
+
+ service.set('a', of({ level: ServiceStatusLevels.degraded, summary: 'a degraded' }));
+ service.set('a', of({ level: ServiceStatusLevels.unavailable, summary: 'a unavailable' }));
+ service.set('a', of({ level: ServiceStatusLevels.available, summary: 'a available' }));
+ subscription.unsubscribe();
+
+ expect(statusUpdates).toEqual([
+ { a: { level: ServiceStatusLevels.available, summary: 'All dependencies are available' } },
+ { a: { level: ServiceStatusLevels.degraded, summary: 'a degraded' } },
+ { a: { level: ServiceStatusLevels.unavailable, summary: 'a unavailable' } },
+ { a: { level: ServiceStatusLevels.available, summary: 'a available' } },
+ ]);
+ });
+ });
+
+ describe('getDependenciesStatus$', () => {
+ it('only includes dependencies of specified plugin', async () => {
+ const service = new PluginsStatusService({
+ core$: coreAllAvailable$,
+ pluginDependencies,
+ });
+ expect(await service.getDependenciesStatus$('a').pipe(first()).toPromise()).toEqual({});
+ expect(await service.getDependenciesStatus$('b').pipe(first()).toPromise()).toEqual({
+ a: { level: ServiceStatusLevels.available, summary: 'All dependencies are available' },
+ });
+ expect(await service.getDependenciesStatus$('c').pipe(first()).toPromise()).toEqual({
+ a: { level: ServiceStatusLevels.available, summary: 'All dependencies are available' },
+ b: { level: ServiceStatusLevels.available, summary: 'All dependencies are available' },
+ });
+ });
+
+ it('uses the manually set status level if plugin specifies one', async () => {
+ const service = new PluginsStatusService({ core$: coreOneDegraded$, pluginDependencies });
+ service.set('a', of({ level: ServiceStatusLevels.available, summary: 'a status' }));
+
+ expect(await service.getDependenciesStatus$('c').pipe(first()).toPromise()).toEqual({
+ a: { level: ServiceStatusLevels.available, summary: 'a status' }, // a is available depsite savedObjects being degraded
+ b: {
+ level: ServiceStatusLevels.degraded,
+ summary: '[savedObjects]: savedObjects degraded',
+ detail: 'See the status page for more information',
+ meta: expect.any(Object),
+ },
+ });
+ });
+
+ it('throws error if unknown plugin passed', () => {
+ const service = new PluginsStatusService({ core$: coreAllAvailable$, pluginDependencies });
+ expect(() => {
+ service.getDependenciesStatus$('dont-exist');
+ }).toThrowError();
+ });
+
+ it('debounces events in quick succession', async () => {
+ const service = new PluginsStatusService({
+ core$: coreAllAvailable$,
+ pluginDependencies,
+ });
+ const available: ServiceStatus = {
+ level: ServiceStatusLevels.available,
+ summary: 'a available',
+ };
+ const degraded: ServiceStatus = {
+ level: ServiceStatusLevels.degraded,
+ summary: 'a degraded',
+ };
+ const pluginA$ = new BehaviorSubject(available);
+ service.set('a', pluginA$);
+
+ const statusUpdates: Array> = [];
+ const subscription = service
+ .getDependenciesStatus$('b')
+ .subscribe((status) => statusUpdates.push(status));
+ const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
+
+ pluginA$.next(degraded);
+ pluginA$.next(available);
+ pluginA$.next(degraded);
+ pluginA$.next(available);
+ pluginA$.next(degraded);
+ pluginA$.next(available);
+ pluginA$.next(degraded);
+ // Waiting for the debounce timeout should cut a new update
+ await delay(500);
+ pluginA$.next(available);
+ await delay(500);
+ subscription.unsubscribe();
+
+ expect(statusUpdates).toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "a": Object {
+ "level": degraded,
+ "summary": "a degraded",
+ },
+ },
+ Object {
+ "a": Object {
+ "level": available,
+ "summary": "a available",
+ },
+ },
+ ]
+ `);
+ });
+ });
+});
diff --git a/src/core/server/status/plugins_status.ts b/src/core/server/status/plugins_status.ts
new file mode 100644
index 0000000000000..113d59b327c11
--- /dev/null
+++ b/src/core/server/status/plugins_status.ts
@@ -0,0 +1,98 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { BehaviorSubject, Observable, combineLatest, of } from 'rxjs';
+import { map, distinctUntilChanged, switchMap, debounceTime } from 'rxjs/operators';
+import { isDeepStrictEqual } from 'util';
+
+import { PluginName } from '../plugins';
+import { ServiceStatus, CoreStatus } from './types';
+import { getSummaryStatus } from './get_summary_status';
+
+interface Deps {
+ core$: Observable;
+ pluginDependencies: ReadonlyMap;
+}
+
+export class PluginsStatusService {
+ private readonly pluginStatuses = new Map>();
+ private readonly update$ = new BehaviorSubject(true);
+ constructor(private readonly deps: Deps) {}
+
+ public set(plugin: PluginName, status$: Observable) {
+ this.pluginStatuses.set(plugin, status$);
+ this.update$.next(true); // trigger all existing Observables to update from the new source Observable
+ }
+
+ public getAll$(): Observable> {
+ return this.getPluginStatuses$([...this.deps.pluginDependencies.keys()]);
+ }
+
+ public getDependenciesStatus$(plugin: PluginName): Observable> {
+ const dependencies = this.deps.pluginDependencies.get(plugin);
+ if (!dependencies) {
+ throw new Error(`Unknown plugin: ${plugin}`);
+ }
+
+ return this.getPluginStatuses$(dependencies).pipe(
+ // Prevent many emissions at once from dependency status resolution from making this too noisy
+ debounceTime(500)
+ );
+ }
+
+ public getDerivedStatus$(plugin: PluginName): Observable {
+ return combineLatest([this.deps.core$, this.getDependenciesStatus$(plugin)]).pipe(
+ map(([coreStatus, pluginStatuses]) => {
+ return getSummaryStatus(
+ [...Object.entries(coreStatus), ...Object.entries(pluginStatuses)],
+ {
+ allAvailableSummary: `All dependencies are available`,
+ }
+ );
+ })
+ );
+ }
+
+ private getPluginStatuses$(plugins: PluginName[]): Observable> {
+ if (plugins.length === 0) {
+ return of({});
+ }
+
+ return this.update$.pipe(
+ switchMap(() => {
+ const pluginStatuses = plugins
+ .map(
+ (depName) =>
+ [depName, this.pluginStatuses.get(depName) ?? this.getDerivedStatus$(depName)] as [
+ PluginName,
+ Observable
+ ]
+ )
+ .map(([pName, status$]) =>
+ status$.pipe(map((status) => [pName, status] as [PluginName, ServiceStatus]))
+ );
+
+ return combineLatest(pluginStatuses).pipe(
+ map((statuses) => Object.fromEntries(statuses)),
+ distinctUntilChanged(isDeepStrictEqual)
+ );
+ })
+ );
+ }
+}
diff --git a/src/core/server/status/status_service.mock.ts b/src/core/server/status/status_service.mock.ts
index 47ef8659b4079..42b3eecdca310 100644
--- a/src/core/server/status/status_service.mock.ts
+++ b/src/core/server/status/status_service.mock.ts
@@ -40,6 +40,9 @@ const createSetupContractMock = () => {
const setupContract: jest.Mocked = {
core$: new BehaviorSubject(availableCoreStatus),
overall$: new BehaviorSubject(available),
+ set: jest.fn(),
+ dependencies$: new BehaviorSubject({}),
+ derivedStatus$: new BehaviorSubject(available),
};
return setupContract;
@@ -50,6 +53,11 @@ const createInternalSetupContractMock = () => {
core$: new BehaviorSubject(availableCoreStatus),
overall$: new BehaviorSubject(available),
isStatusPageAnonymous: jest.fn().mockReturnValue(false),
+ plugins: {
+ set: jest.fn(),
+ getDependenciesStatus$: jest.fn(),
+ getDerivedStatus$: jest.fn(),
+ },
};
return setupContract;
diff --git a/src/core/server/status/status_service.test.ts b/src/core/server/status/status_service.test.ts
index 863fe34e8ecea..dcb1e0a559f5d 100644
--- a/src/core/server/status/status_service.test.ts
+++ b/src/core/server/status/status_service.test.ts
@@ -34,6 +34,7 @@ describe('StatusService', () => {
service = new StatusService(mockCoreContext.create());
});
+ const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
const available: ServiceStatus = {
level: ServiceStatusLevels.available,
summary: 'Available',
@@ -53,6 +54,7 @@ describe('StatusService', () => {
savedObjects: {
status$: of(degraded),
},
+ pluginDependencies: new Map(),
});
expect(await setup.core$.pipe(first()).toPromise()).toEqual({
elasticsearch: available,
@@ -68,6 +70,7 @@ describe('StatusService', () => {
savedObjects: {
status$: of(degraded),
},
+ pluginDependencies: new Map(),
});
const subResult1 = await setup.core$.pipe(first()).toPromise();
const subResult2 = await setup.core$.pipe(first()).toPromise();
@@ -96,6 +99,7 @@ describe('StatusService', () => {
savedObjects: {
status$: savedObjects$,
},
+ pluginDependencies: new Map(),
});
const statusUpdates: CoreStatus[] = [];
@@ -158,6 +162,7 @@ describe('StatusService', () => {
savedObjects: {
status$: of(degraded),
},
+ pluginDependencies: new Map(),
});
expect(await setup.overall$.pipe(first()).toPromise()).toMatchObject({
level: ServiceStatusLevels.degraded,
@@ -173,6 +178,7 @@ describe('StatusService', () => {
savedObjects: {
status$: of(degraded),
},
+ pluginDependencies: new Map(),
});
const subResult1 = await setup.overall$.pipe(first()).toPromise();
const subResult2 = await setup.overall$.pipe(first()).toPromise();
@@ -201,26 +207,95 @@ describe('StatusService', () => {
savedObjects: {
status$: savedObjects$,
},
+ pluginDependencies: new Map(),
});
const statusUpdates: ServiceStatus[] = [];
const subscription = setup.overall$.subscribe((status) => statusUpdates.push(status));
+ // Wait for timers to ensure that duplicate events are still filtered out regardless of debouncing.
elasticsearch$.next(available);
+ await delay(500);
elasticsearch$.next(available);
+ await delay(500);
elasticsearch$.next({
level: ServiceStatusLevels.available,
summary: `Wow another summary`,
});
+ await delay(500);
savedObjects$.next(degraded);
+ await delay(500);
savedObjects$.next(available);
+ await delay(500);
savedObjects$.next(available);
+ await delay(500);
subscription.unsubscribe();
expect(statusUpdates).toMatchInlineSnapshot(`
Array [
Object {
+ "detail": "See the status page for more information",
"level": degraded,
+ "meta": Object {
+ "affectedServices": Object {
+ "savedObjects": Object {
+ "level": degraded,
+ "summary": "This is degraded!",
+ },
+ },
+ },
+ "summary": "[savedObjects]: This is degraded!",
+ },
+ Object {
+ "level": available,
+ "summary": "All services are available",
+ },
+ ]
+ `);
+ });
+
+ it('debounces events in quick succession', async () => {
+ const savedObjects$ = new BehaviorSubject(available);
+ const setup = await service.setup({
+ elasticsearch: {
+ status$: new BehaviorSubject(available),
+ },
+ savedObjects: {
+ status$: savedObjects$,
+ },
+ pluginDependencies: new Map(),
+ });
+
+ const statusUpdates: ServiceStatus[] = [];
+ const subscription = setup.overall$.subscribe((status) => statusUpdates.push(status));
+
+ // All of these should debounced into a single `available` status
+ savedObjects$.next(degraded);
+ savedObjects$.next(available);
+ savedObjects$.next(degraded);
+ savedObjects$.next(available);
+ savedObjects$.next(degraded);
+ savedObjects$.next(available);
+ savedObjects$.next(degraded);
+ // Waiting for the debounce timeout should cut a new update
+ await delay(500);
+ savedObjects$.next(available);
+ await delay(500);
+ subscription.unsubscribe();
+
+ expect(statusUpdates).toMatchInlineSnapshot(`
+ Array [
+ Object {
+ "detail": "See the status page for more information",
+ "level": degraded,
+ "meta": Object {
+ "affectedServices": Object {
+ "savedObjects": Object {
+ "level": degraded,
+ "summary": "This is degraded!",
+ },
+ },
+ },
"summary": "[savedObjects]: This is degraded!",
},
Object {
diff --git a/src/core/server/status/status_service.ts b/src/core/server/status/status_service.ts
index aea335e64babf..8fe65eddb61d3 100644
--- a/src/core/server/status/status_service.ts
+++ b/src/core/server/status/status_service.ts
@@ -18,7 +18,7 @@
*/
import { Observable, combineLatest } from 'rxjs';
-import { map, distinctUntilChanged, shareReplay, take } from 'rxjs/operators';
+import { map, distinctUntilChanged, shareReplay, take, debounceTime } from 'rxjs/operators';
import { isDeepStrictEqual } from 'util';
import { CoreService } from '../../types';
@@ -26,13 +26,16 @@ import { CoreContext } from '../core_context';
import { Logger } from '../logging';
import { InternalElasticsearchServiceSetup } from '../elasticsearch';
import { InternalSavedObjectsServiceSetup } from '../saved_objects';
+import { PluginName } from '../plugins';
import { config, StatusConfigType } from './status_config';
import { ServiceStatus, CoreStatus, InternalStatusServiceSetup } from './types';
import { getSummaryStatus } from './get_summary_status';
+import { PluginsStatusService } from './plugins_status';
interface SetupDeps {
elasticsearch: Pick;
+ pluginDependencies: ReadonlyMap;
savedObjects: Pick;
}
@@ -40,26 +43,44 @@ export class StatusService implements CoreService {
private readonly logger: Logger;
private readonly config$: Observable;
+ private pluginsStatus?: PluginsStatusService;
+
constructor(coreContext: CoreContext) {
this.logger = coreContext.logger.get('status');
this.config$ = coreContext.configService.atPath(config.path);
}
- public async setup(core: SetupDeps) {
+ public async setup({ elasticsearch, pluginDependencies, savedObjects }: SetupDeps) {
const statusConfig = await this.config$.pipe(take(1)).toPromise();
- const core$ = this.setupCoreStatus(core);
- const overall$: Observable = core$.pipe(
- map((coreStatus) => {
- const summary = getSummaryStatus(Object.entries(coreStatus));
+ const core$ = this.setupCoreStatus({ elasticsearch, savedObjects });
+ this.pluginsStatus = new PluginsStatusService({ core$, pluginDependencies });
+
+ const overall$: Observable = combineLatest(
+ core$,
+ this.pluginsStatus.getAll$()
+ ).pipe(
+ // Prevent many emissions at once from dependency status resolution from making this too noisy
+ debounceTime(500),
+ map(([coreStatus, pluginsStatus]) => {
+ const summary = getSummaryStatus([
+ ...Object.entries(coreStatus),
+ ...Object.entries(pluginsStatus),
+ ]);
this.logger.debug(`Recalculated overall status`, { status: summary });
return summary;
}),
- distinctUntilChanged(isDeepStrictEqual)
+ distinctUntilChanged(isDeepStrictEqual),
+ shareReplay(1)
);
return {
core$,
overall$,
+ plugins: {
+ set: this.pluginsStatus.set.bind(this.pluginsStatus),
+ getDependenciesStatus$: this.pluginsStatus.getDependenciesStatus$.bind(this.pluginsStatus),
+ getDerivedStatus$: this.pluginsStatus.getDerivedStatus$.bind(this.pluginsStatus),
+ },
isStatusPageAnonymous: () => statusConfig.allowAnonymous,
};
}
@@ -68,7 +89,10 @@ export class StatusService implements CoreService {
public stop() {}
- private setupCoreStatus({ elasticsearch, savedObjects }: SetupDeps): Observable {
+ private setupCoreStatus({
+ elasticsearch,
+ savedObjects,
+ }: Pick): Observable {
return combineLatest([elasticsearch.status$, savedObjects.status$]).pipe(
map(([elasticsearchStatus, savedObjectsStatus]) => ({
elasticsearch: elasticsearchStatus,
diff --git a/src/core/server/status/types.ts b/src/core/server/status/types.ts
index 2ecf11deb2960..f884b80316fa8 100644
--- a/src/core/server/status/types.ts
+++ b/src/core/server/status/types.ts
@@ -19,6 +19,7 @@
import { Observable } from 'rxjs';
import { deepFreeze } from '../../utils';
+import { PluginName } from '../plugins';
/**
* The current status of a service at a point in time.
@@ -116,6 +117,60 @@ export interface CoreStatus {
/**
* API for accessing status of Core and this plugin's dependencies as well as for customizing this plugin's status.
+ *
+ * @remarks
+ * By default, a plugin inherits it's current status from the most severe status level of any Core services and any
+ * plugins that it depends on. This default status is available on the
+ * {@link ServiceStatusSetup.derivedStatus$ | core.status.derviedStatus$} API.
+ *
+ * Plugins may customize their status calculation by calling the {@link ServiceStatusSetup.set | core.status.set} API
+ * with an Observable. Within this Observable, a plugin may choose to only depend on the status of some of its
+ * dependencies, to ignore severe status levels of particular Core services they are not concerned with, or to make its
+ * status dependent on other external services.
+ *
+ * @example
+ * Customize a plugin's status to only depend on the status of SavedObjects:
+ * ```ts
+ * core.status.set(
+ * core.status.core$.pipe(
+ * . map((coreStatus) => {
+ * return coreStatus.savedObjects;
+ * }) ;
+ * );
+ * );
+ * ```
+ *
+ * @example
+ * Customize a plugin's status to include an external service:
+ * ```ts
+ * const externalStatus$ = interval(1000).pipe(
+ * switchMap(async () => {
+ * const resp = await fetch(`https://myexternaldep.com/_healthz`);
+ * const body = await resp.json();
+ * if (body.ok) {
+ * return of({ level: ServiceStatusLevels.available, summary: 'External Service is up'});
+ * } else {
+ * return of({ level: ServiceStatusLevels.available, summary: 'External Service is unavailable'});
+ * }
+ * }),
+ * catchError((error) => {
+ * of({ level: ServiceStatusLevels.unavailable, summary: `External Service is down`, meta: { error }})
+ * })
+ * );
+ *
+ * core.status.set(
+ * combineLatest([core.status.derivedStatus$, externalStatus$]).pipe(
+ * map(([derivedStatus, externalStatus]) => {
+ * if (externalStatus.level > derivedStatus) {
+ * return externalStatus;
+ * } else {
+ * return derivedStatus;
+ * }
+ * })
+ * )
+ * );
+ * ```
+ *
* @public
*/
export interface StatusServiceSetup {
@@ -134,9 +189,43 @@ export interface StatusServiceSetup {
* only depend on the statuses of {@link StatusServiceSetup.core$ | Core} or their dependencies.
*/
overall$: Observable;
+
+ /**
+ * Allows a plugin to specify a custom status dependent on its own criteria.
+ * Completely overrides the default inherited status.
+ *
+ * @remarks
+ * See the {@link StatusServiceSetup.derivedStatus$} API for leveraging the default status
+ * calculation that is provided by Core.
+ */
+ set(status$: Observable): void;
+
+ /**
+ * Current status for all plugins this plugin depends on.
+ * Each key of the `Record` is a plugin id.
+ */
+ dependencies$: Observable>;
+
+ /**
+ * The status of this plugin as derived from its dependencies.
+ *
+ * @remarks
+ * By default, plugins inherit this derived status from their dependencies.
+ * Calling {@link StatusSetup.set} overrides this default status.
+ *
+ * This may emit multliple times for a single status change event as propagates
+ * through the dependency tree
+ */
+ derivedStatus$: Observable;
}
/** @internal */
-export interface InternalStatusServiceSetup extends StatusServiceSetup {
+export interface InternalStatusServiceSetup extends Pick {
isStatusPageAnonymous: () => boolean;
+ // Namespaced under `plugins` key to improve clarity that these are APIs for plugins specifically.
+ plugins: {
+ set(plugin: PluginName, status$: Observable): void;
+ getDependenciesStatus$(plugin: PluginName): Observable