Merge branch 'master' into reporting/test-better
This commit is contained in:
commit
206fd14b77
472 changed files with 9812 additions and 4619 deletions
3
.github/CODEOWNERS
vendored
3
.github/CODEOWNERS
vendored
|
@ -202,7 +202,8 @@
|
|||
# Endpoint
|
||||
/x-pack/plugins/endpoint/ @elastic/endpoint-app-team
|
||||
/x-pack/test/api_integration/apis/endpoint/ @elastic/endpoint-app-team
|
||||
/x-pack/test/functional/apps/endpoint/ @elastic/endpoint-app-team
|
||||
/x-pack/test/functional_endpoint/ @elastic/endpoint-app-team
|
||||
/x-pack/test/functional_endpoint_ingest_failure/ @elastic/endpoint-app-team
|
||||
/x-pack/test/functional/es_archives/endpoint/ @elastic/endpoint-app-team
|
||||
|
||||
# SIEM
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
"src/legacy/core_plugins/management",
|
||||
"src/plugins/management"
|
||||
],
|
||||
"indexPatternManagement": "src/plugins/index_pattern_management",
|
||||
"advancedSettings": "src/plugins/advanced_settings",
|
||||
"kibana_legacy": "src/plugins/kibana_legacy",
|
||||
"kibana_react": "src/legacy/core_plugins/kibana_react",
|
||||
|
|
97
docs/apm/apm-alerts.asciidoc
Normal file
97
docs/apm/apm-alerts.asciidoc
Normal file
|
@ -0,0 +1,97 @@
|
|||
[role="xpack"]
|
||||
[[apm-alerts]]
|
||||
=== Create an alert
|
||||
|
||||
beta::[]
|
||||
|
||||
The APM app is integrated with Kibana's {kibana-ref}/alerting-getting-started.html[alerting and actions] feature.
|
||||
It provides a set of built-in **actions** and APM specific threshold **alerts** for you to use,
|
||||
and allows all alerts to be centrally managed from <<management,Kibana Management>>.
|
||||
|
||||
[role="screenshot"]
|
||||
image::apm/images/apm-alert.png[Create an alert in the APM app]
|
||||
|
||||
There are two different types of threshold alerts: transaction duration, and error rate.
|
||||
Below, we'll create one of each.
|
||||
|
||||
[float]
|
||||
[[apm-create-transaction-alert]]
|
||||
=== Create a transaction duration alert
|
||||
|
||||
This guide creates an alert for the `opbeans-java` service based on the following criteria:
|
||||
|
||||
* Transaction type: `transaction.type:request`
|
||||
* Average request is above `1500ms` for the last 5 minutes
|
||||
* Check every 10 minutes, and repeat the alert every 30 minutes
|
||||
* Send the alert via Slack
|
||||
|
||||
From the APM app, navigate to the `opbeans-java` service and select
|
||||
**Alerts** > **Create threshold alert** > **Transaction duration**.
|
||||
|
||||
The name of your alert will automatically be set as `Transaction duration | opbeans-java`,
|
||||
and the alert will be tagged with `apm` and `service.name:opbeans-java`.
|
||||
Feel free to edit either of these defaults.
|
||||
|
||||
Based on the alert criteria, define the following alert details:
|
||||
|
||||
* **Check every** - `10 minutes`
|
||||
* **Notify every** - `30 minutes`
|
||||
* **TYPE** - `request`
|
||||
* **WHEN** - `avg`
|
||||
* **IS ABOVE** - `1500ms`
|
||||
* **FOR THE LAST** - `5 minutes`
|
||||
|
||||
Select an action type.
|
||||
Multiple action types can be selected, but in this example we want to post to a slack channel.
|
||||
Select **Slack** > **Create a connector**.
|
||||
Enter a name for the connector,
|
||||
and paste the webhook URL.
|
||||
See Slack's webhook documentation if you need to create one.
|
||||
|
||||
Select **Save**. The alert has been created and is now active!
|
||||
|
||||
[float]
|
||||
[[apm-create-error-alert]]
|
||||
=== Create an error rate alert
|
||||
|
||||
This guide creates an alert for the `opbeans-python` service based on the following criteria:
|
||||
|
||||
* Error rate is above 25 for the last minute
|
||||
* Check every 1 minute, and repeat the alert every 10 minutes
|
||||
* Send the alert via email to the `opbeans-python` team
|
||||
|
||||
From the APM app, navigate to the `opbeans-python` service and select
|
||||
**Alerts** > **Create threshold alert** > **Error rate**.
|
||||
|
||||
The name of your alert will automatically be set as `Error rate | opbeans-python`,
|
||||
and the alert will be tagged with `apm` and `service.name:opbeans-python`.
|
||||
Feel free to edit either of these defaults.
|
||||
|
||||
Based on the alert criteria, define the following alert details:
|
||||
|
||||
* **Check every** - `1 minute`
|
||||
* **Notify every** - `10 minutes`
|
||||
* **IS ABOVE** - `25 errors`
|
||||
* **FOR THE LAST** - `1 minute`
|
||||
|
||||
Select the **Email** action type and click **Create a connector**.
|
||||
Fill out the required details: sender, host, port, etc., and click **save**.
|
||||
|
||||
Select **Save**. The alert has been created and is now active!
|
||||
|
||||
[float]
|
||||
[[apm-alert-manage]]
|
||||
=== Manage alerts and actions
|
||||
|
||||
From the APM app, select **Alerts** > **View active alerts** to be taken to the Kibana alerts and actions management page.
|
||||
From this page, you can create, edit, disable, mute, and delete alerts, and create, edit, and disable connectors.
|
||||
|
||||
[float]
|
||||
[[apm-alert-more-info]]
|
||||
=== More information
|
||||
|
||||
See {kibana-ref}/alerting-getting-started.html[alerting and actions] for more information.
|
||||
|
||||
NOTE: If you are using an **on-premise** Elastic Stack deployment with security,
|
||||
TLS must be configured for communication between Elasticsearch and Kibana.
|
||||
More information is in the alerting {kibana-ref}/alerting-getting-started.html#alerting-setup-prerequisites[prerequisites].
|
BIN
docs/apm/images/apm-alert.png
Normal file
BIN
docs/apm/images/apm-alert.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 643 KiB |
|
@ -34,4 +34,4 @@ which indicates the next transaction in the trace.
|
|||
These transactions can be expanded and viewed in detail by clicking on them.
|
||||
|
||||
After exploring these traces,
|
||||
you can return to the full trace by clicking *View full trace* in the upper right hand corner of the page.
|
||||
you can return to the full trace by clicking *View full trace*.
|
||||
|
|
|
@ -105,6 +105,7 @@ image::apm/images/apm-transaction-duration-dist.png[Example view of transactions
|
|||
|
||||
This graph shows a typical distribution, and indicates most of our requests were served quickly - awesome!
|
||||
It's the requests on the right, the ones taking longer than average, that we probably want to focus on.
|
||||
|
||||
When you select one of these buckets,
|
||||
you're presented with up to ten trace samples.
|
||||
Each sample has a span timeline waterfall that shows what a typical request in that bucket was doing.
|
||||
|
|
|
@ -15,6 +15,7 @@ APM is available via the navigation sidebar in {Kib}.
|
|||
* <<spans>>
|
||||
* <<errors>>
|
||||
* <<metrics>>
|
||||
* <<apm-alerts>>
|
||||
* <<machine-learning-integration>>
|
||||
* <<agent-configuration>>
|
||||
* <<advanced-queries>>
|
||||
|
@ -37,6 +38,8 @@ include::errors.asciidoc[]
|
|||
|
||||
include::metrics.asciidoc[]
|
||||
|
||||
include::apm-alerts.asciidoc[]
|
||||
|
||||
include::agent-configuration.asciidoc[]
|
||||
|
||||
include::custom-links.asciidoc[]
|
||||
|
|
|
@ -76,7 +76,7 @@ After you've added the workpad to your website, you can change the autoplay and
|
|||
|
||||
To change the autoplay settings:
|
||||
|
||||
. In the lower right corner of the shareable workpad, click the settings icon.
|
||||
. Click the settings icon.
|
||||
|
||||
. Click *Auto Play*, then change the settings.
|
||||
+
|
||||
|
@ -85,7 +85,7 @@ image::images/canvas_share_autoplay_480.gif[Autoplay settings]
|
|||
|
||||
To change the toolbar settings:
|
||||
|
||||
. In the lower right corner, click the settings icon.
|
||||
. Click the settings icon.
|
||||
|
||||
. Click *Toolbar*, then change the settings.
|
||||
+
|
||||
|
|
|
@ -18,7 +18,7 @@ Your first step to working with Canvas is to create a workpad.
|
|||
|
||||
. Click *Create workpad*.
|
||||
|
||||
. To add a *Name* for your workpad, use the editor on the right. For example, `My Canvas Workpad`.
|
||||
. To add a *Name* for your workpad, use the editor. For example, `My Canvas Workpad`.
|
||||
|
||||
[float]
|
||||
=== Customize your workpad with images
|
||||
|
@ -29,7 +29,7 @@ To customize your workpad to look the way you want, add your own images.
|
|||
+
|
||||
The default Elastic logo image appears on your page.
|
||||
|
||||
. To replace the Elastic logo with your own image, select the image, then use the editor on the right.
|
||||
. To replace the Elastic logo with your own image, select the image, then use the editor.
|
||||
|
||||
. To move the image, click and drag it to your preferred location.
|
||||
|
||||
|
@ -73,7 +73,7 @@ You'll notice that the error is gone, but the number could use some formatting.
|
|||
|
||||
. To format the number, use the Canvas expression language.
|
||||
|
||||
.. In the lower right corner, click *Expression editor*.
|
||||
.. Click *Expression editor*.
|
||||
+
|
||||
You're now looking at the raw data syntax that Canvas uses to display the element.
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ Organize your ideas onto separate pages by adding more pages.
|
|||
|
||||
. Click *Page 1*, then click *+*.
|
||||
|
||||
. On the *Page* editor panel on the right, select the page transition from the *Transition* dropdown.
|
||||
. On the *Page* editor panel, select the page transition from the *Transition* dropdown.
|
||||
+
|
||||
[role="screenshot"]
|
||||
image::images/canvas-add-pages.gif[Add pages]
|
||||
|
|
BIN
docs/dev-tools/painlesslab/images/painless-lab.png
Normal file
BIN
docs/dev-tools/painlesslab/images/painless-lab.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 216 KiB |
17
docs/dev-tools/painlesslab/index.asciidoc
Normal file
17
docs/dev-tools/painlesslab/index.asciidoc
Normal file
|
@ -0,0 +1,17 @@
|
|||
[role="xpack"]
|
||||
[[painlesslab]]
|
||||
== Painless Lab
|
||||
|
||||
beta::[]
|
||||
|
||||
The Painless Lab is an interactive code editor that lets you test and
|
||||
debug {ref}/modules-scripting-painless.html[Painless scripts] in real-time.
|
||||
You can use the Painless scripting
|
||||
language to create <<scripted-fields, {kib} scripted fields>>,
|
||||
process {ref}/docs-reindex.html[reindexed data], define complex
|
||||
<<watcher-create-advanced-watch, Watcher conditions>>,
|
||||
and work with data in other contexts.
|
||||
|
||||
To get started, go to *Dev Tools > Painless Lab*.
|
||||
|
||||
image::dev-tools/painlesslab/images/painless-lab.png[Painless Lab]
|
|
@ -23,6 +23,7 @@ export interface CoreSetup<TPluginsStart extends object = object, TStart = unkno
|
|||
| [http](./kibana-plugin-core-server.coresetup.http.md) | <code>HttpServiceSetup</code> | [HttpServiceSetup](./kibana-plugin-core-server.httpservicesetup.md) |
|
||||
| [metrics](./kibana-plugin-core-server.coresetup.metrics.md) | <code>MetricsServiceSetup</code> | [MetricsServiceSetup](./kibana-plugin-core-server.metricsservicesetup.md) |
|
||||
| [savedObjects](./kibana-plugin-core-server.coresetup.savedobjects.md) | <code>SavedObjectsServiceSetup</code> | [SavedObjectsServiceSetup](./kibana-plugin-core-server.savedobjectsservicesetup.md) |
|
||||
| [status](./kibana-plugin-core-server.coresetup.status.md) | <code>StatusServiceSetup</code> | [StatusServiceSetup](./kibana-plugin-core-server.statusservicesetup.md) |
|
||||
| [uiSettings](./kibana-plugin-core-server.coresetup.uisettings.md) | <code>UiSettingsServiceSetup</code> | [UiSettingsServiceSetup](./kibana-plugin-core-server.uisettingsservicesetup.md) |
|
||||
| [uuid](./kibana-plugin-core-server.coresetup.uuid.md) | <code>UuidServiceSetup</code> | [UuidServiceSetup](./kibana-plugin-core-server.uuidservicesetup.md) |
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CoreSetup](./kibana-plugin-core-server.coresetup.md) > [status](./kibana-plugin-core-server.coresetup.status.md)
|
||||
|
||||
## CoreSetup.status property
|
||||
|
||||
[StatusServiceSetup](./kibana-plugin-core-server.statusservicesetup.md)
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
status: StatusServiceSetup;
|
||||
```
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CoreStatus](./kibana-plugin-core-server.corestatus.md) > [elasticsearch](./kibana-plugin-core-server.corestatus.elasticsearch.md)
|
||||
|
||||
## CoreStatus.elasticsearch property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
elasticsearch: ServiceStatus;
|
||||
```
|
|
@ -0,0 +1,21 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CoreStatus](./kibana-plugin-core-server.corestatus.md)
|
||||
|
||||
## CoreStatus interface
|
||||
|
||||
Status of core services.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface CoreStatus
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [elasticsearch](./kibana-plugin-core-server.corestatus.elasticsearch.md) | <code>ServiceStatus</code> | |
|
||||
| [savedObjects](./kibana-plugin-core-server.corestatus.savedobjects.md) | <code>ServiceStatus</code> | |
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CoreStatus](./kibana-plugin-core-server.corestatus.md) > [savedObjects](./kibana-plugin-core-server.corestatus.savedobjects.md)
|
||||
|
||||
## CoreStatus.savedObjects property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
savedObjects: ServiceStatus;
|
||||
```
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchStatusMeta](./kibana-plugin-core-server.elasticsearchstatusmeta.md) > [incompatibleNodes](./kibana-plugin-core-server.elasticsearchstatusmeta.incompatiblenodes.md)
|
||||
|
||||
## ElasticsearchStatusMeta.incompatibleNodes property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
incompatibleNodes: NodesVersionCompatibility['incompatibleNodes'];
|
||||
```
|
|
@ -0,0 +1,20 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchStatusMeta](./kibana-plugin-core-server.elasticsearchstatusmeta.md)
|
||||
|
||||
## ElasticsearchStatusMeta interface
|
||||
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface ElasticsearchStatusMeta
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [incompatibleNodes](./kibana-plugin-core-server.elasticsearchstatusmeta.incompatiblenodes.md) | <code>NodesVersionCompatibility['incompatibleNodes']</code> | |
|
||||
| [warningNodes](./kibana-plugin-core-server.elasticsearchstatusmeta.warningnodes.md) | <code>NodesVersionCompatibility['warningNodes']</code> | |
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchStatusMeta](./kibana-plugin-core-server.elasticsearchstatusmeta.md) > [warningNodes](./kibana-plugin-core-server.elasticsearchstatusmeta.warningnodes.md)
|
||||
|
||||
## ElasticsearchStatusMeta.warningNodes property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
warningNodes: NodesVersionCompatibility['warningNodes'];
|
||||
```
|
|
@ -66,6 +66,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| [ContextSetup](./kibana-plugin-core-server.contextsetup.md) | An object that handles registration of context providers and configuring handlers with context. |
|
||||
| [CoreSetup](./kibana-plugin-core-server.coresetup.md) | Context passed to the plugins <code>setup</code> method. |
|
||||
| [CoreStart](./kibana-plugin-core-server.corestart.md) | Context passed to the plugins <code>start</code> method. |
|
||||
| [CoreStatus](./kibana-plugin-core-server.corestatus.md) | Status of core services. |
|
||||
| [CustomHttpResponseOptions](./kibana-plugin-core-server.customhttpresponseoptions.md) | HTTP response parameters for a response with adjustable status code. |
|
||||
| [DeprecationAPIClientParams](./kibana-plugin-core-server.deprecationapiclientparams.md) | |
|
||||
| [DeprecationAPIResponse](./kibana-plugin-core-server.deprecationapiresponse.md) | |
|
||||
|
@ -75,6 +76,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| [ElasticsearchError](./kibana-plugin-core-server.elasticsearcherror.md) | |
|
||||
| [ElasticsearchServiceSetup](./kibana-plugin-core-server.elasticsearchservicesetup.md) | |
|
||||
| [ElasticsearchServiceStart](./kibana-plugin-core-server.elasticsearchservicestart.md) | |
|
||||
| [ElasticsearchStatusMeta](./kibana-plugin-core-server.elasticsearchstatusmeta.md) | |
|
||||
| [EnvironmentMode](./kibana-plugin-core-server.environmentmode.md) | |
|
||||
| [ErrorHttpResponseOptions](./kibana-plugin-core-server.errorhttpresponseoptions.md) | HTTP response parameters |
|
||||
| [FakeRequest](./kibana-plugin-core-server.fakerequest.md) | Fake request object created manually by Kibana plugins. |
|
||||
|
@ -101,6 +103,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| [LoggerFactory](./kibana-plugin-core-server.loggerfactory.md) | The single purpose of <code>LoggerFactory</code> interface is to define a way to retrieve a context-based logger instance. |
|
||||
| [LogMeta](./kibana-plugin-core-server.logmeta.md) | Contextual metadata |
|
||||
| [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. |
|
||||
| [OnPreResponseExtensions](./kibana-plugin-core-server.onpreresponseextensions.md) | Additional data to extend a response. |
|
||||
|
@ -162,15 +165,18 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md) | Options to control the "resolve import" operation. |
|
||||
| [SavedObjectsServiceSetup](./kibana-plugin-core-server.savedobjectsservicesetup.md) | Saved Objects is Kibana's data persistence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceSetup API exposes methods for registering Saved Object types, creating and registering Saved Object client wrappers and factories. |
|
||||
| [SavedObjectsServiceStart](./kibana-plugin-core-server.savedobjectsservicestart.md) | Saved Objects is Kibana's data persisentence mechanism allowing plugins to use Elasticsearch for storing and querying state. The SavedObjectsServiceStart API provides a scoped Saved Objects client for interacting with Saved Objects. |
|
||||
| [SavedObjectStatusMeta](./kibana-plugin-core-server.savedobjectstatusmeta.md) | Meta information about the SavedObjectService's status. Available to plugins via [CoreSetup.status](./kibana-plugin-core-server.coresetup.status.md)<!-- -->. |
|
||||
| [SavedObjectsType](./kibana-plugin-core-server.savedobjectstype.md) | |
|
||||
| [SavedObjectsTypeManagementDefinition](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.md) | Configuration options for the [type](./kibana-plugin-core-server.savedobjectstype.md)<!-- -->'s management section. |
|
||||
| [SavedObjectsTypeMappingDefinition](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) | Describe a saved object type mapping. |
|
||||
| [SavedObjectsUpdateOptions](./kibana-plugin-core-server.savedobjectsupdateoptions.md) | |
|
||||
| [SavedObjectsUpdateResponse](./kibana-plugin-core-server.savedobjectsupdateresponse.md) | |
|
||||
| [ServiceStatus](./kibana-plugin-core-server.servicestatus.md) | The current status of a service at a point in time. |
|
||||
| [SessionCookieValidationResult](./kibana-plugin-core-server.sessioncookievalidationresult.md) | Return type from a function to validate cookie contents. |
|
||||
| [SessionStorage](./kibana-plugin-core-server.sessionstorage.md) | Provides an interface to store and retrieve data across requests. |
|
||||
| [SessionStorageCookieOptions](./kibana-plugin-core-server.sessionstoragecookieoptions.md) | Configuration used to create HTTP session storage based on top of cookie mechanism. |
|
||||
| [SessionStorageFactory](./kibana-plugin-core-server.sessionstoragefactory.md) | SessionStorage factory to bind one to an incoming request |
|
||||
| [StatusServiceSetup](./kibana-plugin-core-server.statusservicesetup.md) | API for accessing status of Core and this plugin's dependencies as well as for customizing this plugin's status. |
|
||||
| [StringValidationRegex](./kibana-plugin-core-server.stringvalidationregex.md) | StringValidation with regex object |
|
||||
| [StringValidationRegexString](./kibana-plugin-core-server.stringvalidationregexstring.md) | StringValidation as regex string |
|
||||
| [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) | UiSettings parameters defined by the plugins. |
|
||||
|
@ -184,6 +190,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| Variable | Description |
|
||||
| --- | --- |
|
||||
| [kibanaResponseFactory](./kibana-plugin-core-server.kibanaresponsefactory.md) | Set of helpers used to create <code>KibanaResponse</code> to form HTTP response on an incoming request. Should be returned as a result of [RequestHandler](./kibana-plugin-core-server.requesthandler.md) execution. |
|
||||
| [ServiceStatusLevels](./kibana-plugin-core-server.servicestatuslevels.md) | The current "level" of availability of a service. |
|
||||
| [validBodyOutput](./kibana-plugin-core-server.validbodyoutput.md) | The set of valid body.output |
|
||||
|
||||
## Type Aliases
|
||||
|
@ -256,6 +263,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| [SavedObjectsClientWrapperFactory](./kibana-plugin-core-server.savedobjectsclientwrapperfactory.md) | Describes the factory used to create instances of Saved Objects Client Wrappers. |
|
||||
| [SavedObjectsFieldMapping](./kibana-plugin-core-server.savedobjectsfieldmapping.md) | Describe a [saved object type mapping](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) field.<!-- -->Please refer to [elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html) For the mapping documentation |
|
||||
| [ScopeableRequest](./kibana-plugin-core-server.scopeablerequest.md) | A user credentials container. It accommodates the necessary auth credentials to impersonate the current user.<!-- -->See [KibanaRequest](./kibana-plugin-core-server.kibanarequest.md)<!-- -->. |
|
||||
| [ServiceStatusLevel](./kibana-plugin-core-server.servicestatuslevel.md) | A convenience type that represents the union of each value in [ServiceStatusLevels](./kibana-plugin-core-server.servicestatuslevels.md)<!-- -->. |
|
||||
| [SharedGlobalConfig](./kibana-plugin-core-server.sharedglobalconfig.md) | |
|
||||
| [StartServicesAccessor](./kibana-plugin-core-server.startservicesaccessor.md) | Allows plugins to get access to APIs available in start inside async handlers. Promise will not resolve until Core and plugin dependencies have completed <code>start</code>. This should only be used inside handlers registered during <code>setup</code> that will only be executed after <code>start</code> lifecycle. |
|
||||
| [StringValidation](./kibana-plugin-core-server.stringvalidation.md) | Allows regex objects or a regex string |
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [NodesVersionCompatibility](./kibana-plugin-core-server.nodesversioncompatibility.md) > [incompatibleNodes](./kibana-plugin-core-server.nodesversioncompatibility.incompatiblenodes.md)
|
||||
|
||||
## NodesVersionCompatibility.incompatibleNodes property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
incompatibleNodes: NodeInfo[];
|
||||
```
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [NodesVersionCompatibility](./kibana-plugin-core-server.nodesversioncompatibility.md) > [isCompatible](./kibana-plugin-core-server.nodesversioncompatibility.iscompatible.md)
|
||||
|
||||
## NodesVersionCompatibility.isCompatible property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
isCompatible: boolean;
|
||||
```
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [NodesVersionCompatibility](./kibana-plugin-core-server.nodesversioncompatibility.md) > [kibanaVersion](./kibana-plugin-core-server.nodesversioncompatibility.kibanaversion.md)
|
||||
|
||||
## NodesVersionCompatibility.kibanaVersion property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
kibanaVersion: string;
|
||||
```
|
|
@ -0,0 +1,22 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [NodesVersionCompatibility](./kibana-plugin-core-server.nodesversioncompatibility.md)
|
||||
|
||||
## NodesVersionCompatibility interface
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface NodesVersionCompatibility
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [incompatibleNodes](./kibana-plugin-core-server.nodesversioncompatibility.incompatiblenodes.md) | <code>NodeInfo[]</code> | |
|
||||
| [isCompatible](./kibana-plugin-core-server.nodesversioncompatibility.iscompatible.md) | <code>boolean</code> | |
|
||||
| [kibanaVersion](./kibana-plugin-core-server.nodesversioncompatibility.kibanaversion.md) | <code>string</code> | |
|
||||
| [message](./kibana-plugin-core-server.nodesversioncompatibility.message.md) | <code>string</code> | |
|
||||
| [warningNodes](./kibana-plugin-core-server.nodesversioncompatibility.warningnodes.md) | <code>NodeInfo[]</code> | |
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [NodesVersionCompatibility](./kibana-plugin-core-server.nodesversioncompatibility.md) > [message](./kibana-plugin-core-server.nodesversioncompatibility.message.md)
|
||||
|
||||
## NodesVersionCompatibility.message property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
message?: string;
|
||||
```
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [NodesVersionCompatibility](./kibana-plugin-core-server.nodesversioncompatibility.md) > [warningNodes](./kibana-plugin-core-server.nodesversioncompatibility.warningnodes.md)
|
||||
|
||||
## NodesVersionCompatibility.warningNodes property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
warningNodes: NodeInfo[];
|
||||
```
|
|
@ -0,0 +1,20 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectStatusMeta](./kibana-plugin-core-server.savedobjectstatusmeta.md)
|
||||
|
||||
## SavedObjectStatusMeta interface
|
||||
|
||||
Meta information about the SavedObjectService's status. Available to plugins via [CoreSetup.status](./kibana-plugin-core-server.coresetup.status.md)<!-- -->.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface SavedObjectStatusMeta
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [migratedIndices](./kibana-plugin-core-server.savedobjectstatusmeta.migratedindices.md) | <code>{</code><br/><code> [status: string]: number;</code><br/><code> skipped: number;</code><br/><code> migrated: number;</code><br/><code> }</code> | |
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectStatusMeta](./kibana-plugin-core-server.savedobjectstatusmeta.md) > [migratedIndices](./kibana-plugin-core-server.savedobjectstatusmeta.migratedindices.md)
|
||||
|
||||
## SavedObjectStatusMeta.migratedIndices property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
migratedIndices: {
|
||||
[status: string]: number;
|
||||
skipped: number;
|
||||
migrated: number;
|
||||
};
|
||||
```
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ServiceStatus](./kibana-plugin-core-server.servicestatus.md) > [detail](./kibana-plugin-core-server.servicestatus.detail.md)
|
||||
|
||||
## ServiceStatus.detail property
|
||||
|
||||
A more detailed description of the service status.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
detail?: string;
|
||||
```
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ServiceStatus](./kibana-plugin-core-server.servicestatus.md) > [documentationUrl](./kibana-plugin-core-server.servicestatus.documentationurl.md)
|
||||
|
||||
## ServiceStatus.documentationUrl property
|
||||
|
||||
A URL to open in a new tab about how to resolve or troubleshoot the problem.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
documentationUrl?: string;
|
||||
```
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ServiceStatus](./kibana-plugin-core-server.servicestatus.md) > [level](./kibana-plugin-core-server.servicestatus.level.md)
|
||||
|
||||
## ServiceStatus.level property
|
||||
|
||||
The current availability level of the service.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
level: ServiceStatusLevel;
|
||||
```
|
|
@ -0,0 +1,24 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ServiceStatus](./kibana-plugin-core-server.servicestatus.md)
|
||||
|
||||
## ServiceStatus interface
|
||||
|
||||
The current status of a service at a point in time.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface ServiceStatus<Meta extends Record<string, any> | unknown = unknown>
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [detail](./kibana-plugin-core-server.servicestatus.detail.md) | <code>string</code> | A more detailed description of the service status. |
|
||||
| [documentationUrl](./kibana-plugin-core-server.servicestatus.documentationurl.md) | <code>string</code> | A URL to open in a new tab about how to resolve or troubleshoot the problem. |
|
||||
| [level](./kibana-plugin-core-server.servicestatus.level.md) | <code>ServiceStatusLevel</code> | The current availability level of the service. |
|
||||
| [meta](./kibana-plugin-core-server.servicestatus.meta.md) | <code>Meta</code> | Any JSON-serializable data to be included in the HTTP API response. Useful for providing more fine-grained, machine-readable information about the service status. May include status information for underlying features. |
|
||||
| [summary](./kibana-plugin-core-server.servicestatus.summary.md) | <code>string</code> | A high-level summary of the service status. |
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ServiceStatus](./kibana-plugin-core-server.servicestatus.md) > [meta](./kibana-plugin-core-server.servicestatus.meta.md)
|
||||
|
||||
## ServiceStatus.meta property
|
||||
|
||||
Any JSON-serializable data to be included in the HTTP API response. Useful for providing more fine-grained, machine-readable information about the service status. May include status information for underlying features.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
meta?: Meta;
|
||||
```
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ServiceStatus](./kibana-plugin-core-server.servicestatus.md) > [summary](./kibana-plugin-core-server.servicestatus.summary.md)
|
||||
|
||||
## ServiceStatus.summary property
|
||||
|
||||
A high-level summary of the service status.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
summary: string;
|
||||
```
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ServiceStatusLevel](./kibana-plugin-core-server.servicestatuslevel.md)
|
||||
|
||||
## ServiceStatusLevel type
|
||||
|
||||
A convenience type that represents the union of each value in [ServiceStatusLevels](./kibana-plugin-core-server.servicestatuslevels.md)<!-- -->.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type ServiceStatusLevel = typeof ServiceStatusLevels[keyof typeof ServiceStatusLevels];
|
||||
```
|
|
@ -0,0 +1,37 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ServiceStatusLevels](./kibana-plugin-core-server.servicestatuslevels.md)
|
||||
|
||||
## ServiceStatusLevels variable
|
||||
|
||||
The current "level" of availability of a service.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
ServiceStatusLevels: Readonly<{
|
||||
available: Readonly<{
|
||||
toString: () => "available";
|
||||
valueOf: () => 0;
|
||||
}>;
|
||||
degraded: Readonly<{
|
||||
toString: () => "degraded";
|
||||
valueOf: () => 1;
|
||||
}>;
|
||||
unavailable: Readonly<{
|
||||
toString: () => "unavailable";
|
||||
valueOf: () => 2;
|
||||
}>;
|
||||
critical: Readonly<{
|
||||
toString: () => "critical";
|
||||
valueOf: () => 3;
|
||||
}>;
|
||||
}>
|
||||
```
|
||||
|
||||
## Remarks
|
||||
|
||||
The values implement `valueOf` to allow for easy comparisons between status levels with <<!-- -->, ><!-- -->, etc. Higher values represent higher severities. Note that the default `Array.prototype.sort` implementation does not correctly sort these values.
|
||||
|
||||
A snapshot serializer is available in `src/core/server/test_utils` to ease testing of these values with Jest.
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [StatusServiceSetup](./kibana-plugin-core-server.statusservicesetup.md) > [core$](./kibana-plugin-core-server.statusservicesetup.core_.md)
|
||||
|
||||
## StatusServiceSetup.core$ property
|
||||
|
||||
Current status for all Core services.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
core$: Observable<CoreStatus>;
|
||||
```
|
|
@ -0,0 +1,20 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [StatusServiceSetup](./kibana-plugin-core-server.statusservicesetup.md)
|
||||
|
||||
## StatusServiceSetup interface
|
||||
|
||||
API for accessing status of Core and this plugin's dependencies as well as for customizing this plugin's status.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface StatusServiceSetup
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [core$](./kibana-plugin-core-server.statusservicesetup.core_.md) | <code>Observable<CoreStatus></code> | Current status for all Core services. |
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [createSearchSource](./kibana-plugin-plugins-data-public.createsearchsource.md)
|
||||
|
||||
## createSearchSource variable
|
||||
|
||||
Deserializes a json string and a set of referenced objects to a `SearchSource` instance. Use this method to re-create the search source serialized using `searchSource.serialize`<!-- -->.
|
||||
|
||||
This function is a factory function that returns the actual utility when calling it with the required service dependency (index patterns contract). A pre-wired version is also exposed in the start contract of the data plugin as part of the search service
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
createSearchSource: (indexPatterns: Pick<import("../../index_patterns/index_patterns").IndexPatternsService, "get" | "clearCache" | "getFieldsForTimePattern" | "getFieldsForWildcard" | "getIds" | "getTitles" | "getFields" | "getCache" | "getDefault" | "make">) => (searchSourceJson: string, references: SavedObjectReference[]) => Promise<SearchSource>
|
||||
```
|
|
@ -102,6 +102,7 @@
|
|||
| [castEsToKbnFieldTypeName](./kibana-plugin-plugins-data-public.castestokbnfieldtypename.md) | Get the KbnFieldType name for an esType string |
|
||||
| [connectToQueryState](./kibana-plugin-plugins-data-public.connecttoquerystate.md) | Helper to setup two-way syncing of global data and a state container |
|
||||
| [createSavedQueryService](./kibana-plugin-plugins-data-public.createsavedqueryservice.md) | |
|
||||
| [createSearchSource](./kibana-plugin-plugins-data-public.createsearchsource.md) | Deserializes a json string and a set of referenced objects to a <code>SearchSource</code> instance. Use this method to re-create the search source serialized using <code>searchSource.serialize</code>.<!-- -->This function is a factory function that returns the actual utility when calling it with the required service dependency (index patterns contract). A pre-wired version is also exposed in the start contract of the data plugin as part of the search service |
|
||||
| [ES\_SEARCH\_STRATEGY](./kibana-plugin-plugins-data-public.es_search_strategy.md) | |
|
||||
| [esFilters](./kibana-plugin-plugins-data-public.esfilters.md) | |
|
||||
| [esKuery](./kibana-plugin-plugins-data-public.eskuery.md) | |
|
||||
|
|
|
@ -38,6 +38,7 @@ export declare class SearchSource
|
|||
| [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) | | |
|
||||
| [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 <code>kibanaSavedObjectMeta.searchSourceJSON.index</code> and <code>kibanaSavedObjectMeta.searchSourceJSON.filter[<number>].meta.index</code>.<!-- -->Using <code>createSearchSource</code>, the instance can be re-created. |
|
||||
| [setField(field, value)](./kibana-plugin-plugins-data-public.searchsource.setfield.md) | | |
|
||||
| [setFields(newFields)](./kibana-plugin-plugins-data-public.searchsource.setfields.md) | | |
|
||||
| [setParent(parent, options)](./kibana-plugin-plugins-data-public.searchsource.setparent.md) | | Set a searchSource that this source should inherit from |
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[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[<number>].meta.index`<!-- -->.
|
||||
|
||||
Using `createSearchSource`<!-- -->, the instance can be re-created.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
serialize(): {
|
||||
searchSourceJSON: string;
|
||||
references: SavedObjectReference[];
|
||||
};
|
||||
```
|
||||
<b>Returns:</b>
|
||||
|
||||
`{
|
||||
searchSourceJSON: string;
|
||||
references: SavedObjectReference[];
|
||||
}`
|
||||
|
|
@ -23,7 +23,6 @@
|
|||
| Function | Description |
|
||||
| --- | --- |
|
||||
| [getDefaultSearchParams(config)](./kibana-plugin-plugins-data-server.getdefaultsearchparams.md) | |
|
||||
| [getTotalLoaded({ total, failed, successful })](./kibana-plugin-plugins-data-server.gettotalloaded.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) | |
|
||||
|
|
|
@ -18,9 +18,9 @@ For more information on alerting concepts and the types of alerts and actions av
|
|||
[float]
|
||||
==== Finding alerts
|
||||
|
||||
The *Alerts* tab lists all alerts in the current space, including summary information about their execution frequency, tags, and type.
|
||||
The *Alerts* tab lists all alerts in the current space, including summary information about their execution frequency, tags, and type.
|
||||
|
||||
The *search bar* can be used to quickly find alerts by name or tag.
|
||||
The *search bar* can be used to quickly find alerts by name or tag.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/alerts-filter-by-search.png[Filtering the alerts list using the search bar]
|
||||
|
@ -30,7 +30,7 @@ The *type* dropdown lets you filter to a subset of alert types.
|
|||
[role="screenshot"]
|
||||
image::images/alerts-filter-by-type.png[Filtering the alerts list by types of alert]
|
||||
|
||||
The *Action type* dropdown lets you filter by the type of action used in the alert.
|
||||
The *Action type* dropdown lets you filter by the type of action used in the alert.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/alerts-filter-by-action-type.png[Filtering the alert list by type of action]
|
||||
|
@ -39,16 +39,16 @@ image::images/alerts-filter-by-action-type.png[Filtering the alert list by type
|
|||
[[create-edit-alerts]]
|
||||
==== Creating and editing alerts
|
||||
|
||||
Many alerts must be created within the context of a {kib} app like <<xpack-infra, Metrics>>, <<xpack-apm, APM>>, or <<xpack-uptime, Uptime>>, but others are generic. Generic alert types can be created in the *Alerts* management UI by clicking the *Create* button. This will launch a flyout that guides you through selecting an alert type and configuring it's properties. Refer to <<alert-types>> for details on what types of alerts are available and how to configure them.
|
||||
Many alerts must be created within the context of a {kib} app like <<xpack-infra, Metrics>>, <<xpack-apm, APM>>, or <<xpack-uptime, Uptime>>, but others are generic. Generic alert types can be created in the *Alerts* management UI by clicking the *Create* button. This will launch a flyout that guides you through selecting an alert type and configuring it's properties. Refer to <<alert-types>> for details on what types of alerts are available and how to configure them.
|
||||
|
||||
After an alert is created, you can re-open the flyout and change an alerts properties by clicking the *Edit* button shown on each row of the alert listing.
|
||||
After an alert is created, you can re-open the flyout and change an alerts properties by clicking the *Edit* button shown on each row of the alert listing.
|
||||
|
||||
|
||||
[float]
|
||||
[[controlling-alerts]]
|
||||
==== Controlling alerts
|
||||
|
||||
The alert listing allows you to quickly mute/unmute, disable/enable, and delete individual alerts by clicking the action button at the right of each row.
|
||||
The alert listing allows you to quickly mute/unmute, disable/enable, and delete individual alerts by clicking the action button.
|
||||
|
||||
[role="screenshot"]
|
||||
image:management/alerting/images/individual-mute-disable.png[The actions button allows an individual alert to be muted, disabled, or deleted]
|
||||
|
@ -56,4 +56,4 @@ image:management/alerting/images/individual-mute-disable.png[The actions button
|
|||
These operations can also be performed in bulk by multi-selecting alerts and clicking the *Manage alerts* button:
|
||||
|
||||
[role="screenshot"]
|
||||
image:management/alerting/images/bulk-mute-disable.png[The Manage alerts button lets you mute/unmute, enable/disable, and delete in bulk]
|
||||
image:management/alerting/images/bulk-mute-disable.png[The Manage alerts button lets you mute/unmute, enable/disable, and delete in bulk]
|
||||
|
|
|
@ -15,7 +15,7 @@ image::images/connector-listing.png[Example connector listing in the Alerts and
|
|||
[float]
|
||||
==== Connector list
|
||||
|
||||
The *Connectors* tab lists all connectors in the current space. The *search bar* can be used to find specific connectors by name and/or type.
|
||||
The *Connectors* tab lists all connectors in the current space. The *search bar* can be used to find specific connectors by name and/or type.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/connector-filter-by-search.png[Filtering the connector list using the search bar]
|
||||
|
@ -26,12 +26,12 @@ The *type* dropdown also lets you filter to a subset of action types.
|
|||
[role="screenshot"]
|
||||
image::images/connector-filter-by-type.png[Filtering the connector list by types of actions]
|
||||
|
||||
The *Actions* column indicates the number of actions that reference the connector. This count helps you confirm a connector is unused before you delete it, and tells you how many actions will be affected when a connector is modified.
|
||||
The *Actions* column indicates the number of actions that reference the connector. This count helps you confirm a connector is unused before you delete it, and tells you how many actions will be affected when a connector is modified.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/connector-action-count.png[Filtering the connector list by types of actions]
|
||||
|
||||
You can delete individual connectors using the trash icon on the right of each row. Connectors can also be deleted in bulk by multi-selecting them and clicking the *Delete* button to the left of the search box.
|
||||
You can delete individual connectors using the trash icon. Connectors can also be deleted in bulk by multi-selecting them and clicking the *Delete* button to the left of the search box.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/connector-delete.png[Deleting connectors individually or in bulk]
|
||||
|
@ -44,4 +44,4 @@ When this happens the action will fail to execute, and appear as errors in the {
|
|||
|
||||
==== Creating a new connector
|
||||
|
||||
New connectors can be created by clicking the *Create connector* button, which will guide you to select the type of connector and configure it's properties. Refer to <<action-types>> for the types of connectors available and how to configure them. Once you create a connector it will be made available to you anytime you set up an action in the current space.
|
||||
New connectors can be created by clicking the *Create connector* button, which will guide you to select the type of connector and configure it's properties. Refer to <<action-types>> for the types of connectors available and how to configure them. Once you create a connector it will be made available to you anytime you set up an action in the current space.
|
||||
|
|
|
@ -38,7 +38,6 @@ image:management/index-patterns/images/rollup-index-pattern.png["Menu with rollu
|
|||
Just start typing in the *Index pattern* field, and {kib} looks for
|
||||
the names of {es} indices that match your input. Make sure that the name of the
|
||||
index pattern is unique.
|
||||
To include system indices in your search, toggle the switch in the upper right.
|
||||
|
||||
[role="screenshot"]
|
||||
image:management/index-patterns/images/create-index-pattern.png["Create index pattern"]
|
||||
|
|
|
@ -25,7 +25,7 @@ the *Index patterns* overview.
|
|||
[role="screenshot"]
|
||||
image::management/index-patterns/images/new-index-pattern.png["Index files and data types"]
|
||||
|
||||
Use the icons in the upper right to perform the following actions:
|
||||
Use the icons to perform the following actions:
|
||||
|
||||
* [[set-default-pattern]]*Set the default index pattern.* {kib} uses a badge to make users
|
||||
aware of which index pattern is the default. The first pattern
|
||||
|
|
|
@ -42,8 +42,8 @@ image::images/management_create_rollup_job.png[][Wizard that walks you through c
|
|||
=== Start, stop, and delete rollup jobs
|
||||
|
||||
Once you’ve saved a rollup job, you’ll see it the *Rollup Jobs* overview page,
|
||||
where you can drill down for further investigation. The *Manage* menu in
|
||||
the lower right enables you to start, stop, and delete the rollup job.
|
||||
where you can drill down for further investigation. The *Manage* menu enables
|
||||
you to start, stop, and delete the rollup job.
|
||||
You must first stop a rollup job before deleting it.
|
||||
|
||||
[role="screenshot"]
|
||||
|
|
|
@ -37,7 +37,6 @@ the Elasticsearch responses are shown on the *Layer add panel* and the indexed d
|
|||
appears on the map. The geospatial data on the map
|
||||
should be identical to the locally-previewed data, but now it's indexed data from Elasticsearch.
|
||||
|
||||
. To continue adding data to the map, click *Add layer* in the lower
|
||||
right-hand corner.
|
||||
. To continue adding data to the map, click *Add layer*.
|
||||
. In *Layer settings*, adjust any settings or <<maps-vector-style-properties, properties>> as needed.
|
||||
. Click *Save & close*.
|
||||
|
|
|
@ -55,14 +55,14 @@ auto-populate *Index type* with either {ref}/geo-point.html[geo_point] or
|
|||
{ref}/geo-shape.html[geo_shape] and *Index name* with
|
||||
`<file name>`.
|
||||
|
||||
. Click *Import file* in the lower right.
|
||||
. Click *Import file*.
|
||||
+
|
||||
You'll see activity as the GeoJSON Upload utility creates a new index
|
||||
and index pattern for the data set. When the process is complete, you should
|
||||
receive messages that the creation of the new index and index pattern
|
||||
were successful.
|
||||
|
||||
. Click *Add layer* in the bottom right.
|
||||
. Click *Add layer*.
|
||||
|
||||
. In *Layer settings*, adjust settings and <<maps-vector-style-properties, properties>> as needed.
|
||||
. Click *Save & close*.
|
||||
|
|
|
@ -80,7 +80,7 @@ To symbolize countries by web traffic, you'll need to augment the world country
|
|||
To do this, you'll create a <<terms-join, term join>> to link the vector source *World Countries* to
|
||||
the {es} index `kibana_sample_data_logs` on the shared key iso2 = geo.src.
|
||||
|
||||
. Click plus image:maps/images/gs_plus_icon.png[] to the right of *Term Joins* label.
|
||||
. Click plus image:maps/images/gs_plus_icon.png[] next to the *Term Joins* label.
|
||||
. Click *Join --select--*
|
||||
. Set *Left field* to *ISO 3166-1 alpha-2 code*.
|
||||
. Set *Right source* to *kibana_sample_data_logs*.
|
||||
|
@ -238,7 +238,7 @@ The *machine.os.keyword: osx* filter appears in the dashboard query bar.
|
|||
+
|
||||
. Click the *x* to remove the *machine.os.keyword: osx* filter.
|
||||
. In the map, click in the United States vector.
|
||||
. Click plus image:maps/images/gs_plus_icon.png[] to the right of *iso2* row in the tooltip.
|
||||
. Click plus image:maps/images/gs_plus_icon.png[] next to the *iso2* row in the tooltip.
|
||||
+
|
||||
Both the visualizations and the map are filtered to only show documents where *geo.src* is *US*.
|
||||
The *geo.src: US* filter appears in the dashboard query bar.
|
||||
|
@ -247,4 +247,3 @@ Your dashboard should look like this:
|
|||
+
|
||||
[role="screenshot"]
|
||||
image::maps/images/gs_dashboard_with_terms_filter.png[]
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
**Elastic Maps** embeds the search bar for real-time search.
|
||||
Only layers requesting data from {es} are filtered when you submit a search request.
|
||||
Layers narrowed by the search context contain the filter icon image:maps/images/filter_icon.png[] to the right of layer name in the legend.
|
||||
Layers narrowed by the search context contain the filter icon image:maps/images/filter_icon.png[] next to the layer name in the legend.
|
||||
|
||||
You can create a layer that requests data from {es} from the following:
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
[[defining-alerts]]
|
||||
== Defining alerts
|
||||
|
||||
{kib} alerts can be created in a variety of apps including <<xpack-apm,*APM*>>, <<xpack-infra,*Metrics*>>, <<xpack-siem,*SIEM*>>, <<xpack-uptime,*Uptime*>> and from <<management,*Management*>> UI. While alerting details may differ from app to app, they share a common interface for defining and configuring alerts that this section describes in more detail.
|
||||
{kib} alerts can be created in a variety of apps including <<xpack-apm,*APM*>>, <<xpack-infra,*Metrics*>>, <<xpack-siem,*SIEM*>>, <<xpack-uptime,*Uptime*>> and from <<management,*Management*>> UI. While alerting details may differ from app to app, they share a common interface for defining and configuring alerts that this section describes in more detail.
|
||||
|
||||
[float]
|
||||
=== Alert flyout
|
||||
|
@ -25,20 +25,20 @@ All alert share the following four properties in common:
|
|||
image::images/alert-flyout-general-details.png[All alerts have name, tags, check every, and re-notify every properties in common]
|
||||
|
||||
Name:: The name of the alert. While this name does not have to be unique, the name can be referenced in actions and also appears in the searchable alert listing in the management UI. A distinctive name can help identify and find an alert.
|
||||
Tags:: A list of tag names that can be applied to an alert. Tags can help you organize and find alerts, because tags appear in the alert listing in the management UI which is searchable by tag.
|
||||
Tags:: A list of tag names that can be applied to an alert. Tags can help you organize and find alerts, because tags appear in the alert listing in the management UI which is searchable by tag.
|
||||
Check every:: This value determines how frequently the alert conditions below are checked. Note that the timing of background alert checks are not guaranteed, particularly for intervals of less than 10 seconds. See <<alerting-scale-performance>> for more information.
|
||||
Re-notify every:: This value limits how often actions are repeated when an alert instance remains active across alert checks. See <<alerting-concepts-suppressing-duplicate-notifications>> for more information.
|
||||
Re-notify every:: This value limits how often actions are repeated when an alert instance remains active across alert checks. See <<alerting-concepts-suppressing-duplicate-notifications>> for more information.
|
||||
|
||||
[float]
|
||||
[[defining-alerts-type-conditions]]
|
||||
=== Alert type and conditions
|
||||
|
||||
Depending upon the {kib} app and context, you may be prompted to choose the type of alert you wish to create. Some apps will pre-select the type of alert for you.
|
||||
Depending upon the {kib} app and context, you may be prompted to choose the type of alert you wish to create. Some apps will pre-select the type of alert for you.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/alert-flyout-alert-type-selection.png[Choosing the type of alert to create]
|
||||
|
||||
Each alert type provides its own way of defining the conditions to detect, but an expression formed by a series of clauses is a common pattern. Each clause has a UI control that allows you to define the clause. For example, in an index threshold alert the `WHEN` clause allows you to select an aggregation operation to apply to a numeric field.
|
||||
Each alert type provides its own way of defining the conditions to detect, but an expression formed by a series of clauses is a common pattern. Each clause has a UI control that allows you to define the clause. For example, in an index threshold alert the `WHEN` clause allows you to select an aggregation operation to apply to a numeric field.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/alert-flyout-alert-conditions.png[UI for defining alert conditions on an index threshold alert]
|
||||
|
@ -52,19 +52,19 @@ To add an action to an alert, you first select the type of action:
|
|||
[role="screenshot"]
|
||||
image::images/alert-flyout-action-type-selection.png[UI for selecting an action type]
|
||||
|
||||
Each action must specify a <<alerting-concepts-connectors, connector>> instance. If no connectors exist for that action type, click "Add new" to create one.
|
||||
Each action must specify a <<alerting-concepts-connectors, connector>> instance. If no connectors exist for that action type, click "Add new" to create one.
|
||||
|
||||
Each action type exposes different properties. For example an email action allows you to set the recipients, the subject, and a message body in markdown format. See <<action-types>> for details on the types of actions provided by {kib} and their properties.
|
||||
Each action type exposes different properties. For example an email action allows you to set the recipients, the subject, and a message body in markdown format. See <<action-types>> for details on the types of actions provided by {kib} and their properties.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/alert-flyout-action-details.png[UI for defining an email action]
|
||||
|
||||
Using the https://mustache.github.io/[Mustache] template syntax `{{variable name}}`, you can pass alert values at the time a condition is detected to an action. Available variables differ by alert type, and a list can be accessed using the "add variable" button at the right of the text box.
|
||||
Using the https://mustache.github.io/[Mustache] template syntax `{{variable name}}`, you can pass alert values at the time a condition is detected to an action. Available variables differ by alert type, and a list can be accessed using the "add variable" button.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/alert-flyout-action-variables.png[Passing alert values to an action]
|
||||
|
||||
You can attach more than one action. Clicking the "Add action" button will prompt you to select another alert type and repeat the above steps again.
|
||||
You can attach more than one action. Clicking the "Add action" button will prompt you to select another alert type and repeat the above steps again.
|
||||
|
||||
[role="screenshot"]
|
||||
image::images/alert-flyout-add-action.png[You can add multiple actions on an alert]
|
||||
|
@ -77,4 +77,4 @@ Actions are not required on alerts. In some cases you may want to run an alert w
|
|||
[float]
|
||||
=== Managing alerts
|
||||
|
||||
To modify an alert after it was created, including muting or disabling it, use the <<alert-management, alert listing in the Management UI>>.
|
||||
To modify an alert after it was created, including muting or disabling it, use the <<alert-management, alert listing in the Management UI>>.
|
||||
|
|
|
@ -163,7 +163,8 @@ If you are using an *on-premises* Elastic Stack deployment with <<using-kibana-w
|
|||
[[alerting-security]]
|
||||
== Security
|
||||
|
||||
To access alerting in a space, a user must have access to one of the following features:
|
||||
To access alerting in a space, a user must have access to one of the following features:
|
||||
|
||||
* <<xpack-apm,*APM*>>
|
||||
* <<xpack-infra,*Metrics*>>
|
||||
* <<xpack-siem,*SIEM*>>
|
||||
|
|
|
@ -90,7 +90,7 @@ In *Edit* mode, you can move, resize, customize, and delete panels to suit your
|
|||
* To move a panel, click and hold the panel header and drag to the new location.
|
||||
|
||||
[[resizing-containers]]
|
||||
* To resize a panel, click the resize control on the lower right and drag
|
||||
* To resize a panel, click the resize control and drag
|
||||
to the new dimensions.
|
||||
|
||||
* To toggle the use of margins and panel titles, use the *Options* menu.
|
||||
|
|
|
@ -4,13 +4,29 @@
|
|||
|
||||
[partintro]
|
||||
--
|
||||
The *Dev Tools* page contains development tools that you can use to interact
|
||||
with your data in Kibana.
|
||||
*Dev Tools* contains tools that you can use to interact
|
||||
with your data.
|
||||
|
||||
* <<console-kibana, Console>>
|
||||
* <<xpack-profiler, Search Profiler>>
|
||||
* <<xpack-grokdebugger, Grok Debugger>>
|
||||
[cols="2"]
|
||||
|===
|
||||
|
||||
a| <<console-kibana, Console>>
|
||||
|
||||
| Interact with the REST API of Elasticsearch, including sending requests
|
||||
and viewing API documentation.
|
||||
|
||||
a| <<xpack-profiler, Search Profiler>>
|
||||
|
||||
| Inspect and analyze your search queries.
|
||||
|
||||
a| <<xpack-grokdebugger, Grok Debugger >>
|
||||
|
||||
| Build and debug grok patterns before you use them in your data processing pipelines.
|
||||
|
||||
a| <<painlesslab, Painless Lab>>
|
||||
|
||||
| beta:[] Test and debug Painless scripts in real-time.
|
||||
|===
|
||||
|
||||
--
|
||||
|
||||
|
@ -19,3 +35,5 @@ include::{kib-repo-dir}/dev-tools/console/console.asciidoc[]
|
|||
include::{kib-repo-dir}/dev-tools/searchprofiler/index.asciidoc[]
|
||||
|
||||
include::{kib-repo-dir}/dev-tools/grokdebugger/index.asciidoc[]
|
||||
|
||||
include::{kib-repo-dir}/dev-tools/painlesslab/index.asciidoc[]
|
||||
|
|
|
@ -33,7 +33,7 @@ which has a pre-built index pattern.
|
|||
|
||||
By default, *Discover* shows data for the last 15 minutes.
|
||||
If you have a time-based index, and no data displays,
|
||||
you might need to increase the time range. Using the <<set-time-filter, time filter>> in the upper right,
|
||||
you might need to increase the time range. Using the <<set-time-filter, time filter>>,
|
||||
you can specify a common or recently-used time range, a relative time
|
||||
from now, or an absolute time range.
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ image::user/graph/images/graph-url-connections.png["URL connections"]
|
|||
[role="screenshot"]
|
||||
image::user/graph/images/graph-link-summary.png["Link summary"]
|
||||
|
||||
. Use the control bar on the right to explore
|
||||
. Use the control bar to explore
|
||||
additional connections:
|
||||
+
|
||||
* To display additional vertices that connect to your graph, click the expand icon
|
||||
|
@ -70,7 +70,7 @@ select *Edit settings*.
|
|||
|
||||
To change the color and label of selected vertices,
|
||||
click the style icon image:user/graph/images/graph-style-button.png[Style]
|
||||
in the control bar on the right.
|
||||
in the control bar.
|
||||
|
||||
|
||||
[float]
|
||||
|
|
|
@ -14,8 +14,8 @@ image::user/monitoring/images/monitoring-beats.jpg["Monitoring Beats",link="imag
|
|||
To view an overview of the Beats data in the cluster, click *Overview*. The
|
||||
overview page has a section for activity in the last day, which is a real-time
|
||||
sample of data. The summary bar and charts follow the typical paradigm
|
||||
of data in the Monitoring UI, which is bound to the span of the time filter in
|
||||
the top right corner of the page. This overview page can therefore show
|
||||
of data in the Monitoring UI, which is bound to the span of the time filter.
|
||||
This overview page can therefore show
|
||||
up-to-date or historical information.
|
||||
|
||||
To view a listing of the individual Beat instances in the cluster, click *Beats*.
|
||||
|
|
|
@ -38,7 +38,7 @@ you'll see two places highlighted in green:
|
|||
|
||||
* The visualization builder pane
|
||||
|
||||
* The *X-axis* or *Y-axis* fields in the right column
|
||||
* The *X-axis* or *Y-axis* fields
|
||||
|
||||
You can incorporate many fields into your visualization, and Lens uses heuristics to decide how
|
||||
to apply each one to the visualization.
|
||||
|
@ -89,8 +89,8 @@ You can switch between suggestions without losing your previous state:
|
|||
[role="screenshot"]
|
||||
image::images/lens_suggestions.gif[]
|
||||
|
||||
If you want to switch to a chart type that is not suggested, click the chart type in the
|
||||
top right, then select a chart type. When there is an exclamation point (!)
|
||||
If you want to switch to a chart type that is not suggested, click the chart type,
|
||||
then select a chart type. When there is an exclamation point (!)
|
||||
next to a chart type, Lens is unable to transfer your current data, but
|
||||
still allows you to make the change.
|
||||
|
||||
|
@ -106,7 +106,7 @@ If there is a match, Lens displays the new data. All fields that do not match th
|
|||
|
||||
. Change the data field options, such as the aggregation or label.
|
||||
|
||||
.. Click *Drop a field here* or the field name in the right column.
|
||||
.. Click *Drop a field here* or the field name in the column.
|
||||
|
||||
.. Change the options that appear depending on the type of field.
|
||||
|
||||
|
@ -168,7 +168,7 @@ image::images/lens_tutorial_2.png[Lens tutorial]
|
|||
|
||||
Customize your visualization to look exactly how you want.
|
||||
|
||||
. In the right column, click *Average of taxful_total_price*.
|
||||
. Click *Average of taxful_total_price*.
|
||||
|
||||
.. Change the *Label* to `Sales`, or a name that you prefer for the data.
|
||||
|
||||
|
@ -180,7 +180,7 @@ six available categories.
|
|||
. Look at the suggestions. None of them show an area chart, but for sales data, a stacked area chart
|
||||
might make sense. To switch the chart type:
|
||||
|
||||
.. Click *Stacked bar chart* in the right column.
|
||||
.. Click *Stacked bar chart* in the column.
|
||||
|
||||
.. Click *Stacked area*.
|
||||
+
|
||||
|
|
|
@ -376,7 +376,7 @@
|
|||
"@types/recompose": "^0.30.6",
|
||||
"@types/redux-actions": "^2.6.1",
|
||||
"@types/request": "^2.48.2",
|
||||
"@types/selenium-webdriver": "^4.0.5",
|
||||
"@types/selenium-webdriver": "4.0.9",
|
||||
"@types/semver": "^5.5.0",
|
||||
"@types/sinon": "^7.0.13",
|
||||
"@types/strip-ansi": "^3.0.0",
|
||||
|
@ -462,6 +462,7 @@
|
|||
"load-grunt-config": "^3.0.1",
|
||||
"mocha": "^7.1.1",
|
||||
"mock-http-server": "1.3.0",
|
||||
"ms-chromium-edge-driver": "^0.2.0",
|
||||
"multistream": "^2.1.1",
|
||||
"murmurhash3js": "3.0.1",
|
||||
"mutation-observer": "^1.0.3",
|
||||
|
@ -480,7 +481,7 @@
|
|||
"react-textarea-autosize": "^7.1.2",
|
||||
"regenerate": "^1.4.0",
|
||||
"sass-lint": "^1.12.1",
|
||||
"selenium-webdriver": "^4.0.0-alpha.5",
|
||||
"selenium-webdriver": "^4.0.0-alpha.7",
|
||||
"simple-git": "1.116.0",
|
||||
"simplebar-react": "^2.1.0",
|
||||
"sinon": "^7.4.2",
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
"json-stable-stringify": "^1.0.1",
|
||||
"loader-utils": "^1.2.3",
|
||||
"node-sass": "^4.13.0",
|
||||
"normalize-path": "^3.0.0",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"raw-loader": "^3.1.0",
|
||||
"resolve-url-loader": "^3.1.1",
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -19,6 +19,7 @@
|
|||
|
||||
import Path from 'path';
|
||||
|
||||
import normalizePath from 'normalize-path';
|
||||
import { stringifyRequest } from 'loader-utils';
|
||||
import webpack from 'webpack';
|
||||
// @ts-ignore
|
||||
|
@ -36,6 +37,59 @@ const ISTANBUL_PRESET_PATH = require.resolve('@kbn/babel-preset/istanbul_preset'
|
|||
const PUBLIC_PATH_PLACEHOLDER = '__REPLACE_WITH_PUBLIC_PATH__';
|
||||
const BABEL_PRESET_PATH = require.resolve('@kbn/babel-preset/webpack_preset');
|
||||
|
||||
const STATIC_BUNDLE_PLUGINS = [
|
||||
// { id: 'data', dirname: 'data' },
|
||||
{ id: 'kibanaReact', dirname: 'kibana_react' },
|
||||
{ id: 'kibanaUtils', dirname: 'kibana_utils' },
|
||||
{ id: 'esUiShared', dirname: 'es_ui_shared' },
|
||||
];
|
||||
|
||||
/**
|
||||
* Determine externals statements for require/import statements by looking
|
||||
* for requests resolving to the primary public export of the data, kibanaReact,
|
||||
* amd kibanaUtils plugins. If this module is being imported then rewrite
|
||||
* the import to access the global `__kbnBundles__` variables and access
|
||||
* the relavent properties from that global object.
|
||||
*
|
||||
* @param bundle
|
||||
* @param context the directory containing the module which made `request`
|
||||
* @param request the request for a module from a commonjs require() call or import statement
|
||||
*/
|
||||
function dynamicExternals(bundle: Bundle, context: string, request: string) {
|
||||
// ignore imports that have loaders defined
|
||||
if (request.includes('!')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// don't allow any static bundle to rely on other static bundles
|
||||
if (STATIC_BUNDLE_PLUGINS.some(p => bundle.id === p.id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore requests that don't include a /data/public, /kibana_react/public, or
|
||||
// /kibana_utils/public segment as a cheap way to avoid doing path resolution
|
||||
// for paths that couldn't possibly resolve to what we're looking for
|
||||
const reqToStaticBundle = STATIC_BUNDLE_PLUGINS.some(p =>
|
||||
request.includes(`/${p.dirname}/public`)
|
||||
);
|
||||
if (!reqToStaticBundle) {
|
||||
return;
|
||||
}
|
||||
|
||||
// determine the most acurate resolution string we can without running full resolution
|
||||
const rootRelative = normalizePath(
|
||||
Path.relative(bundle.sourceRoot, Path.resolve(context, request))
|
||||
);
|
||||
for (const { id, dirname } of STATIC_BUNDLE_PLUGINS) {
|
||||
if (rootRelative === `src/plugins/${dirname}/public`) {
|
||||
return `__kbnBundles__['plugin/${id}']`;
|
||||
}
|
||||
}
|
||||
|
||||
// import doesn't match a root public import
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getWebpackConfig(bundle: Bundle, worker: WorkerConfig) {
|
||||
const commonConfig: webpack.Configuration = {
|
||||
node: { fs: 'empty' },
|
||||
|
@ -63,7 +117,6 @@ export function getWebpackConfig(bundle: Bundle, worker: WorkerConfig) {
|
|||
// When the entry point is loaded, assign it's exported `plugin`
|
||||
// value to a key on the global `__kbnBundles__` object.
|
||||
library: ['__kbnBundles__', `plugin/${bundle.id}`],
|
||||
libraryExport: 'plugin',
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
|
@ -72,9 +125,16 @@ export function getWebpackConfig(bundle: Bundle, worker: WorkerConfig) {
|
|||
noEmitOnErrors: true,
|
||||
},
|
||||
|
||||
externals: {
|
||||
...UiSharedDeps.externals,
|
||||
},
|
||||
externals: [
|
||||
UiSharedDeps.externals,
|
||||
function(context, request, cb) {
|
||||
try {
|
||||
cb(undefined, dynamicExternals(bundle, context, request));
|
||||
} catch (error) {
|
||||
cb(error, undefined);
|
||||
}
|
||||
},
|
||||
],
|
||||
|
||||
plugins: [new CleanWebpackPlugin(), new DisallowedSyntaxPlugin()],
|
||||
|
||||
|
|
1105
packages/kbn-pm/dist/index.js
vendored
1105
packages/kbn-pm/dist/index.js
vendored
File diff suppressed because it is too large
Load diff
|
@ -136,7 +136,7 @@ export const schema = Joi.object()
|
|||
browser: Joi.object()
|
||||
.keys({
|
||||
type: Joi.string()
|
||||
.valid('chrome', 'firefox', 'ie')
|
||||
.valid('chrome', 'firefox', 'ie', 'msedge')
|
||||
.default('chrome'),
|
||||
|
||||
logPollingMs: Joi.number().default(100),
|
||||
|
|
|
@ -20,6 +20,13 @@
|
|||
require('core-js/stable');
|
||||
require('regenerator-runtime/runtime');
|
||||
require('custom-event-polyfill');
|
||||
|
||||
if (typeof window.Event === 'object') {
|
||||
// IE11 doesn't support unknown event types, required by react-use
|
||||
// https://github.com/streamich/react-use/issues/73
|
||||
window.Event = CustomEvent;
|
||||
}
|
||||
|
||||
require('whatwg-fetch');
|
||||
require('abortcontroller-polyfill/dist/polyfill-patch-fetch');
|
||||
require('./vendor/childnode_remove_polyfill');
|
||||
|
|
|
@ -71,7 +71,7 @@ test('`loadPluginBundles` creates a script tag and loads initializer', async ()
|
|||
|
||||
// Setup a fake initializer as if a plugin bundle had actually been loaded.
|
||||
const fakeInitializer = jest.fn();
|
||||
coreWindow.__kbnBundles__['plugin/plugin-a'] = fakeInitializer;
|
||||
coreWindow.__kbnBundles__['plugin/plugin-a'] = { plugin: fakeInitializer };
|
||||
// Call the onload callback
|
||||
fakeScriptTag.onload();
|
||||
await expect(loadPromise).resolves.toEqual(fakeInitializer);
|
||||
|
|
|
@ -32,7 +32,7 @@ export type UnknownPluginInitializer = PluginInitializer<unknown, Record<string,
|
|||
*/
|
||||
export interface CoreWindow {
|
||||
__kbnBundles__: {
|
||||
[pluginBundleName: string]: UnknownPluginInitializer | undefined;
|
||||
[pluginBundleName: string]: { plugin: UnknownPluginInitializer } | undefined;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -70,9 +70,28 @@ export const loadPluginBundle: LoadPluginBundle = <
|
|||
) =>
|
||||
new Promise<PluginInitializer<TSetup, TStart, TPluginsSetup, TPluginsStart>>(
|
||||
(resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
const coreWindow = (window as unknown) as CoreWindow;
|
||||
const exportId = `plugin/${pluginName}`;
|
||||
|
||||
const readPluginExport = () => {
|
||||
const PluginExport: any = coreWindow.__kbnBundles__[exportId];
|
||||
if (typeof PluginExport?.plugin !== 'function') {
|
||||
reject(
|
||||
new Error(`Definition of plugin "${pluginName}" should be a function (${bundlePath}).`)
|
||||
);
|
||||
} else {
|
||||
resolve(
|
||||
PluginExport.plugin as PluginInitializer<TSetup, TStart, TPluginsSetup, TPluginsStart>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
if (coreWindow.__kbnBundles__[exportId]) {
|
||||
readPluginExport();
|
||||
return;
|
||||
}
|
||||
|
||||
const script = document.createElement('script');
|
||||
// Assumes that all plugin bundles get put into the bundles/plugins subdirectory
|
||||
const bundlePath = addBasePath(`/bundles/plugin/${pluginName}/${pluginName}.plugin.js`);
|
||||
script.setAttribute('src', bundlePath);
|
||||
|
@ -89,15 +108,7 @@ export const loadPluginBundle: LoadPluginBundle = <
|
|||
// Wire up resolve and reject
|
||||
script.onload = () => {
|
||||
cleanupTag();
|
||||
|
||||
const initializer = coreWindow.__kbnBundles__[`plugin/${pluginName}`];
|
||||
if (!initializer || typeof initializer !== 'function') {
|
||||
reject(
|
||||
new Error(`Definition of plugin "${pluginName}" should be a function (${bundlePath}).`)
|
||||
);
|
||||
} else {
|
||||
resolve(initializer as PluginInitializer<TSetup, TStart, TPluginsSetup, TPluginsStart>);
|
||||
}
|
||||
readPluginExport();
|
||||
};
|
||||
|
||||
script.onerror = () => {
|
||||
|
|
|
@ -26,8 +26,10 @@ import {
|
|||
InternalElasticsearchServiceSetup,
|
||||
ElasticsearchServiceSetup,
|
||||
ElasticsearchServiceStart,
|
||||
ElasticsearchStatusMeta,
|
||||
} from './types';
|
||||
import { NodesVersionCompatibility } from './version_check/ensure_es_version';
|
||||
import { ServiceStatus, ServiceStatusLevels } from '../status';
|
||||
|
||||
const createScopedClusterClientMock = (): jest.Mocked<IScopedClusterClient> => ({
|
||||
callAsInternalUser: jest.fn(),
|
||||
|
@ -102,6 +104,10 @@ const createInternalSetupContractMock = () => {
|
|||
warningNodes: [],
|
||||
kibanaVersion: '8.0.0',
|
||||
}),
|
||||
status$: new BehaviorSubject<ServiceStatus<ElasticsearchStatusMeta>>({
|
||||
level: ServiceStatusLevels.available,
|
||||
summary: 'Elasticsearch is available',
|
||||
}),
|
||||
legacy: {
|
||||
config$: new BehaviorSubject({} as ElasticsearchConfig),
|
||||
},
|
||||
|
|
|
@ -40,6 +40,7 @@ import { InternalHttpServiceSetup, GetAuthHeaders } from '../http/';
|
|||
import { InternalElasticsearchServiceSetup, ElasticsearchServiceStart } from './types';
|
||||
import { CallAPIOptions } from './api_types';
|
||||
import { pollEsNodesVersion } from './version_check/ensure_es_version';
|
||||
import { calculateStatus$ } from './status';
|
||||
|
||||
/** @internal */
|
||||
interface CoreClusterClients {
|
||||
|
@ -186,6 +187,7 @@ export class ElasticsearchService
|
|||
adminClient: this.adminClient,
|
||||
dataClient,
|
||||
createClient: this.createClient,
|
||||
status$: calculateStatus$(esNodesCompatibility$),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -31,3 +31,4 @@ export { config, configSchema, ElasticsearchConfig } from './elasticsearch_confi
|
|||
export { ElasticsearchError, ElasticsearchErrorHelpers } from './errors';
|
||||
export * from './api_types';
|
||||
export * from './types';
|
||||
export { NodesVersionCompatibility } from './version_check/ensure_es_version';
|
||||
|
|
222
src/core/server/elasticsearch/status.test.ts
Normal file
222
src/core/server/elasticsearch/status.test.ts
Normal file
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* 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 { take } from 'rxjs/operators';
|
||||
import { Subject, of } from 'rxjs';
|
||||
|
||||
import { calculateStatus$ } from './status';
|
||||
import { ServiceStatusLevels, ServiceStatus } from '../status';
|
||||
import { ServiceStatusLevelSnapshotSerializer } from '../status/test_utils';
|
||||
import { NodesVersionCompatibility } from './version_check/ensure_es_version';
|
||||
|
||||
expect.addSnapshotSerializer(ServiceStatusLevelSnapshotSerializer);
|
||||
|
||||
const nodeInfo = {
|
||||
version: '1.1.1',
|
||||
ip: '1.1.1.1',
|
||||
http: {
|
||||
publish_address: 'https://1.1.1.1:9200',
|
||||
},
|
||||
name: 'node1',
|
||||
};
|
||||
|
||||
describe('calculateStatus', () => {
|
||||
it('starts in unavailable', async () => {
|
||||
expect(
|
||||
await calculateStatus$(new Subject())
|
||||
.pipe(take(1))
|
||||
.toPromise()
|
||||
).toEqual({
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: 'Waiting for Elasticsearch',
|
||||
meta: {
|
||||
warningNodes: [],
|
||||
incompatibleNodes: [],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('changes to available when isCompatible and no warningNodes', async () => {
|
||||
expect(
|
||||
await calculateStatus$(
|
||||
of({ isCompatible: true, kibanaVersion: '1.1.1', warningNodes: [], incompatibleNodes: [] })
|
||||
)
|
||||
.pipe(take(2))
|
||||
.toPromise()
|
||||
).toEqual({
|
||||
level: ServiceStatusLevels.available,
|
||||
summary: 'Elasticsearch is available',
|
||||
meta: {
|
||||
warningNodes: [],
|
||||
incompatibleNodes: [],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('changes to degraded when isCompatible and warningNodes present', async () => {
|
||||
expect(
|
||||
await calculateStatus$(
|
||||
of({
|
||||
isCompatible: true,
|
||||
kibanaVersion: '1.1.1',
|
||||
warningNodes: [nodeInfo],
|
||||
incompatibleNodes: [],
|
||||
// this isn't the real message, just used to test that the message
|
||||
// is forwarded to the status
|
||||
message: 'Some nodes are a different version',
|
||||
})
|
||||
)
|
||||
.pipe(take(2))
|
||||
.toPromise()
|
||||
).toEqual({
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: 'Some nodes are a different version',
|
||||
meta: {
|
||||
incompatibleNodes: [],
|
||||
warningNodes: [nodeInfo],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('changes to critical when isCompatible is false', async () => {
|
||||
expect(
|
||||
await calculateStatus$(
|
||||
of({
|
||||
isCompatible: false,
|
||||
kibanaVersion: '2.1.1',
|
||||
warningNodes: [nodeInfo],
|
||||
incompatibleNodes: [nodeInfo],
|
||||
// this isn't the real message, just used to test that the message
|
||||
// is forwarded to the status
|
||||
message: 'Incompatible with Elasticsearch',
|
||||
})
|
||||
)
|
||||
.pipe(take(2))
|
||||
.toPromise()
|
||||
).toEqual({
|
||||
level: ServiceStatusLevels.critical,
|
||||
summary: 'Incompatible with Elasticsearch',
|
||||
meta: {
|
||||
incompatibleNodes: [nodeInfo],
|
||||
warningNodes: [nodeInfo],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('emits status updates when node compatibility changes', () => {
|
||||
const nodeCompat$ = new Subject<NodesVersionCompatibility>();
|
||||
|
||||
const statusUpdates: ServiceStatus[] = [];
|
||||
const subscription = calculateStatus$(nodeCompat$).subscribe(status =>
|
||||
statusUpdates.push(status)
|
||||
);
|
||||
|
||||
nodeCompat$.next({
|
||||
isCompatible: false,
|
||||
kibanaVersion: '2.1.1',
|
||||
incompatibleNodes: [],
|
||||
warningNodes: [],
|
||||
message: 'Unable to retrieve version info',
|
||||
});
|
||||
nodeCompat$.next({
|
||||
isCompatible: false,
|
||||
kibanaVersion: '2.1.1',
|
||||
incompatibleNodes: [nodeInfo],
|
||||
warningNodes: [],
|
||||
message: 'Incompatible with Elasticsearch',
|
||||
});
|
||||
nodeCompat$.next({
|
||||
isCompatible: true,
|
||||
kibanaVersion: '1.1.1',
|
||||
warningNodes: [nodeInfo],
|
||||
incompatibleNodes: [],
|
||||
message: 'Some nodes are incompatible',
|
||||
});
|
||||
nodeCompat$.next({
|
||||
isCompatible: true,
|
||||
kibanaVersion: '1.1.1',
|
||||
warningNodes: [],
|
||||
incompatibleNodes: [],
|
||||
});
|
||||
|
||||
subscription.unsubscribe();
|
||||
expect(statusUpdates).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"level": unavailable,
|
||||
"meta": Object {
|
||||
"incompatibleNodes": Array [],
|
||||
"warningNodes": Array [],
|
||||
},
|
||||
"summary": "Waiting for Elasticsearch",
|
||||
},
|
||||
Object {
|
||||
"level": critical,
|
||||
"meta": Object {
|
||||
"incompatibleNodes": Array [],
|
||||
"warningNodes": Array [],
|
||||
},
|
||||
"summary": "Unable to retrieve version info",
|
||||
},
|
||||
Object {
|
||||
"level": critical,
|
||||
"meta": Object {
|
||||
"incompatibleNodes": Array [
|
||||
Object {
|
||||
"http": Object {
|
||||
"publish_address": "https://1.1.1.1:9200",
|
||||
},
|
||||
"ip": "1.1.1.1",
|
||||
"name": "node1",
|
||||
"version": "1.1.1",
|
||||
},
|
||||
],
|
||||
"warningNodes": Array [],
|
||||
},
|
||||
"summary": "Incompatible with Elasticsearch",
|
||||
},
|
||||
Object {
|
||||
"level": degraded,
|
||||
"meta": Object {
|
||||
"incompatibleNodes": Array [],
|
||||
"warningNodes": Array [
|
||||
Object {
|
||||
"http": Object {
|
||||
"publish_address": "https://1.1.1.1:9200",
|
||||
},
|
||||
"ip": "1.1.1.1",
|
||||
"name": "node1",
|
||||
"version": "1.1.1",
|
||||
},
|
||||
],
|
||||
},
|
||||
"summary": "Some nodes are incompatible",
|
||||
},
|
||||
Object {
|
||||
"level": available,
|
||||
"meta": Object {
|
||||
"incompatibleNodes": Array [],
|
||||
"warningNodes": Array [],
|
||||
},
|
||||
"summary": "Elasticsearch is available",
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
78
src/core/server/elasticsearch/status.ts
Normal file
78
src/core/server/elasticsearch/status.ts
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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 { Observable, merge, of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { ServiceStatus, ServiceStatusLevels } from '../status';
|
||||
import { ElasticsearchStatusMeta } from './types';
|
||||
import { NodesVersionCompatibility } from './version_check/ensure_es_version';
|
||||
|
||||
export const calculateStatus$ = (
|
||||
esNodesCompatibility$: Observable<NodesVersionCompatibility>
|
||||
): Observable<ServiceStatus<ElasticsearchStatusMeta>> =>
|
||||
merge(
|
||||
of({
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: `Waiting for Elasticsearch`,
|
||||
meta: {
|
||||
warningNodes: [],
|
||||
incompatibleNodes: [],
|
||||
},
|
||||
}),
|
||||
esNodesCompatibility$.pipe(
|
||||
map(
|
||||
({
|
||||
isCompatible,
|
||||
message,
|
||||
incompatibleNodes,
|
||||
warningNodes,
|
||||
}): ServiceStatus<ElasticsearchStatusMeta> => {
|
||||
if (!isCompatible) {
|
||||
return {
|
||||
level: ServiceStatusLevels.critical,
|
||||
summary:
|
||||
// Message should always be present, but this is a safe fallback
|
||||
message ??
|
||||
`Some Elasticsearch nodes are not compatible with this version of Kibana`,
|
||||
meta: { warningNodes, incompatibleNodes },
|
||||
};
|
||||
} else if (warningNodes.length > 0) {
|
||||
return {
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary:
|
||||
// Message should always be present, but this is a safe fallback
|
||||
message ??
|
||||
`Some Elasticsearch nodes are running different versions than this version of Kibana`,
|
||||
meta: { warningNodes, incompatibleNodes },
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
level: ServiceStatusLevels.available,
|
||||
summary: `Elasticsearch is available`,
|
||||
meta: {
|
||||
warningNodes: [],
|
||||
incompatibleNodes: [],
|
||||
},
|
||||
};
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
|
@ -22,6 +22,7 @@ import { ElasticsearchConfig } from './elasticsearch_config';
|
|||
import { ElasticsearchClientConfig } from './elasticsearch_client_config';
|
||||
import { IClusterClient, ICustomClusterClient } from './cluster_client';
|
||||
import { NodesVersionCompatibility } from './version_check/ensure_es_version';
|
||||
import { ServiceStatus } from '../status';
|
||||
|
||||
/**
|
||||
* @public
|
||||
|
@ -128,4 +129,11 @@ export interface InternalElasticsearchServiceSetup extends ElasticsearchServiceS
|
|||
readonly config$: Observable<ElasticsearchConfig>;
|
||||
};
|
||||
esNodesCompatibility$: Observable<NodesVersionCompatibility>;
|
||||
status$: Observable<ServiceStatus<ElasticsearchStatusMeta>>;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface ElasticsearchStatusMeta {
|
||||
warningNodes: NodesVersionCompatibility['warningNodes'];
|
||||
incompatibleNodes: NodesVersionCompatibility['incompatibleNodes'];
|
||||
}
|
||||
|
|
|
@ -142,7 +142,7 @@ export const pollEsNodesVersion = ({
|
|||
kibanaVersion,
|
||||
ignoreVersionMismatch,
|
||||
esVersionCheckInterval: healthCheckInterval,
|
||||
}: PollEsNodesVersionOptions): Observable<any> => {
|
||||
}: PollEsNodesVersionOptions): Observable<NodesVersionCompatibility> => {
|
||||
log.debug('Checking Elasticsearch version');
|
||||
return timer(0, healthCheckInterval).pipe(
|
||||
exhaustMap(() => {
|
||||
|
|
|
@ -60,6 +60,7 @@ import {
|
|||
import { CapabilitiesSetup, CapabilitiesStart } from './capabilities';
|
||||
import { UuidServiceSetup } from './uuid';
|
||||
import { MetricsServiceSetup } from './metrics';
|
||||
import { StatusServiceSetup } from './status';
|
||||
|
||||
export { bootstrap } from './bootstrap';
|
||||
export { Capabilities, CapabilitiesProvider, CapabilitiesSwitcher } from './capabilities';
|
||||
|
@ -95,6 +96,8 @@ export {
|
|||
ElasticsearchErrorHelpers,
|
||||
ElasticsearchServiceSetup,
|
||||
ElasticsearchServiceStart,
|
||||
ElasticsearchStatusMeta,
|
||||
NodesVersionCompatibility,
|
||||
APICaller,
|
||||
FakeRequest,
|
||||
ScopeableRequest,
|
||||
|
@ -226,6 +229,7 @@ export {
|
|||
SavedObjectsUpdateResponse,
|
||||
SavedObjectsServiceStart,
|
||||
SavedObjectsServiceSetup,
|
||||
SavedObjectStatusMeta,
|
||||
SavedObjectsDeleteOptions,
|
||||
ISavedObjectsRepository,
|
||||
SavedObjectsRepository,
|
||||
|
@ -294,6 +298,14 @@ export {
|
|||
LegacyInternals,
|
||||
} from './legacy';
|
||||
|
||||
export {
|
||||
CoreStatus,
|
||||
ServiceStatus,
|
||||
ServiceStatusLevel,
|
||||
ServiceStatusLevels,
|
||||
StatusServiceSetup,
|
||||
} from './status';
|
||||
|
||||
/**
|
||||
* Plugin specific context passed to a route handler.
|
||||
*
|
||||
|
@ -348,14 +360,16 @@ export interface CoreSetup<TPluginsStart extends object = object, TStart = unkno
|
|||
elasticsearch: ElasticsearchServiceSetup;
|
||||
/** {@link HttpServiceSetup} */
|
||||
http: HttpServiceSetup;
|
||||
/** {@link MetricsServiceSetup} */
|
||||
metrics: MetricsServiceSetup;
|
||||
/** {@link SavedObjectsServiceSetup} */
|
||||
savedObjects: SavedObjectsServiceSetup;
|
||||
/** {@link StatusServiceSetup} */
|
||||
status: StatusServiceSetup;
|
||||
/** {@link UiSettingsServiceSetup} */
|
||||
uiSettings: UiSettingsServiceSetup;
|
||||
/** {@link UuidServiceSetup} */
|
||||
uuid: UuidServiceSetup;
|
||||
/** {@link MetricsServiceSetup} */
|
||||
metrics: MetricsServiceSetup;
|
||||
/** {@link StartServicesAccessor} */
|
||||
getStartServices: StartServicesAccessor<TPluginsStart, TStart>;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import {
|
|||
import { InternalUiSettingsServiceSetup, InternalUiSettingsServiceStart } from './ui_settings';
|
||||
import { UuidServiceSetup } from './uuid';
|
||||
import { InternalMetricsServiceSetup } from './metrics';
|
||||
import { InternalStatusServiceSetup } from './status';
|
||||
|
||||
/** @internal */
|
||||
export interface InternalCoreSetup {
|
||||
|
@ -38,10 +39,11 @@ export interface InternalCoreSetup {
|
|||
context: ContextSetup;
|
||||
http: InternalHttpServiceSetup;
|
||||
elasticsearch: InternalElasticsearchServiceSetup;
|
||||
uiSettings: InternalUiSettingsServiceSetup;
|
||||
savedObjects: InternalSavedObjectsServiceSetup;
|
||||
uuid: UuidServiceSetup;
|
||||
metrics: InternalMetricsServiceSetup;
|
||||
savedObjects: InternalSavedObjectsServiceSetup;
|
||||
status: InternalStatusServiceSetup;
|
||||
uiSettings: InternalUiSettingsServiceSetup;
|
||||
uuid: UuidServiceSetup;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -48,6 +48,7 @@ import { findLegacyPluginSpecs } from './plugins';
|
|||
import { LegacyVars, LegacyServiceSetupDeps, LegacyServiceStartDeps } from './types';
|
||||
import { LegacyService } from './legacy_service';
|
||||
import { coreMock } from '../mocks';
|
||||
import { statusServiceMock } from '../status/status_service.mock';
|
||||
|
||||
const MockKbnServer: jest.Mock<KbnServer> = KbnServer as any;
|
||||
|
||||
|
@ -106,6 +107,7 @@ beforeEach(() => {
|
|||
rendering: renderingServiceMock,
|
||||
metrics: metricsServiceMock.createInternalSetupContract(),
|
||||
uuid: uuidSetup,
|
||||
status: statusServiceMock.createInternalSetupContract(),
|
||||
},
|
||||
plugins: { 'plugin-id': 'plugin-value' },
|
||||
};
|
||||
|
|
|
@ -306,6 +306,9 @@ export class LegacyService implements CoreService {
|
|||
registerType: setupDeps.core.savedObjects.registerType,
|
||||
getImportExportObjectLimit: setupDeps.core.savedObjects.getImportExportObjectLimit,
|
||||
},
|
||||
status: {
|
||||
core$: setupDeps.core.status.core$,
|
||||
},
|
||||
uiSettings: {
|
||||
register: setupDeps.core.uiSettings.register,
|
||||
},
|
||||
|
|
|
@ -33,6 +33,7 @@ import { InternalCoreSetup, InternalCoreStart } from './internal_types';
|
|||
import { capabilitiesServiceMock } from './capabilities/capabilities_service.mock';
|
||||
import { metricsServiceMock } from './metrics/metrics_service.mock';
|
||||
import { uuidServiceMock } from './uuid/uuid_service.mock';
|
||||
import { statusServiceMock } from './status/status_service.mock';
|
||||
|
||||
export { httpServerMock } from './http/http_server.mocks';
|
||||
export { sessionStorageMock } from './http/cookie_session_storage.mocks';
|
||||
|
@ -133,9 +134,10 @@ function createCoreSetupMock({
|
|||
elasticsearch: elasticsearchServiceMock.createSetup(),
|
||||
http: httpMock,
|
||||
savedObjects: savedObjectsServiceMock.createInternalSetupContract(),
|
||||
status: statusServiceMock.createSetupContract(),
|
||||
metrics: metricsServiceMock.createSetupContract(),
|
||||
uiSettings: uiSettingsMock,
|
||||
uuid: uuidServiceMock.createSetupContract(),
|
||||
metrics: metricsServiceMock.createSetupContract(),
|
||||
getStartServices: jest
|
||||
.fn<Promise<[ReturnType<typeof createCoreStartMock>, object, any]>, []>()
|
||||
.mockResolvedValue([createCoreStartMock(), pluginStartDeps, pluginStartContract]),
|
||||
|
@ -161,10 +163,11 @@ function createInternalCoreSetupMock() {
|
|||
context: contextServiceMock.createSetupContract(),
|
||||
elasticsearch: elasticsearchServiceMock.createInternalSetup(),
|
||||
http: httpServiceMock.createSetupContract(),
|
||||
uiSettings: uiSettingsServiceMock.createSetupContract(),
|
||||
savedObjects: savedObjectsServiceMock.createInternalSetupContract(),
|
||||
uuid: uuidServiceMock.createSetupContract(),
|
||||
metrics: metricsServiceMock.createInternalSetupContract(),
|
||||
savedObjects: savedObjectsServiceMock.createInternalSetupContract(),
|
||||
status: statusServiceMock.createInternalSetupContract(),
|
||||
uuid: uuidServiceMock.createSetupContract(),
|
||||
uiSettings: uiSettingsServiceMock.createSetupContract(),
|
||||
};
|
||||
return setupDeps;
|
||||
}
|
||||
|
|
|
@ -175,6 +175,9 @@ export function createPluginSetupContext<TPlugin, TPluginDependencies>(
|
|||
registerType: deps.savedObjects.registerType,
|
||||
getImportExportObjectLimit: deps.savedObjects.getImportExportObjectLimit,
|
||||
},
|
||||
status: {
|
||||
core$: deps.status.core$,
|
||||
},
|
||||
uiSettings: {
|
||||
register: deps.uiSettings.register,
|
||||
},
|
||||
|
|
|
@ -68,7 +68,11 @@ export {
|
|||
SavedObjectMigrationContext,
|
||||
} from './migrations';
|
||||
|
||||
export { SavedObjectsType, SavedObjectsTypeManagementDefinition } from './types';
|
||||
export {
|
||||
SavedObjectStatusMeta,
|
||||
SavedObjectsType,
|
||||
SavedObjectsTypeManagementDefinition,
|
||||
} from './types';
|
||||
|
||||
export { savedObjectsConfig, savedObjectsMigrationConfig } from './saved_objects_config';
|
||||
export { SavedObjectTypeRegistry, ISavedObjectTypeRegistry } from './saved_objects_type_registry';
|
||||
|
|
|
@ -22,4 +22,4 @@ export { IndexMigrator } from './index_migrator';
|
|||
export { buildActiveMappings } from './build_active_mappings';
|
||||
export { CallCluster } from './call_cluster';
|
||||
export { LogFn } from './migration_logger';
|
||||
export { MigrationResult } from './migration_coordinator';
|
||||
export { MigrationResult, MigrationStatus } from './migration_coordinator';
|
||||
|
|
|
@ -39,6 +39,8 @@ import { SavedObjectsMigrationLogger } from './migration_logger';
|
|||
|
||||
const DEFAULT_POLL_INTERVAL = 15000;
|
||||
|
||||
export type MigrationStatus = 'waiting' | 'running' | 'completed';
|
||||
|
||||
export type MigrationResult =
|
||||
| { status: 'skipped' }
|
||||
| { status: 'patched' }
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export { MigrationResult } from './core';
|
||||
export { KibanaMigrator, IKibanaMigrator } from './kibana';
|
||||
export {
|
||||
SavedObjectMigrationFn,
|
||||
|
|
|
@ -17,4 +17,4 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export { KibanaMigrator, IKibanaMigrator } from './kibana_migrator';
|
||||
export { KibanaMigrator, IKibanaMigrator, KibanaMigratorStatus } from './kibana_migrator';
|
||||
|
|
|
@ -17,10 +17,11 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { KibanaMigrator } from './kibana_migrator';
|
||||
import { KibanaMigrator, KibanaMigratorStatus } from './kibana_migrator';
|
||||
import { buildActiveMappings } from '../core';
|
||||
const { mergeTypes } = jest.requireActual('./kibana_migrator');
|
||||
import { SavedObjectsType } from '../../types';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
const defaultSavedObjectTypes: SavedObjectsType[] = [
|
||||
{
|
||||
|
@ -47,6 +48,20 @@ const createMigrator = (
|
|||
runMigrations: jest.fn(),
|
||||
getActiveMappings: jest.fn(),
|
||||
migrateDocument: jest.fn(),
|
||||
getStatus$: jest.fn(
|
||||
() =>
|
||||
new BehaviorSubject<KibanaMigratorStatus>({
|
||||
status: 'completed',
|
||||
result: [
|
||||
{
|
||||
status: 'migrated',
|
||||
destIndex: '.test-kibana_2',
|
||||
sourceIndex: '.test-kibana_1',
|
||||
elapsedMs: 10,
|
||||
},
|
||||
],
|
||||
})
|
||||
),
|
||||
};
|
||||
|
||||
mockMigrator.getActiveMappings.mockReturnValue(buildActiveMappings(mergeTypes(types)));
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
import { KibanaMigratorOptions, KibanaMigrator } from './kibana_migrator';
|
||||
import { loggingServiceMock } from '../../../logging/logging_service.mock';
|
||||
|
@ -79,6 +80,33 @@ describe('KibanaMigrator', () => {
|
|||
.filter(callClusterPath => callClusterPath === 'cat.templates');
|
||||
expect(callClusterCommands.length).toBe(1);
|
||||
});
|
||||
|
||||
it('emits results on getMigratorResult$()', async () => {
|
||||
const options = mockOptions();
|
||||
const clusterStub = jest.fn<any, any>(() => ({ status: 404 }));
|
||||
|
||||
options.callCluster = clusterStub;
|
||||
const migrator = new KibanaMigrator(options);
|
||||
const migratorStatus = migrator
|
||||
.getStatus$()
|
||||
.pipe(take(3))
|
||||
.toPromise();
|
||||
await migrator.runMigrations();
|
||||
const { status, result } = await migratorStatus;
|
||||
expect(status).toEqual('completed');
|
||||
expect(result![0]).toMatchObject({
|
||||
destIndex: '.my-index_1',
|
||||
elapsedMs: expect.any(Number),
|
||||
sourceIndex: '.my-index',
|
||||
status: 'migrated',
|
||||
});
|
||||
expect(result![1]).toMatchObject({
|
||||
destIndex: 'other-index_1',
|
||||
elapsedMs: expect.any(Number),
|
||||
sourceIndex: 'other-index',
|
||||
status: 'migrated',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -24,10 +24,17 @@
|
|||
|
||||
import { Logger } from 'src/core/server/logging';
|
||||
import { KibanaConfigType } from 'src/core/server/kibana_config';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { IndexMapping, SavedObjectsTypeMappingDefinitions } from '../../mappings';
|
||||
import { SavedObjectUnsanitizedDoc, SavedObjectsSerializer } from '../../serialization';
|
||||
import { docValidator, PropertyValidators } from '../../validation';
|
||||
import { buildActiveMappings, CallCluster, IndexMigrator } from '../core';
|
||||
import {
|
||||
buildActiveMappings,
|
||||
CallCluster,
|
||||
IndexMigrator,
|
||||
MigrationResult,
|
||||
MigrationStatus,
|
||||
} from '../core';
|
||||
import { DocumentMigrator, VersionedTransformer } from '../core/document_migrator';
|
||||
import { createIndexMap } from '../core/build_index_map';
|
||||
import { SavedObjectsMigrationConfigType } from '../../saved_objects_config';
|
||||
|
@ -46,6 +53,11 @@ export interface KibanaMigratorOptions {
|
|||
|
||||
export type IKibanaMigrator = Pick<KibanaMigrator, keyof KibanaMigrator>;
|
||||
|
||||
export interface KibanaMigratorStatus {
|
||||
status: MigrationStatus;
|
||||
result?: MigrationResult[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages the shape of mappings and documents in the Kibana index.
|
||||
*/
|
||||
|
@ -58,7 +70,10 @@ export class KibanaMigrator {
|
|||
private readonly mappingProperties: SavedObjectsTypeMappingDefinitions;
|
||||
private readonly typeRegistry: ISavedObjectTypeRegistry;
|
||||
private readonly serializer: SavedObjectsSerializer;
|
||||
private migrationResult?: Promise<Array<{ status: string }>>;
|
||||
private migrationResult?: Promise<MigrationResult[]>;
|
||||
private readonly status$ = new BehaviorSubject<KibanaMigratorStatus>({
|
||||
status: 'waiting',
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates an instance of KibanaMigrator.
|
||||
|
@ -109,12 +124,20 @@ export class KibanaMigrator {
|
|||
Array<{ status: string }>
|
||||
> {
|
||||
if (this.migrationResult === undefined || rerun) {
|
||||
this.migrationResult = this.runMigrationsInternal();
|
||||
this.status$.next({ status: 'running' });
|
||||
this.migrationResult = this.runMigrationsInternal().then(result => {
|
||||
this.status$.next({ status: 'completed', result });
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
return this.migrationResult;
|
||||
}
|
||||
|
||||
public getStatus$() {
|
||||
return this.status$.asObservable();
|
||||
}
|
||||
|
||||
private runMigrationsInternal() {
|
||||
const kibanaIndexName = this.kibanaConfig.index;
|
||||
const indexMap = createIndexMap({
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
import {
|
||||
SavedObjectsService,
|
||||
InternalSavedObjectsServiceSetup,
|
||||
|
@ -29,6 +31,7 @@ import { savedObjectsClientProviderMock } from './service/lib/scoped_client_prov
|
|||
import { savedObjectsRepositoryMock } from './service/lib/repository.mock';
|
||||
import { savedObjectsClientMock } from './service/saved_objects_client.mock';
|
||||
import { typeRegistryMock } from './saved_objects_type_registry.mock';
|
||||
import { ServiceStatusLevels } from '../status';
|
||||
|
||||
type SavedObjectsServiceContract = PublicMethodsOf<SavedObjectsService>;
|
||||
|
||||
|
@ -75,6 +78,10 @@ const createSetupContractMock = () => {
|
|||
const createInternalSetupContractMock = () => {
|
||||
const internalSetupContract: jest.Mocked<InternalSavedObjectsServiceSetup> = {
|
||||
...createSetupContractMock(),
|
||||
status$: new BehaviorSubject({
|
||||
level: ServiceStatusLevels.available,
|
||||
summary: `SavedObjects is available`,
|
||||
}),
|
||||
};
|
||||
return internalSetupContract;
|
||||
};
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { Subject } from 'rxjs';
|
||||
import { first, filter, take } from 'rxjs/operators';
|
||||
import { Subject, Observable } from 'rxjs';
|
||||
import { first, filter, take, switchMap } from 'rxjs/operators';
|
||||
import { CoreService } from '../../types';
|
||||
import {
|
||||
SavedObjectsClient,
|
||||
|
@ -38,7 +38,7 @@ import {
|
|||
SavedObjectConfig,
|
||||
} from './saved_objects_config';
|
||||
import { KibanaRequest, InternalHttpServiceSetup } from '../http';
|
||||
import { SavedObjectsClientContract, SavedObjectsType } from './types';
|
||||
import { SavedObjectsClientContract, SavedObjectsType, SavedObjectStatusMeta } from './types';
|
||||
import { ISavedObjectsRepository, SavedObjectsRepository } from './service/lib/repository';
|
||||
import {
|
||||
SavedObjectsClientFactoryProvider,
|
||||
|
@ -50,6 +50,8 @@ import { SavedObjectTypeRegistry, ISavedObjectTypeRegistry } from './saved_objec
|
|||
import { PropertyValidators } from './validation';
|
||||
import { SavedObjectsSerializer } from './serialization';
|
||||
import { registerRoutes } from './routes';
|
||||
import { ServiceStatus } from '../status';
|
||||
import { calculateStatus$ } from './status';
|
||||
|
||||
/**
|
||||
* Saved Objects is Kibana's data persistence mechanism allowing plugins to
|
||||
|
@ -164,7 +166,9 @@ export interface SavedObjectsServiceSetup {
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type InternalSavedObjectsServiceSetup = SavedObjectsServiceSetup;
|
||||
export interface InternalSavedObjectsServiceSetup extends SavedObjectsServiceSetup {
|
||||
status$: Observable<ServiceStatus<SavedObjectStatusMeta>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saved Objects is Kibana's data persisentence mechanism allowing plugins to
|
||||
|
@ -321,6 +325,10 @@ export class SavedObjectsService
|
|||
});
|
||||
|
||||
return {
|
||||
status$: calculateStatus$(
|
||||
this.migrator$.pipe(switchMap(migrator => migrator.getStatus$())),
|
||||
setupDeps.elasticsearch.status$
|
||||
),
|
||||
setClientFactoryProvider: provider => {
|
||||
if (this.started) {
|
||||
throw new Error('cannot call `setClientFactoryProvider` after service startup.');
|
||||
|
|
134
src/core/server/saved_objects/status.test.ts
Normal file
134
src/core/server/saved_objects/status.test.ts
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* 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 { of, Observable } from 'rxjs';
|
||||
import { ServiceStatus, ServiceStatusLevels } from '../status';
|
||||
import { calculateStatus$ } from './status';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
describe('calculateStatus$', () => {
|
||||
const expectUnavailableDueToEs = (status$: Observable<ServiceStatus>) =>
|
||||
expect(status$.pipe(take(1)).toPromise()).resolves.toEqual({
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: `SavedObjects service is not available without a healthy Elasticearch connection`,
|
||||
});
|
||||
|
||||
const expectUnavailableDueToMigrations = (status$: Observable<ServiceStatus>) =>
|
||||
expect(status$.pipe(take(1)).toPromise()).resolves.toEqual({
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: `SavedObjects service is waiting to start migrations`,
|
||||
});
|
||||
|
||||
describe('when elasticsearch is unavailable', () => {
|
||||
const esStatus$ = of<ServiceStatus>({
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: 'xxx',
|
||||
});
|
||||
|
||||
it('is unavailable before migrations have ran', async () => {
|
||||
await expectUnavailableDueToEs(calculateStatus$(of<any>(), esStatus$));
|
||||
});
|
||||
it('is unavailable after migrations have ran', async () => {
|
||||
await expectUnavailableDueToEs(
|
||||
calculateStatus$(of({ status: 'completed', result: [] }), esStatus$)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when elasticsearch is critical', () => {
|
||||
const esStatus$ = of<ServiceStatus>({
|
||||
level: ServiceStatusLevels.critical,
|
||||
summary: 'xxx',
|
||||
});
|
||||
|
||||
it('is unavailable before migrations have ran', async () => {
|
||||
await expectUnavailableDueToEs(calculateStatus$(of<any>(), esStatus$));
|
||||
});
|
||||
it('is unavailable after migrations have ran', async () => {
|
||||
await expectUnavailableDueToEs(
|
||||
calculateStatus$(
|
||||
of({ status: 'completed', result: [{ status: 'migrated' } as any] }),
|
||||
esStatus$
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when elasticsearch is available', () => {
|
||||
const esStatus$ = of<ServiceStatus>({
|
||||
level: ServiceStatusLevels.available,
|
||||
summary: 'Available',
|
||||
});
|
||||
|
||||
it('is unavailable before migrations have ran', async () => {
|
||||
await expectUnavailableDueToMigrations(calculateStatus$(of<any>(), esStatus$));
|
||||
});
|
||||
it('is unavailable while migrations are running', async () => {
|
||||
await expect(
|
||||
calculateStatus$(of({ status: 'running' }), esStatus$)
|
||||
.pipe(take(2))
|
||||
.toPromise()
|
||||
).resolves.toEqual({
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: `SavedObjects service is running migrations`,
|
||||
});
|
||||
});
|
||||
it('is available after migrations have ran', async () => {
|
||||
await expect(
|
||||
calculateStatus$(
|
||||
of({ status: 'completed', result: [{ status: 'skipped' }, { status: 'patched' }] }),
|
||||
esStatus$
|
||||
)
|
||||
.pipe(take(2))
|
||||
.toPromise()
|
||||
).resolves.toEqual({
|
||||
level: ServiceStatusLevels.available,
|
||||
summary: `SavedObjects service has completed migrations and is available`,
|
||||
meta: {
|
||||
migratedIndices: {
|
||||
migrated: 0,
|
||||
patched: 1,
|
||||
skipped: 1,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when elasticsearch is degraded', () => {
|
||||
const esStatus$ = of<ServiceStatus>({ level: ServiceStatusLevels.degraded, summary: 'xxx' });
|
||||
|
||||
it('is unavailable before migrations have ran', async () => {
|
||||
await expectUnavailableDueToMigrations(calculateStatus$(of<any>(), esStatus$));
|
||||
});
|
||||
it('is degraded after migrations have ran', async () => {
|
||||
await expect(
|
||||
calculateStatus$(
|
||||
of<any>([{ status: 'skipped' }]),
|
||||
esStatus$
|
||||
)
|
||||
.pipe(take(2))
|
||||
.toPromise()
|
||||
).resolves.toEqual({
|
||||
level: ServiceStatusLevels.degraded,
|
||||
summary: 'SavedObjects service is degraded due to Elasticsearch: [xxx]',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
84
src/core/server/saved_objects/status.ts
Normal file
84
src/core/server/saved_objects/status.ts
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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 { Observable, combineLatest } from 'rxjs';
|
||||
import { startWith, map } from 'rxjs/operators';
|
||||
import { ServiceStatus, ServiceStatusLevels } from '../status';
|
||||
import { SavedObjectStatusMeta } from './types';
|
||||
import { KibanaMigratorStatus } from './migrations/kibana';
|
||||
|
||||
export const calculateStatus$ = (
|
||||
rawMigratorStatus$: Observable<KibanaMigratorStatus>,
|
||||
elasticsearchStatus$: Observable<ServiceStatus>
|
||||
): Observable<ServiceStatus<SavedObjectStatusMeta>> => {
|
||||
const migratorStatus$: Observable<ServiceStatus<SavedObjectStatusMeta>> = rawMigratorStatus$.pipe(
|
||||
map(migrationStatus => {
|
||||
if (migrationStatus.status === 'waiting') {
|
||||
return {
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: `SavedObjects service is waiting to start migrations`,
|
||||
};
|
||||
} else if (migrationStatus.status === 'running') {
|
||||
return {
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: `SavedObjects service is running migrations`,
|
||||
};
|
||||
}
|
||||
|
||||
const statusCounts: SavedObjectStatusMeta['migratedIndices'] = { migrated: 0, skipped: 0 };
|
||||
if (migrationStatus.result) {
|
||||
migrationStatus.result.forEach(({ status }) => {
|
||||
statusCounts[status] = (statusCounts[status] ?? 0) + 1;
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
level: ServiceStatusLevels.available,
|
||||
summary: `SavedObjects service has completed migrations and is available`,
|
||||
meta: {
|
||||
migratedIndices: statusCounts,
|
||||
},
|
||||
};
|
||||
}),
|
||||
startWith({
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: `SavedObjects service is waiting to start migrations`,
|
||||
})
|
||||
);
|
||||
|
||||
return combineLatest([elasticsearchStatus$, migratorStatus$]).pipe(
|
||||
map(([esStatus, migratorStatus]) => {
|
||||
if (esStatus.level >= ServiceStatusLevels.unavailable) {
|
||||
return {
|
||||
level: ServiceStatusLevels.unavailable,
|
||||
summary: `SavedObjects service is not available without a healthy Elasticearch connection`,
|
||||
};
|
||||
} else if (migratorStatus.level === ServiceStatusLevels.unavailable) {
|
||||
return migratorStatus;
|
||||
} else if (esStatus.level === ServiceStatusLevels.degraded) {
|
||||
return {
|
||||
level: esStatus.level,
|
||||
summary: `SavedObjects service is degraded due to Elasticsearch: [${esStatus.summary}]`,
|
||||
};
|
||||
} else {
|
||||
return migratorStatus;
|
||||
}
|
||||
})
|
||||
);
|
||||
};
|
|
@ -46,6 +46,19 @@ export {
|
|||
SavedObjectsMigrationVersion,
|
||||
} from '../../types';
|
||||
|
||||
/**
|
||||
* Meta information about the SavedObjectService's status. Available to plugins via {@link CoreSetup.status}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface SavedObjectStatusMeta {
|
||||
migratedIndices: {
|
||||
[status: string]: number;
|
||||
skipped: number;
|
||||
migrated: number;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @public
|
||||
|
|
|
@ -638,6 +638,8 @@ export interface CoreSetup<TPluginsStart extends object = object, TStart = unkno
|
|||
// (undocumented)
|
||||
savedObjects: SavedObjectsServiceSetup;
|
||||
// (undocumented)
|
||||
status: StatusServiceSetup;
|
||||
// (undocumented)
|
||||
uiSettings: UiSettingsServiceSetup;
|
||||
// (undocumented)
|
||||
uuid: UuidServiceSetup;
|
||||
|
@ -655,6 +657,14 @@ export interface CoreStart {
|
|||
uiSettings: UiSettingsServiceStart;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface CoreStatus {
|
||||
// (undocumented)
|
||||
elasticsearch: ServiceStatus;
|
||||
// (undocumented)
|
||||
savedObjects: ServiceStatus;
|
||||
}
|
||||
|
||||
// @public
|
||||
export class CspConfig implements ICspConfig {
|
||||
// @internal
|
||||
|
@ -794,6 +804,14 @@ export interface ElasticsearchServiceStart {
|
|||
};
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface ElasticsearchStatusMeta {
|
||||
// (undocumented)
|
||||
incompatibleNodes: NodesVersionCompatibility['incompatibleNodes'];
|
||||
// (undocumented)
|
||||
warningNodes: NodesVersionCompatibility['warningNodes'];
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface EnvironmentMode {
|
||||
// (undocumented)
|
||||
|
@ -1249,6 +1267,24 @@ export type MIGRATION_DEPRECATION_LEVEL = 'none' | 'info' | 'warning' | 'critica
|
|||
// @public
|
||||
export type MutatingOperationRefreshSetting = boolean | 'wait_for';
|
||||
|
||||
// Warning: (ae-missing-release-tag) "NodesVersionCompatibility" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface NodesVersionCompatibility {
|
||||
// Warning: (ae-forgotten-export) The symbol "NodeInfo" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
incompatibleNodes: NodeInfo[];
|
||||
// (undocumented)
|
||||
isCompatible: boolean;
|
||||
// (undocumented)
|
||||
kibanaVersion: string;
|
||||
// (undocumented)
|
||||
message?: string;
|
||||
// (undocumented)
|
||||
warningNodes: NodeInfo[];
|
||||
}
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "OnPostAuthResult" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// @public
|
||||
|
@ -2169,6 +2205,16 @@ export interface SavedObjectsServiceStart {
|
|||
getTypeRegistry: () => ISavedObjectTypeRegistry;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface SavedObjectStatusMeta {
|
||||
// (undocumented)
|
||||
migratedIndices: {
|
||||
[status: string]: number;
|
||||
skipped: number;
|
||||
migrated: number;
|
||||
};
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface SavedObjectsType {
|
||||
convertToAliasScript?: string;
|
||||
|
@ -2237,6 +2283,38 @@ export class ScopedClusterClient implements IScopedClusterClient {
|
|||
callAsInternalUser(endpoint: string, clientParams?: Record<string, any>, options?: CallAPIOptions): Promise<any>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface ServiceStatus<Meta extends Record<string, any> | unknown = unknown> {
|
||||
detail?: string;
|
||||
documentationUrl?: string;
|
||||
level: ServiceStatusLevel;
|
||||
meta?: Meta;
|
||||
summary: string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type ServiceStatusLevel = typeof ServiceStatusLevels[keyof typeof ServiceStatusLevels];
|
||||
|
||||
// @public
|
||||
export const ServiceStatusLevels: Readonly<{
|
||||
available: Readonly<{
|
||||
toString: () => "available";
|
||||
valueOf: () => 0;
|
||||
}>;
|
||||
degraded: Readonly<{
|
||||
toString: () => "degraded";
|
||||
valueOf: () => 1;
|
||||
}>;
|
||||
unavailable: Readonly<{
|
||||
toString: () => "unavailable";
|
||||
valueOf: () => 2;
|
||||
}>;
|
||||
critical: Readonly<{
|
||||
toString: () => "critical";
|
||||
valueOf: () => 3;
|
||||
}>;
|
||||
}>;
|
||||
|
||||
// @public
|
||||
export interface SessionCookieValidationResult {
|
||||
isValid: boolean;
|
||||
|
@ -2274,6 +2352,11 @@ export type SharedGlobalConfig = RecursiveReadonly_2<{
|
|||
// @public
|
||||
export type StartServicesAccessor<TPluginsStart extends object = object, TStart = unknown> = () => Promise<[CoreStart, TPluginsStart, TStart]>;
|
||||
|
||||
// @public
|
||||
export interface StatusServiceSetup {
|
||||
core$: Observable<CoreStatus>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type StringValidation = StringValidationRegex | StringValidationRegexString;
|
||||
|
||||
|
|
|
@ -85,3 +85,9 @@ export const mockMetricsService = metricsServiceMock.create();
|
|||
jest.doMock('./metrics/metrics_service', () => ({
|
||||
MetricsService: jest.fn(() => mockMetricsService),
|
||||
}));
|
||||
|
||||
import { statusServiceMock } from './status/status_service.mock';
|
||||
export const mockStatusService = statusServiceMock.create();
|
||||
jest.doMock('./status/status_service', () => ({
|
||||
StatusService: jest.fn(() => mockStatusService),
|
||||
}));
|
||||
|
|
|
@ -29,6 +29,7 @@ import {
|
|||
mockUiSettingsService,
|
||||
mockRenderingService,
|
||||
mockMetricsService,
|
||||
mockStatusService,
|
||||
} from './server.test.mocks';
|
||||
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
@ -63,6 +64,7 @@ test('sets up services on "setup"', async () => {
|
|||
expect(mockUiSettingsService.setup).not.toHaveBeenCalled();
|
||||
expect(mockRenderingService.setup).not.toHaveBeenCalled();
|
||||
expect(mockMetricsService.setup).not.toHaveBeenCalled();
|
||||
expect(mockStatusService.setup).not.toHaveBeenCalled();
|
||||
|
||||
await server.setup();
|
||||
|
||||
|
@ -74,6 +76,7 @@ test('sets up services on "setup"', async () => {
|
|||
expect(mockUiSettingsService.setup).toHaveBeenCalledTimes(1);
|
||||
expect(mockRenderingService.setup).toHaveBeenCalledTimes(1);
|
||||
expect(mockMetricsService.setup).toHaveBeenCalledTimes(1);
|
||||
expect(mockStatusService.setup).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('injects legacy dependency to context#setup()', async () => {
|
||||
|
@ -141,6 +144,7 @@ test('stops services on "stop"', async () => {
|
|||
expect(mockSavedObjectsService.stop).not.toHaveBeenCalled();
|
||||
expect(mockUiSettingsService.stop).not.toHaveBeenCalled();
|
||||
expect(mockMetricsService.stop).not.toHaveBeenCalled();
|
||||
expect(mockStatusService.stop).not.toHaveBeenCalled();
|
||||
|
||||
await server.stop();
|
||||
|
||||
|
@ -151,6 +155,7 @@ test('stops services on "stop"', async () => {
|
|||
expect(mockSavedObjectsService.stop).toHaveBeenCalledTimes(1);
|
||||
expect(mockUiSettingsService.stop).toHaveBeenCalledTimes(1);
|
||||
expect(mockMetricsService.stop).toHaveBeenCalledTimes(1);
|
||||
expect(mockStatusService.stop).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test(`doesn't setup core services if config validation fails`, async () => {
|
||||
|
@ -167,6 +172,7 @@ test(`doesn't setup core services if config validation fails`, async () => {
|
|||
expect(mockUiSettingsService.setup).not.toHaveBeenCalled();
|
||||
expect(mockRenderingService.setup).not.toHaveBeenCalled();
|
||||
expect(mockMetricsService.setup).not.toHaveBeenCalled();
|
||||
expect(mockStatusService.setup).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test(`doesn't setup core services if legacy config validation fails`, async () => {
|
||||
|
@ -187,4 +193,5 @@ test(`doesn't setup core services if legacy config validation fails`, async () =
|
|||
expect(mockSavedObjectsService.stop).not.toHaveBeenCalled();
|
||||
expect(mockUiSettingsService.setup).not.toHaveBeenCalled();
|
||||
expect(mockMetricsService.setup).not.toHaveBeenCalled();
|
||||
expect(mockStatusService.setup).not.toHaveBeenCalled();
|
||||
});
|
||||
|
|
|
@ -36,6 +36,9 @@ import { UiSettingsService } from './ui_settings';
|
|||
import { PluginsService, config as pluginsConfig } from './plugins';
|
||||
import { SavedObjectsService } from '../server/saved_objects';
|
||||
import { MetricsService, opsConfig } from './metrics';
|
||||
import { CapabilitiesService } from './capabilities';
|
||||
import { UuidService } from './uuid';
|
||||
import { StatusService } from './status/status_service';
|
||||
|
||||
import { config as cspConfig } from './csp';
|
||||
import { config as elasticsearchConfig } from './elasticsearch';
|
||||
|
@ -50,8 +53,6 @@ import { mapToObject } from '../utils';
|
|||
import { ContextService } from './context';
|
||||
import { RequestHandlerContext } from '.';
|
||||
import { InternalCoreSetup, InternalCoreStart } from './internal_types';
|
||||
import { CapabilitiesService } from './capabilities';
|
||||
import { UuidService } from './uuid';
|
||||
|
||||
const coreId = Symbol('core');
|
||||
const rootConfigPath = '';
|
||||
|
@ -70,6 +71,7 @@ export class Server {
|
|||
private readonly uiSettings: UiSettingsService;
|
||||
private readonly uuid: UuidService;
|
||||
private readonly metrics: MetricsService;
|
||||
private readonly status: StatusService;
|
||||
private readonly coreApp: CoreApp;
|
||||
|
||||
private pluginsInitialized?: boolean;
|
||||
|
@ -95,6 +97,7 @@ export class Server {
|
|||
this.capabilities = new CapabilitiesService(core);
|
||||
this.uuid = new UuidService(core);
|
||||
this.metrics = new MetricsService(core);
|
||||
this.status = new StatusService(core);
|
||||
this.coreApp = new CoreApp(core);
|
||||
}
|
||||
|
||||
|
@ -145,15 +148,21 @@ export class Server {
|
|||
|
||||
const metricsSetup = await this.metrics.setup({ http: httpSetup });
|
||||
|
||||
const statusSetup = this.status.setup({
|
||||
elasticsearch: elasticsearchServiceSetup,
|
||||
savedObjects: savedObjectsSetup,
|
||||
});
|
||||
|
||||
const coreSetup: InternalCoreSetup = {
|
||||
capabilities: capabilitiesSetup,
|
||||
context: contextServiceSetup,
|
||||
elasticsearch: elasticsearchServiceSetup,
|
||||
http: httpSetup,
|
||||
uiSettings: uiSettingsSetup,
|
||||
savedObjects: savedObjectsSetup,
|
||||
uuid: uuidSetup,
|
||||
metrics: metricsSetup,
|
||||
savedObjects: savedObjectsSetup,
|
||||
status: statusSetup,
|
||||
uiSettings: uiSettingsSetup,
|
||||
uuid: uuidSetup,
|
||||
};
|
||||
|
||||
const pluginsSetup = await this.plugins.setup(coreSetup);
|
||||
|
@ -220,6 +229,7 @@ export class Server {
|
|||
await this.uiSettings.stop();
|
||||
await this.rendering.stop();
|
||||
await this.metrics.stop();
|
||||
await this.status.stop();
|
||||
}
|
||||
|
||||
private registerCoreContext(coreSetup: InternalCoreSetup, rendering: RenderingServiceSetup) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue