diff --git a/.buildkite/scripts/steps/es_snapshots/build.sh b/.buildkite/scripts/steps/es_snapshots/build.sh
index c11f041836413..cdc1750e59bfc 100755
--- a/.buildkite/scripts/steps/es_snapshots/build.sh
+++ b/.buildkite/scripts/steps/es_snapshots/build.sh
@@ -69,6 +69,7 @@ echo "--- Build Elasticsearch"
:distribution:archives:darwin-aarch64-tar:assemble \
:distribution:archives:darwin-tar:assemble \
:distribution:docker:docker-export:assemble \
+ :distribution:docker:cloud-docker-export:assemble \
:distribution:archives:linux-aarch64-tar:assemble \
:distribution:archives:linux-tar:assemble \
:distribution:archives:windows-zip:assemble \
@@ -79,11 +80,26 @@ find distribution -type f \( -name 'elasticsearch-*-*-*-*.tar.gz' -o -name 'elas
ls -alh "$destination"
-echo "--- Create docker image archives"
+echo "--- Create docker default image archives"
docker images "docker.elastic.co/elasticsearch/elasticsearch"
docker images "docker.elastic.co/elasticsearch/elasticsearch" --format "{{.Tag}}" | xargs -n1 echo 'docker save docker.elastic.co/elasticsearch/elasticsearch:${0} | gzip > ../es-build/elasticsearch-${0}-docker-image.tar.gz'
docker images "docker.elastic.co/elasticsearch/elasticsearch" --format "{{.Tag}}" | xargs -n1 bash -c 'docker save docker.elastic.co/elasticsearch/elasticsearch:${0} | gzip > ../es-build/elasticsearch-${0}-docker-image.tar.gz'
+echo "--- Create kibana-ci docker cloud image archives"
+ES_CLOUD_ID=$(docker images "docker.elastic.co/elasticsearch-ci/elasticsearch-cloud" --format "{{.ID}}")
+ES_CLOUD_VERSION=$(docker images "docker.elastic.co/elasticsearch-ci/elasticsearch-cloud" --format "{{.Tag}}")
+KIBANA_ES_CLOUD_VERSION="$ES_CLOUD_VERSION-$ELASTICSEARCH_GIT_COMMIT"
+KIBANA_ES_CLOUD_IMAGE="docker.elastic.co/kibana-ci/elasticsearch-cloud:$KIBANA_ES_CLOUD_VERSION"
+
+docker tag "$ES_CLOUD_ID" "$KIBANA_ES_CLOUD_IMAGE"
+
+echo "$KIBANA_DOCKER_PASSWORD" | docker login -u "$KIBANA_DOCKER_USERNAME" --password-stdin docker.elastic.co
+trap 'docker logout docker.elastic.co' EXIT
+docker image push "$KIBANA_ES_CLOUD_IMAGE"
+
+export ELASTICSEARCH_CLOUD_IMAGE="$KIBANA_ES_CLOUD_IMAGE"
+export ELASTICSEARCH_CLOUD_IMAGE_CHECKSUM="$(docker images "$KIBANA_ES_CLOUD_IMAGE" --format "{{.Digest}}")"
+
echo "--- Create checksums for snapshot files"
cd "$destination"
find ./* -exec bash -c "shasum -a 512 {} > {}.sha512" \;
diff --git a/.buildkite/scripts/steps/es_snapshots/create_manifest.js b/.buildkite/scripts/steps/es_snapshots/create_manifest.js
index cb4ea29a9c534..9357cd72fff06 100644
--- a/.buildkite/scripts/steps/es_snapshots/create_manifest.js
+++ b/.buildkite/scripts/steps/es_snapshots/create_manifest.js
@@ -16,6 +16,8 @@ const { BASE_BUCKET_DAILY } = require('./bucket_config.js');
const destination = process.argv[2] || __dirname + '/test';
const ES_BRANCH = process.env.ELASTICSEARCH_BRANCH;
+ const ES_CLOUD_IMAGE = process.env.ELASTICSEARCH_CLOUD_IMAGE;
+ const ES_CLOUD_IMAGE_CHECKSUM = process.env.ELASTICSEARCH_CLOUD_IMAGE_CHECKSUM;
const GIT_COMMIT = process.env.ELASTICSEARCH_GIT_COMMIT;
const GIT_COMMIT_SHORT = process.env.ELASTICSEARCH_GIT_COMMIT_SHORT;
@@ -59,6 +61,17 @@ const { BASE_BUCKET_DAILY } = require('./bucket_config.js');
};
});
+ if (ES_CLOUD_IMAGE && ES_CLOUD_IMAGE_CHECKSUM) {
+ manifestEntries.push({
+ checksum: ES_CLOUD_IMAGE_CHECKSUM,
+ url: ES_CLOUD_IMAGE,
+ version: VERSION,
+ platform: 'docker',
+ architecture: 'image',
+ license: 'default',
+ });
+ }
+
const manifest = {
id: SNAPSHOT_ID,
bucket: `${BASE_BUCKET_DAILY}/${DESTINATION}`.toString(),
diff --git a/.eslintrc.js b/.eslintrc.js
index af9d77c4a9662..37c951e7e0763 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -274,12 +274,7 @@ module.exports = {
* Licence headers
*/
{
- files: [
- '**/*.{js,mjs,ts,tsx}',
- '!plugins/**/*',
- '!packages/elastic-datemath/**/*',
- '!packages/elastic-eslint-config-kibana/**/*',
- ],
+ files: ['**/*.{js,mjs,ts,tsx}'],
rules: {
'@kbn/eslint/require-license-header': [
'error',
diff --git a/docs/development/core/public/kibana-plugin-core-public.applicationstart.md b/docs/development/core/public/kibana-plugin-core-public.applicationstart.md
index cadf0f91b01d6..eeb8ff3753f13 100644
--- a/docs/development/core/public/kibana-plugin-core-public.applicationstart.md
+++ b/docs/development/core/public/kibana-plugin-core-public.applicationstart.md
@@ -25,5 +25,5 @@ export interface ApplicationStart
| --- | --- |
| [getUrlForApp(appId, options)](./kibana-plugin-core-public.applicationstart.geturlforapp.md) | Returns the absolute path (or URL) to a given app, including the global base path.By default, it returns the absolute path of the application (e.g /basePath/app/my-app
). Use the absolute
option to generate an absolute url instead (e.g http://host:port/basePath/app/my-app
)Note that when generating absolute urls, the origin (protocol, host and port) are determined from the browser's current location. |
| [navigateToApp(appId, options)](./kibana-plugin-core-public.applicationstart.navigatetoapp.md) | Navigate to a given app |
-| [navigateToUrl(url)](./kibana-plugin-core-public.applicationstart.navigatetourl.md) | Navigate to given URL in a SPA friendly way when possible (when the URL will redirect to a valid application within the current basePath).The method resolves pathnames the same way browsers do when resolving a <a href>
value. The provided url
can be: - an absolute URL - an absolute path - a path relative to the current URL (window.location.href)If all these criteria are true for the given URL: - (only for absolute URLs) The origin of the URL matches the origin of the browser's current location - The resolved pathname of the provided URL/path starts with the current basePath (eg. /mybasepath/s/my-space) - The pathname segment after the basePath matches any known application route (eg. /app// or any application's appRoute
configuration)Then a SPA navigation will be performed using navigateToApp
using the corresponding application and path. Otherwise, fallback to a full page reload to navigate to the url using window.location.assign
|
+| [navigateToUrl(url, options)](./kibana-plugin-core-public.applicationstart.navigatetourl.md) | Navigate to given URL in a SPA friendly way when possible (when the URL will redirect to a valid application within the current basePath).The method resolves pathnames the same way browsers do when resolving a <a href>
value. The provided url
can be: - an absolute URL - an absolute path - a path relative to the current URL (window.location.href)If all these criteria are true for the given URL: - (only for absolute URLs) The origin of the URL matches the origin of the browser's current location - The resolved pathname of the provided URL/path starts with the current basePath (eg. /mybasepath/s/my-space) - The pathname segment after the basePath matches any known application route (eg. /app// or any application's appRoute
configuration)Then a SPA navigation will be performed using navigateToApp
using the corresponding application and path. Otherwise, fallback to a full page reload to navigate to the url using window.location.assign
|
diff --git a/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md b/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md
index 9e6644e2b1ca7..b7fbb12f12e29 100644
--- a/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md
+++ b/docs/development/core/public/kibana-plugin-core-public.applicationstart.navigatetourl.md
@@ -15,7 +15,7 @@ Then a SPA navigation will be performed using `navigateToApp` using the correspo
Signature:
```typescript
-navigateToUrl(url: string): Promise;
+navigateToUrl(url: string, options?: NavigateToUrlOptions): Promise;
```
## Parameters
@@ -23,6 +23,7 @@ navigateToUrl(url: string): Promise;
| Parameter | Type | Description |
| --- | --- | --- |
| url | string | an absolute URL, an absolute path or a relative path, to navigate to. |
+| options | NavigateToUrlOptions | |
Returns:
diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md
index 2e51a036dfe9f..241cd378ebcda 100644
--- a/docs/development/core/public/kibana-plugin-core-public.md
+++ b/docs/development/core/public/kibana-plugin-core-public.md
@@ -85,6 +85,7 @@ The plugin integrates with the core system via lifecycle events: `setup`
| [IHttpResponseInterceptorOverrides](./kibana-plugin-core-public.ihttpresponseinterceptoroverrides.md) | Properties that can be returned by HttpInterceptor.request to override the response. |
| [IUiSettingsClient](./kibana-plugin-core-public.iuisettingsclient.md) | Client-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. [IUiSettingsClient](./kibana-plugin-core-public.iuisettingsclient.md) |
| [NavigateToAppOptions](./kibana-plugin-core-public.navigatetoappoptions.md) | Options for the [navigateToApp API](./kibana-plugin-core-public.applicationstart.navigatetoapp.md) |
+| [NavigateToUrlOptions](./kibana-plugin-core-public.navigatetourloptions.md) | Options for the [navigateToUrl API](./kibana-plugin-core-public.applicationstart.navigatetourl.md) |
| [NotificationsSetup](./kibana-plugin-core-public.notificationssetup.md) | |
| [NotificationsStart](./kibana-plugin-core-public.notificationsstart.md) | |
| [OverlayBannersStart](./kibana-plugin-core-public.overlaybannersstart.md) | |
diff --git a/docs/development/core/public/kibana-plugin-core-public.navigatetoappoptions.md b/docs/development/core/public/kibana-plugin-core-public.navigatetoappoptions.md
index c8ec5bdaf8c0d..337e9db1f80d2 100644
--- a/docs/development/core/public/kibana-plugin-core-public.navigatetoappoptions.md
+++ b/docs/development/core/public/kibana-plugin-core-public.navigatetoappoptions.md
@@ -20,5 +20,6 @@ export interface NavigateToAppOptions
| [openInNewTab?](./kibana-plugin-core-public.navigatetoappoptions.openinnewtab.md) | boolean | (Optional) if true, will open the app in new tab, will share session information via window.open if base |
| [path?](./kibana-plugin-core-public.navigatetoappoptions.path.md) | string | (Optional) optional path inside application to deep link to. If undefined, will use [the app's default path](./kibana-plugin-core-public.app.defaultpath.md) as default. |
| [replace?](./kibana-plugin-core-public.navigatetoappoptions.replace.md) | boolean | (Optional) if true, will not create a new history entry when navigating (using replace
instead of push
) |
+| [skipAppLeave?](./kibana-plugin-core-public.navigatetoappoptions.skipappleave.md) | boolean | (Optional) if true, will bypass the default onAppLeave behavior |
| [state?](./kibana-plugin-core-public.navigatetoappoptions.state.md) | unknown | (Optional) optional state to forward to the application |
diff --git a/docs/development/core/public/kibana-plugin-core-public.navigatetoappoptions.skipappleave.md b/docs/development/core/public/kibana-plugin-core-public.navigatetoappoptions.skipappleave.md
new file mode 100644
index 0000000000000..553d557a92daa
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-core-public.navigatetoappoptions.skipappleave.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [NavigateToAppOptions](./kibana-plugin-core-public.navigatetoappoptions.md) > [skipAppLeave](./kibana-plugin-core-public.navigatetoappoptions.skipappleave.md)
+
+## NavigateToAppOptions.skipAppLeave property
+
+if true, will bypass the default onAppLeave behavior
+
+Signature:
+
+```typescript
+skipAppLeave?: boolean;
+```
diff --git a/docs/development/core/public/kibana-plugin-core-public.navigatetourloptions.forceredirect.md b/docs/development/core/public/kibana-plugin-core-public.navigatetourloptions.forceredirect.md
new file mode 100644
index 0000000000000..1603524322dd7
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-core-public.navigatetourloptions.forceredirect.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [NavigateToUrlOptions](./kibana-plugin-core-public.navigatetourloptions.md) > [forceRedirect](./kibana-plugin-core-public.navigatetourloptions.forceredirect.md)
+
+## NavigateToUrlOptions.forceRedirect property
+
+if true, will redirect directly to the url
+
+Signature:
+
+```typescript
+forceRedirect?: boolean;
+```
diff --git a/docs/development/core/public/kibana-plugin-core-public.navigatetourloptions.md b/docs/development/core/public/kibana-plugin-core-public.navigatetourloptions.md
new file mode 100644
index 0000000000000..ccf09e21189ef
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-core-public.navigatetourloptions.md
@@ -0,0 +1,21 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [NavigateToUrlOptions](./kibana-plugin-core-public.navigatetourloptions.md)
+
+## NavigateToUrlOptions interface
+
+Options for the [navigateToUrl API](./kibana-plugin-core-public.applicationstart.navigatetourl.md)
+
+Signature:
+
+```typescript
+export interface NavigateToUrlOptions
+```
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [forceRedirect?](./kibana-plugin-core-public.navigatetourloptions.forceredirect.md) | boolean | (Optional) if true, will redirect directly to the url |
+| [skipAppLeave?](./kibana-plugin-core-public.navigatetourloptions.skipappleave.md) | boolean | (Optional) if true, will bypass the default onAppLeave behavior |
+
diff --git a/docs/development/core/public/kibana-plugin-core-public.navigatetourloptions.skipappleave.md b/docs/development/core/public/kibana-plugin-core-public.navigatetourloptions.skipappleave.md
new file mode 100644
index 0000000000000..f3685c02ff40d
--- /dev/null
+++ b/docs/development/core/public/kibana-plugin-core-public.navigatetourloptions.skipappleave.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [NavigateToUrlOptions](./kibana-plugin-core-public.navigatetourloptions.md) > [skipAppLeave](./kibana-plugin-core-public.navigatetourloptions.skipappleave.md)
+
+## NavigateToUrlOptions.skipAppLeave property
+
+if true, will bypass the default onAppLeave behavior
+
+Signature:
+
+```typescript
+skipAppLeave?: boolean;
+```
diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsfieldmapping.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsfieldmapping.md
index 85b52bacafa25..cf5b5d7e6e339 100644
--- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsfieldmapping.md
+++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsfieldmapping.md
@@ -13,5 +13,6 @@ Please refer to [elasticsearch documentation](https://www.elastic.co/guide/en/el
```typescript
export declare type SavedObjectsFieldMapping = estypes.MappingProperty & {
dynamic?: false | 'strict';
+ properties?: Record;
};
```
diff --git a/docs/management/connectors/action-types/servicenow-sir.asciidoc b/docs/management/connectors/action-types/servicenow-sir.asciidoc
index 70500b26c16e6..81db72be0fb38 100644
--- a/docs/management/connectors/action-types/servicenow-sir.asciidoc
+++ b/docs/management/connectors/action-types/servicenow-sir.asciidoc
@@ -5,7 +5,7 @@
ServiceNow SecOps
++++
-The {sn} SecOps connector uses the https://docs.servicenow.com/bundle/orlando-application-development/page/integrate/inbound-rest/concept/c_TableAPI.html[V2 Table API] to create {sn} security incidents.
+The {sn} SecOps connector uses the https://developer.servicenow.com/dev.do#!/reference/api/sandiego/rest/c_ImportSetAPI[Import Set API] to create {sn} security incidents.
[float]
[[servicenow-sir-connector-prerequisites]]
diff --git a/docs/management/connectors/action-types/servicenow.asciidoc b/docs/management/connectors/action-types/servicenow.asciidoc
index 73e3baaca2ad1..333a26c075c49 100644
--- a/docs/management/connectors/action-types/servicenow.asciidoc
+++ b/docs/management/connectors/action-types/servicenow.asciidoc
@@ -5,7 +5,7 @@
ServiceNow ITSM
++++
-The {sn} ITSM connector uses the https://docs.servicenow.com/bundle/orlando-application-development/page/integrate/inbound-rest/concept/c_TableAPI.html[V2 Table API] to create {sn} incidents.
+The {sn} ITSM connector uses the https://developer.servicenow.com/dev.do#!/reference/api/sandiego/rest/c_ImportSetAPI[Import Set API] to create {sn} incidents.
[float]
[[servicenow-itsm-connector-prerequisites]]
diff --git a/fleet_packages.json b/fleet_packages.json
index c620d438d4f8d..3a12e605316a7 100644
--- a/fleet_packages.json
+++ b/fleet_packages.json
@@ -27,7 +27,7 @@
},
{
"name": "fleet_server",
- "version": "1.1.0"
+ "version": "1.1.1"
},
{
"name": "synthetics",
diff --git a/package.json b/package.json
index 76a84675c2eb2..6e7886823fca1 100644
--- a/package.json
+++ b/package.json
@@ -106,7 +106,7 @@
"@elastic/apm-synthtrace": "link:bazel-bin/packages/elastic-apm-synthtrace",
"@elastic/charts": "45.1.1",
"@elastic/datemath": "link:bazel-bin/packages/elastic-datemath",
- "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.2.0-canary.1",
+ "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.2.0-canary.2",
"@elastic/ems-client": "8.2.0",
"@elastic/eui": "53.0.1",
"@elastic/filesaver": "1.1.2",
@@ -753,7 +753,7 @@
"callsites": "^3.1.0",
"chai": "3.5.0",
"chance": "1.0.18",
- "chromedriver": "^99.0.0",
+ "chromedriver": "^100.0.0",
"clean-webpack-plugin": "^3.0.0",
"cmd-shim": "^2.1.0",
"compression-webpack-plugin": "^4.0.0",
diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts
index 1d9406ac37447..7d209035ab65a 100644
--- a/packages/kbn-doc-links/src/get_doc_links.ts
+++ b/packages/kbn-doc-links/src/get_doc_links.ts
@@ -242,6 +242,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => {
asyncSearch: `${ELASTICSEARCH_DOCS}async-search-intro.html`,
dataStreams: `${ELASTICSEARCH_DOCS}data-streams.html`,
deprecationLogging: `${ELASTICSEARCH_DOCS}logging.html#deprecation-logging`,
+ createIndex: `${ELASTICSEARCH_DOCS}indices-create-index.html`,
frozenIndices: `${ELASTICSEARCH_DOCS}frozen-indices.html`,
gettingStarted: `${ELASTICSEARCH_DOCS}getting-started.html`,
hiddenIndices: `${ELASTICSEARCH_DOCS}multi-index.html#hidden`,
diff --git a/packages/kbn-securitysolution-io-ts-alerting-types/src/actions/index.ts b/packages/kbn-securitysolution-io-ts-alerting-types/src/actions/index.ts
index f984484dd4091..023af9fc7050e 100644
--- a/packages/kbn-securitysolution-io-ts-alerting-types/src/actions/index.ts
+++ b/packages/kbn-securitysolution-io-ts-alerting-types/src/actions/index.ts
@@ -12,8 +12,8 @@ import * as t from 'io-ts';
import { saved_object_attributes } from '../saved_object_attributes';
/**
- * Params is an "object", since it is a type of AlertActionParams which is action templates.
- * @see x-pack/plugins/alerting/common/alert.ts
+ * Params is an "object", since it is a type of RuleActionParams which is action templates.
+ * @see x-pack/plugins/alerting/common/rule.ts
*/
export const action_group = t.string;
export const action_id = t.string;
diff --git a/packages/kbn-shared-ux-components/src/index.ts b/packages/kbn-shared-ux-components/src/index.ts
index 9216f5b21d7f5..557ac980a14c6 100644
--- a/packages/kbn-shared-ux-components/src/index.ts
+++ b/packages/kbn-shared-ux-components/src/index.ts
@@ -95,6 +95,23 @@ export const LazyIconButtonGroup = React.lazy(() =>
*/
export const IconButtonGroup = withSuspense(LazyIconButtonGroup);
+/**
+ * The lazily loaded `KibanaPageTemplateSolutionNav` component that is wrapped by the `withSuspense` HOC. Consumers should use
+ * `React.Suspense` or `withSuspense` HOC to load this component.
+ */
+export const KibanaPageTemplateSolutionNavLazy = React.lazy(() =>
+ import('./page_template/solution_nav').then(({ KibanaPageTemplateSolutionNav }) => ({
+ default: KibanaPageTemplateSolutionNav,
+ }))
+);
+
+/**
+ * A `KibanaPageTemplateSolutionNav` component that is wrapped by the `withSuspense` HOC. This component can
+ * be used directly by consumers and will load the `KibanaPageTemplateSolutionNavLazy` component lazily with
+ * a predefined fallback and error boundary.
+ */
+export const KibanaPageTemplateSolutionNav = withSuspense(KibanaPageTemplateSolutionNavLazy);
+
/**
* The Lazily-loaded `KibanaSolutionAvatar` component. Consumers should use `React.Suspense` or
* the withSuspense` HOC to load this component.
diff --git a/packages/kbn-shared-ux-components/src/page_template/solution_nav/__snapshots__/solution_nav.test.tsx.snap b/packages/kbn-shared-ux-components/src/page_template/solution_nav/__snapshots__/solution_nav.test.tsx.snap
new file mode 100644
index 0000000000000..fce0e996d99cd
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/solution_nav/__snapshots__/solution_nav.test.tsx.snap
@@ -0,0 +1,267 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`KibanaPageTemplateSolutionNav accepts EuiSideNavProps 1`] = `
+
+
+
+ Solution
+
+
+ }
+ isOpenOnMobile={false}
+ items={
+ Array [
+ Object {
+ "id": "1",
+ "items": Array [
+ Object {
+ "id": "1.1",
+ "items": undefined,
+ "name": "Ingest Node Pipelines",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "1.2",
+ "items": undefined,
+ "name": "Logstash Pipelines",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "1.3",
+ "items": undefined,
+ "name": "Beats Central Management",
+ "tabIndex": undefined,
+ },
+ ],
+ "name": "Ingest",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "2",
+ "items": Array [
+ Object {
+ "id": "2.1",
+ "items": undefined,
+ "name": "Index Management",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "2.2",
+ "items": undefined,
+ "name": "Index Lifecycle Policies",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "2.3",
+ "items": undefined,
+ "name": "Snapshot and Restore",
+ "tabIndex": undefined,
+ },
+ ],
+ "name": "Data",
+ "tabIndex": undefined,
+ },
+ ]
+ }
+ mobileTitle={
+
+
+
+ }
+ toggleOpenOnMobile={[Function]}
+ />
+
+`;
+
+exports[`KibanaPageTemplateSolutionNav renders 1`] = `
+
+
+
+ Solution
+
+
+ }
+ isOpenOnMobile={false}
+ items={
+ Array [
+ Object {
+ "id": "1",
+ "items": Array [
+ Object {
+ "id": "1.1",
+ "items": undefined,
+ "name": "Ingest Node Pipelines",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "1.2",
+ "items": undefined,
+ "name": "Logstash Pipelines",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "1.3",
+ "items": undefined,
+ "name": "Beats Central Management",
+ "tabIndex": undefined,
+ },
+ ],
+ "name": "Ingest",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "2",
+ "items": Array [
+ Object {
+ "id": "2.1",
+ "items": undefined,
+ "name": "Index Management",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "2.2",
+ "items": undefined,
+ "name": "Index Lifecycle Policies",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "2.3",
+ "items": undefined,
+ "name": "Snapshot and Restore",
+ "tabIndex": undefined,
+ },
+ ],
+ "name": "Data",
+ "tabIndex": undefined,
+ },
+ ]
+ }
+ mobileTitle={
+
+
+
+ }
+ toggleOpenOnMobile={[Function]}
+ />
+
+`;
+
+exports[`KibanaPageTemplateSolutionNav renders with icon 1`] = `
+
+
+
+
+ Solution
+
+
+ }
+ isOpenOnMobile={false}
+ items={
+ Array [
+ Object {
+ "id": "1",
+ "items": Array [
+ Object {
+ "id": "1.1",
+ "items": undefined,
+ "name": "Ingest Node Pipelines",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "1.2",
+ "items": undefined,
+ "name": "Logstash Pipelines",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "1.3",
+ "items": undefined,
+ "name": "Beats Central Management",
+ "tabIndex": undefined,
+ },
+ ],
+ "name": "Ingest",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "2",
+ "items": Array [
+ Object {
+ "id": "2.1",
+ "items": undefined,
+ "name": "Index Management",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "2.2",
+ "items": undefined,
+ "name": "Index Lifecycle Policies",
+ "tabIndex": undefined,
+ },
+ Object {
+ "id": "2.3",
+ "items": undefined,
+ "name": "Snapshot and Restore",
+ "tabIndex": undefined,
+ },
+ ],
+ "name": "Data",
+ "tabIndex": undefined,
+ },
+ ]
+ }
+ mobileTitle={
+
+
+
+
+ }
+ toggleOpenOnMobile={[Function]}
+ />
+
+`;
diff --git a/packages/kbn-shared-ux-components/src/page_template/solution_nav/__snapshots__/solution_nav_collapse_button.test.tsx.snap b/packages/kbn-shared-ux-components/src/page_template/solution_nav/__snapshots__/solution_nav_collapse_button.test.tsx.snap
new file mode 100644
index 0000000000000..d2548b3e8df43
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/solution_nav/__snapshots__/solution_nav_collapse_button.test.tsx.snap
@@ -0,0 +1,23 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`KibanaPageTemplateSolutionNavCollapseButton isCollapsed 1`] = `
+
+`;
+
+exports[`KibanaPageTemplateSolutionNavCollapseButton renders 1`] = `
+
+`;
diff --git a/packages/kbn-shared-ux-components/src/page_template/solution_nav/index.ts b/packages/kbn-shared-ux-components/src/page_template/solution_nav/index.ts
new file mode 100644
index 0000000000000..59ef2924b048d
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/solution_nav/index.ts
@@ -0,0 +1,12 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+export type { KibanaPageTemplateSolutionNavProps } from './solution_nav';
+export { KibanaPageTemplateSolutionNav } from './solution_nav';
+export type { KibanaPageTemplateSolutionNavCollapseButtonProps } from './solution_nav_collapse_button';
+export { KibanaPageTemplateSolutionNavCollapseButton } from './solution_nav_collapse_button';
diff --git a/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav.scss b/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav.scss
new file mode 100644
index 0000000000000..d0070cef729b7
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav.scss
@@ -0,0 +1,30 @@
+$euiSideNavEmphasizedBackgroundColor: transparentize($euiColorLightShade, .7);
+@import '@elastic/eui/src/components/side_nav/mixins';
+
+// Put the page background color in the flyout version too
+.kbnPageTemplateSolutionNav__flyout {
+ background-color: $euiPageBackgroundColor;
+}
+
+.kbnPageTemplateSolutionNav {
+ @include euiSideNavEmbellish;
+ @include euiYScroll;
+
+ @include euiBreakpoint('m' ,'l', 'xl') {
+ width: 248px;
+ padding: $euiSizeL;
+ }
+
+ .kbnPageTemplateSolutionNavAvatar {
+ margin-right: $euiSize;
+ }
+}
+
+.kbnPageTemplateSolutionNav--hidden {
+ pointer-events: none;
+ opacity: 0;
+
+ @include euiCanAnimate {
+ transition: opacity $euiAnimSpeedFast $euiAnimSlightResistance;
+ }
+}
diff --git a/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav.stories.tsx b/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav.stories.tsx
new file mode 100644
index 0000000000000..5ff1e2c07d9d8
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav.stories.tsx
@@ -0,0 +1,72 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React from 'react';
+import { KibanaPageTemplateSolutionNav, KibanaPageTemplateSolutionNavProps } from './solution_nav';
+
+export default {
+ title: 'Page Template/Solution Nav/Solution Nav',
+ description: 'Solution-specific navigation for the sidebar',
+};
+
+type Params = Pick;
+
+const items: KibanaPageTemplateSolutionNavProps['items'] = [
+ {
+ name: Ingest
,
+ id: '1',
+ items: [
+ {
+ name: 'Ingest Node Pipelines',
+ id: '1.1',
+ },
+ {
+ name: 'Logstash Pipelines',
+ id: '1.2',
+ },
+ {
+ name: 'Beats Central Management',
+ id: '1.3',
+ },
+ ],
+ },
+ {
+ name: 'Data',
+ id: '2',
+ items: [
+ {
+ name: 'Index Management',
+ id: '2.1',
+ },
+ {
+ name: 'Index Lifecycle Policies',
+ id: '2.2',
+ },
+ {
+ name: 'Snapshot and Restore',
+ id: '2.3',
+ },
+ ],
+ },
+];
+
+export const PureComponent = (params: Params) => {
+ return ;
+};
+
+PureComponent.argTypes = {
+ name: {
+ control: 'text',
+ defaultValue: 'Kibana',
+ },
+ icon: {
+ control: { type: 'radio' },
+ options: ['logoKibana', 'logoObservability', 'logoSecurity'],
+ defaultValue: 'logoKibana',
+ },
+};
diff --git a/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav.test.tsx b/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav.test.tsx
new file mode 100644
index 0000000000000..ed90894289169
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav.test.tsx
@@ -0,0 +1,77 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React from 'react';
+import { shallow } from 'enzyme';
+import { KibanaPageTemplateSolutionNav, KibanaPageTemplateSolutionNavProps } from './solution_nav';
+
+jest.mock('@elastic/eui', () => ({
+ useIsWithinBreakpoints: (args: string[]) => {
+ return args[0] === 'xs';
+ },
+}));
+
+const items: KibanaPageTemplateSolutionNavProps['items'] = [
+ {
+ name: 'Ingest',
+ id: '1',
+ items: [
+ {
+ name: 'Ingest Node Pipelines',
+ id: '1.1',
+ },
+ {
+ name: 'Logstash Pipelines',
+ id: '1.2',
+ },
+ {
+ name: 'Beats Central Management',
+ id: '1.3',
+ },
+ ],
+ },
+ {
+ name: 'Data',
+ id: '2',
+ items: [
+ {
+ name: 'Index Management',
+ id: '2.1',
+ },
+ {
+ name: 'Index Lifecycle Policies',
+ id: '2.2',
+ },
+ {
+ name: 'Snapshot and Restore',
+ id: '2.3',
+ },
+ ],
+ },
+];
+
+describe('KibanaPageTemplateSolutionNav', () => {
+ test('renders', () => {
+ const component = shallow();
+ expect(component).toMatchSnapshot();
+ });
+
+ test('renders with icon', () => {
+ const component = shallow(
+
+ );
+ expect(component).toMatchSnapshot();
+ });
+
+ test('accepts EuiSideNavProps', () => {
+ const component = shallow(
+
+ );
+ expect(component).toMatchSnapshot();
+ });
+});
diff --git a/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav.tsx b/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav.tsx
new file mode 100644
index 0000000000000..8bc91789c7054
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav.tsx
@@ -0,0 +1,164 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+import './solution_nav.scss';
+
+import React, { FunctionComponent, useState } from 'react';
+import { FormattedMessage } from '@kbn/i18n-react';
+
+import {
+ EuiAvatarProps,
+ EuiFlyout,
+ EuiSideNav,
+ EuiSideNavItemType,
+ EuiSideNavProps,
+ useIsWithinBreakpoints,
+} from '@elastic/eui';
+
+import classNames from 'classnames';
+import { KibanaSolutionAvatar } from '../../solution_avatar';
+import { KibanaPageTemplateSolutionNavCollapseButton } from './solution_nav_collapse_button';
+
+export type KibanaPageTemplateSolutionNavProps = EuiSideNavProps<{}> & {
+ /**
+ * Name of the solution, i.e. "Observability"
+ */
+ name: EuiAvatarProps['name'];
+ /**
+ * Solution logo, i.e. "logoObservability"
+ */
+ icon?: EuiAvatarProps['iconType'];
+ /**
+ * Control the collapsed state
+ */
+ isOpenOnDesktop?: boolean;
+ onCollapse?: () => void;
+};
+
+const FLYOUT_SIZE = 248;
+
+const setTabIndex = (items: Array>, isHidden: boolean) => {
+ return items.map((item) => {
+ // @ts-ignore-next-line Can be removed on close of https://github.com/elastic/eui/issues/4925
+ item.tabIndex = isHidden ? -1 : undefined;
+ item.items = item.items && setTabIndex(item.items, isHidden);
+ return item;
+ });
+};
+
+/**
+ * A wrapper around EuiSideNav but also creates the appropriate title with optional solution logo
+ */
+export const KibanaPageTemplateSolutionNav: FunctionComponent<
+ KibanaPageTemplateSolutionNavProps
+> = ({ name, icon, items, isOpenOnDesktop = false, onCollapse, ...rest }) => {
+ const isSmallerBreakpoint = useIsWithinBreakpoints(['xs', 's']);
+ const isMediumBreakpoint = useIsWithinBreakpoints(['m']);
+ const isLargerBreakpoint = useIsWithinBreakpoints(['l', 'xl']);
+
+ // This is used for both the EuiSideNav and EuiFlyout toggling
+ const [isSideNavOpenOnMobile, setIsSideNavOpenOnMobile] = useState(false);
+ const toggleOpenOnMobile = () => {
+ setIsSideNavOpenOnMobile(!isSideNavOpenOnMobile);
+ };
+
+ const isHidden = isLargerBreakpoint && !isOpenOnDesktop;
+
+ /**
+ * Create the avatar
+ */
+ const solutionAvatar = icon ? (
+
+ ) : null;
+
+ /**
+ * Create the titles
+ */
+ const titleText = (
+ <>
+ {solutionAvatar}
+ {name}
+ >
+ );
+ const mobileTitleText = (
+
+ );
+
+ /**
+ * Create the side nav component
+ */
+
+ const sideNav = () => {
+ if (!items) {
+ return null;
+ }
+ const sideNavClasses = classNames('kbnPageTemplateSolutionNav', {
+ 'kbnPageTemplateSolutionNav--hidden': isHidden,
+ });
+ return (
+
+ {solutionAvatar}
+ {mobileTitleText}
+ >
+ }
+ toggleOpenOnMobile={toggleOpenOnMobile}
+ isOpenOnMobile={isSideNavOpenOnMobile}
+ items={setTabIndex(items, isHidden)}
+ {...rest}
+ />
+ );
+ };
+
+ return (
+ <>
+ {isSmallerBreakpoint && sideNav()}
+ {isMediumBreakpoint && (
+ <>
+ {isSideNavOpenOnMobile && (
+ setIsSideNavOpenOnMobile(false)}
+ side="left"
+ size={FLYOUT_SIZE}
+ closeButtonPosition="outside"
+ className="kbnPageTemplateSolutionNav__flyout"
+ >
+ {sideNav()}
+
+ )}
+
+ >
+ )}
+ {isLargerBreakpoint && (
+ <>
+ {sideNav()}
+
+ >
+ )}
+ >
+ );
+};
diff --git a/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav_collapse_button.scss b/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav_collapse_button.scss
new file mode 100644
index 0000000000000..61cea7962d956
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav_collapse_button.scss
@@ -0,0 +1,47 @@
+.kbnPageTemplateSolutionNavCollapseButton {
+ position: absolute;
+ opacity: 0;
+ left: 248px - $euiSize;
+ top: $euiSizeL;
+ z-index: 2;
+
+ @include euiCanAnimate {
+ transition: opacity $euiAnimSpeedFast, left $euiAnimSpeedFast, background $euiAnimSpeedFast;
+ }
+
+ &:hover,
+ &:focus {
+ transition-delay: 0s !important;
+ }
+
+ .kbnPageTemplate__pageSideBar:hover &,
+ &:hover,
+ &:focus {
+ opacity: 1;
+ left: 248px - $euiSizeL;
+ }
+
+ .kbnPageTemplate__pageSideBar:hover & {
+ transition-delay: $euiAnimSpeedSlow * 2;
+ }
+
+ &:not(&-isCollapsed) {
+ background-color: $euiColorEmptyShade !important; // Override all states
+ }
+}
+
+// Make the button take up the entire area of the collapsed navigation
+.kbnPageTemplateSolutionNavCollapseButton-isCollapsed {
+ opacity: 1 !important;
+ transition-delay: 0s !important;
+ left: 0 !important;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ height: 100%;
+ width: 100%;
+ border-radius: 0;
+ // Keep the icon at the top instead of it getting shifted to the center of the page
+ padding-top: $euiSizeL + $euiSizeS;
+ align-items: flex-start;
+}
diff --git a/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav_collapse_button.test.tsx b/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav_collapse_button.test.tsx
new file mode 100644
index 0000000000000..e7df2ddd54582
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav_collapse_button.test.tsx
@@ -0,0 +1,29 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { shallow } from 'enzyme';
+import React from 'react';
+import { KibanaPageTemplateSolutionNavCollapseButton } from './solution_nav_collapse_button';
+
+describe('KibanaPageTemplateSolutionNavCollapseButton', () => {
+ test('renders', () => {
+ const component = shallow();
+ expect(component).toMatchSnapshot();
+ expect(component.find('.kbnPageTemplateSolutionNavCollapseButton').prop('title')).toBe(
+ 'Collapse side navigation'
+ );
+ });
+
+ test('isCollapsed', () => {
+ const component = shallow();
+ expect(component).toMatchSnapshot();
+ expect(component.find('.kbnPageTemplateSolutionNavCollapseButton').prop('title')).toBe(
+ 'Open side navigation'
+ );
+ });
+});
diff --git a/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav_collapse_button.tsx b/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav_collapse_button.tsx
new file mode 100644
index 0000000000000..35890b935ad3e
--- /dev/null
+++ b/packages/kbn-shared-ux-components/src/page_template/solution_nav/solution_nav_collapse_button.tsx
@@ -0,0 +1,59 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+import './solution_nav_collapse_button.scss';
+
+import React from 'react';
+import classNames from 'classnames';
+
+import { EuiButtonIcon, EuiButtonIconPropsForButton } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+export type KibanaPageTemplateSolutionNavCollapseButtonProps =
+ Partial & {
+ /**
+ * Boolean state of current collapsed status
+ */
+ isCollapsed: boolean;
+ };
+
+const collapseLabel = i18n.translate('sharedUXComponents.solutionNav.collapsibleLabel', {
+ defaultMessage: 'Collapse side navigation',
+});
+
+const openLabel = i18n.translate('sharedUXComponents.solutionNav.openLabel', {
+ defaultMessage: 'Open side navigation',
+});
+
+/**
+ * Creates the styled icon button for showing/hiding solution nav
+ */
+export const KibanaPageTemplateSolutionNavCollapseButton = ({
+ className,
+ isCollapsed,
+ ...rest
+}: KibanaPageTemplateSolutionNavCollapseButtonProps) => {
+ const classes = classNames(
+ 'kbnPageTemplateSolutionNavCollapseButton',
+ {
+ 'kbnPageTemplateSolutionNavCollapseButton-isCollapsed': isCollapsed,
+ },
+ className
+ );
+
+ return (
+
+ );
+};
diff --git a/packages/kbn-shared-ux-components/src/solution_avatar/index.tsx b/packages/kbn-shared-ux-components/src/solution_avatar/index.tsx
index db31c0fd5a3d4..efc597cbdcb13 100644
--- a/packages/kbn-shared-ux-components/src/solution_avatar/index.tsx
+++ b/packages/kbn-shared-ux-components/src/solution_avatar/index.tsx
@@ -5,5 +5,5 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
-
export { KibanaSolutionAvatar } from './solution_avatar';
+export type { KibanaSolutionAvatarProps } from './solution_avatar';
diff --git a/packages/kbn-shared-ux-components/src/solution_avatar/solution_avatar.tsx b/packages/kbn-shared-ux-components/src/solution_avatar/solution_avatar.tsx
index 78459b90e4b3b..deb71affc9c1a 100644
--- a/packages/kbn-shared-ux-components/src/solution_avatar/solution_avatar.tsx
+++ b/packages/kbn-shared-ux-components/src/solution_avatar/solution_avatar.tsx
@@ -8,9 +8,9 @@
import './solution_avatar.scss';
import React from 'react';
-import classNames from 'classnames';
import { DistributiveOmit, EuiAvatar, EuiAvatarProps } from '@elastic/eui';
+import classNames from 'classnames';
export type KibanaSolutionAvatarProps = DistributiveOmit & {
/**
@@ -20,7 +20,7 @@ export type KibanaSolutionAvatarProps = DistributiveOmit
};
/**
- * Applies extra styling to a typical EuiAvatar;
+ * Applies extra styling to a typical EuiAvatar.
* The `name` value will be appended to 'logo' to configure the `iconType` unless `iconType` is provided.
*/
export const KibanaSolutionAvatar = ({ className, size, ...rest }: KibanaSolutionAvatarProps) => {
@@ -34,9 +34,9 @@ export const KibanaSolutionAvatar = ({ className, size, ...rest }: KibanaSolutio
},
className
)}
- color="plain"
size={size === 'xxl' ? 'xl' : size}
iconSize={size}
+ color="plain"
iconType={`logo${rest.name}`}
{...rest}
/>
diff --git a/src/core/public/application/application_service.test.ts b/src/core/public/application/application_service.test.ts
index ccb0b220e0243..bb7378ff1f0f3 100644
--- a/src/core/public/application/application_service.test.ts
+++ b/src/core/public/application/application_service.test.ts
@@ -898,10 +898,9 @@ describe('#start()', () => {
it('should call private function shouldNavigate with overlays and the nextAppId', async () => {
service.setup(setupDeps);
- const shouldNavigateSpy = jest.spyOn(service as any, 'shouldNavigate');
+ const shouldNavigateSpy = jest.spyOn(service as any, 'shouldNavigate');
const { navigateToApp } = await service.start(startDeps);
-
await navigateToApp('myTestApp');
expect(shouldNavigateSpy).toHaveBeenCalledWith(startDeps.overlays, 'myTestApp');
@@ -909,6 +908,14 @@ describe('#start()', () => {
expect(shouldNavigateSpy).toHaveBeenCalledWith(startDeps.overlays, 'myOtherApp');
});
+ it('should call private function shouldNavigate with overlays, nextAppId and skipAppLeave', async () => {
+ service.setup(setupDeps);
+ const shouldNavigateSpy = jest.spyOn(service as any, 'shouldNavigate');
+ const { navigateToApp } = await service.start(startDeps);
+ await navigateToApp('myTestApp', { skipAppLeave: true });
+ expect(shouldNavigateSpy).not.toHaveBeenCalledWith(startDeps.overlays, 'myTestApp');
+ });
+
describe('when `replace` option is true', () => {
it('use `history.replace` instead of `history.push`', async () => {
service.setup(setupDeps);
@@ -1117,6 +1124,63 @@ describe('#start()', () => {
expect(MockHistory.push).toHaveBeenCalledWith('/app/foo/some-path', undefined);
expect(setupDeps.redirectTo).not.toHaveBeenCalled();
});
+
+ describe('navigateToUrl with options', () => {
+ let addListenerSpy: jest.SpyInstance;
+ let removeListenerSpy: jest.SpyInstance;
+ beforeEach(() => {
+ addListenerSpy = jest.spyOn(window, 'addEventListener');
+ removeListenerSpy = jest.spyOn(window, 'removeEventListener');
+ });
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+
+ it('calls `navigateToApp` with `skipAppLeave` option', async () => {
+ parseAppUrlMock.mockReturnValue({ app: 'foo', path: '/some-path' });
+ service.setup(setupDeps);
+ const { navigateToUrl } = await service.start(startDeps);
+
+ await navigateToUrl('/an-app-path', { skipAppLeave: true });
+
+ expect(MockHistory.push).toHaveBeenCalledWith('/app/foo/some-path', undefined);
+ expect(setupDeps.redirectTo).not.toHaveBeenCalled();
+ });
+
+ it('calls `redirectTo` when `forceRedirect` option is true', async () => {
+ parseAppUrlMock.mockReturnValue({ app: 'foo', path: '/some-path' });
+ service.setup(setupDeps);
+
+ const { navigateToUrl } = await service.start(startDeps);
+
+ await navigateToUrl('/an-app-path', { forceRedirect: true });
+
+ expect(addListenerSpy).toHaveBeenCalledTimes(1);
+ expect(addListenerSpy).toHaveBeenCalledWith('beforeunload', expect.any(Function));
+
+ expect(setupDeps.redirectTo).toHaveBeenCalledWith('/an-app-path');
+ expect(MockHistory.push).not.toHaveBeenCalled();
+ });
+
+ it('removes the beforeunload listener and calls `redirectTo` when `forceRedirect` and `skipAppLeave` option are both true', async () => {
+ parseAppUrlMock.mockReturnValue({ app: 'foo', path: '/some-path' });
+ service.setup(setupDeps);
+
+ const { navigateToUrl } = await service.start(startDeps);
+
+ await navigateToUrl('/an-app-path', { skipAppLeave: true, forceRedirect: true });
+
+ expect(addListenerSpy).toHaveBeenCalledTimes(1);
+ expect(addListenerSpy).toHaveBeenCalledWith('beforeunload', expect.any(Function));
+ const handler = addListenerSpy.mock.calls[0][1];
+
+ expect(MockHistory.push).toHaveBeenCalledTimes(0);
+ expect(setupDeps.redirectTo).toHaveBeenCalledWith('/an-app-path');
+
+ expect(removeListenerSpy).toHaveBeenCalledTimes(1);
+ expect(removeListenerSpy).toHaveBeenCalledWith('beforeunload', handler);
+ });
+ });
});
});
diff --git a/src/core/public/application/application_service.tsx b/src/core/public/application/application_service.tsx
index 1cfae598f67c8..d49a33e3f1371 100644
--- a/src/core/public/application/application_service.tsx
+++ b/src/core/public/application/application_service.tsx
@@ -31,6 +31,7 @@ import {
InternalApplicationStart,
Mounter,
NavigateToAppOptions,
+ NavigateToUrlOptions,
} from './types';
import { getLeaveAction, isConfirmAction } from './application_leave';
import { getUserConfirmationHandler } from './navigation_confirm';
@@ -234,13 +235,19 @@ export class ApplicationService {
const navigateToApp: InternalApplicationStart['navigateToApp'] = async (
appId,
- { deepLinkId, path, state, replace = false, openInNewTab = false }: NavigateToAppOptions = {}
+ {
+ deepLinkId,
+ path,
+ state,
+ replace = false,
+ openInNewTab = false,
+ skipAppLeave = false,
+ }: NavigateToAppOptions = {}
) => {
const currentAppId = this.currentAppId$.value;
const navigatingToSameApp = currentAppId === appId;
- const shouldNavigate = navigatingToSameApp
- ? true
- : await this.shouldNavigate(overlays, appId);
+ const shouldNavigate =
+ navigatingToSameApp || skipAppLeave ? true : await this.shouldNavigate(overlays, appId);
const targetApp = applications$.value.get(appId);
@@ -304,13 +311,20 @@ export class ApplicationService {
return absolute ? relativeToAbsolute(relUrl) : relUrl;
},
navigateToApp,
- navigateToUrl: async (url) => {
+ navigateToUrl: async (
+ url: string,
+ { skipAppLeave = false, forceRedirect = false }: NavigateToUrlOptions = {}
+ ) => {
const appInfo = parseAppUrl(url, http.basePath, this.apps);
- if (appInfo) {
- return navigateToApp(appInfo.app, { path: appInfo.path });
- } else {
+ if ((forceRedirect || !appInfo) === true) {
+ if (skipAppLeave) {
+ window.removeEventListener('beforeunload', this.onBeforeUnload);
+ }
return this.redirectTo!(url);
}
+ if (appInfo) {
+ return navigateToApp(appInfo.app, { path: appInfo.path, skipAppLeave });
+ }
},
getComponent: () => {
if (!this.history) {
diff --git a/src/core/public/application/index.ts b/src/core/public/application/index.ts
index 882555fcd60e0..55ac8f47becfa 100644
--- a/src/core/public/application/index.ts
+++ b/src/core/public/application/index.ts
@@ -28,6 +28,7 @@ export type {
AppLeaveDefaultAction,
AppLeaveConfirmAction,
NavigateToAppOptions,
+ NavigateToUrlOptions,
PublicAppInfo,
PublicAppDeepLinkInfo,
// Internal types
diff --git a/src/core/public/application/integration_tests/application_service.test.tsx b/src/core/public/application/integration_tests/application_service.test.tsx
index dda029c66f4c3..99e6d86b6a941 100644
--- a/src/core/public/application/integration_tests/application_service.test.tsx
+++ b/src/core/public/application/integration_tests/application_service.test.tsx
@@ -170,7 +170,28 @@ describe('ApplicationService', () => {
'/app/app1/deep-link',
]);
});
- ////
+
+ it('handles `skipOnAppLeave` option', async () => {
+ const { register } = service.setup(setupDeps);
+
+ register(Symbol(), {
+ id: 'app1',
+ title: 'App1',
+ mount: async ({}: AppMountParameters) => {
+ return () => undefined;
+ },
+ });
+
+ const { navigateToApp } = await service.start(startDeps);
+
+ await navigateToApp('app1', { path: '/foo' });
+ await navigateToApp('app1', { path: '/bar', skipAppLeave: true });
+ expect(history.entries.map((entry) => entry.pathname)).toEqual([
+ '/',
+ '/app/app1/foo',
+ '/app/app1/bar',
+ ]);
+ });
});
});
@@ -249,6 +270,38 @@ describe('ApplicationService', () => {
expect(history.entries[2].pathname).toEqual('/app/app2');
});
+ it('does not trigger the action if `skipAppLeave` is true', async () => {
+ const { register } = service.setup(setupDeps);
+
+ register(Symbol(), {
+ id: 'app1',
+ title: 'App1',
+ mount: ({ onAppLeave }: AppMountParameters) => {
+ onAppLeave((actions) => actions.confirm('confirmation-message', 'confirmation-title'));
+ return () => undefined;
+ },
+ });
+ register(Symbol(), {
+ id: 'app2',
+ title: 'App2',
+ mount: ({}: AppMountParameters) => {
+ return () => undefined;
+ },
+ });
+
+ const { navigateToApp, getComponent } = await service.start(startDeps);
+
+ update = createRenderer(getComponent());
+
+ await act(async () => {
+ await navigate('/app/app1');
+ await navigateToApp('app2', { skipAppLeave: true });
+ });
+ expect(startDeps.overlays.openConfirm).toHaveBeenCalledTimes(0);
+ expect(history.entries.length).toEqual(3);
+ expect(history.entries[1].pathname).toEqual('/app/app1');
+ });
+
it('blocks navigation to the new app if action is confirm and user declined', async () => {
startDeps.overlays.openConfirm.mockResolvedValue(false);
diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts
index 659145a9958f1..4e96e96505083 100644
--- a/src/core/public/application/types.ts
+++ b/src/core/public/application/types.ts
@@ -740,6 +740,26 @@ export interface NavigateToAppOptions {
* if true, will open the app in new tab, will share session information via window.open if base
*/
openInNewTab?: boolean;
+
+ /**
+ * if true, will bypass the default onAppLeave behavior
+ */
+ skipAppLeave?: boolean;
+}
+
+/**
+ * Options for the {@link ApplicationStart.navigateToUrl | navigateToUrl API}
+ * @public
+ */
+export interface NavigateToUrlOptions {
+ /**
+ * if true, will bypass the default onAppLeave behavior
+ */
+ skipAppLeave?: boolean;
+ /**
+ * if true will force a full page reload/refresh/assign, overriding the outcome of other url checks against current the location (effectively using `window.location.assign` instead of `push`)
+ */
+ forceRedirect?: boolean;
}
/** @public */
@@ -781,7 +801,7 @@ export interface ApplicationStart {
* - The pathname segment after the basePath matches any known application route (eg. /app// or any application's `appRoute` configuration)
*
* Then a SPA navigation will be performed using `navigateToApp` using the corresponding application and path.
- * Otherwise, fallback to a full page reload to navigate to the url using `window.location.assign`
+ * Otherwise, fallback to a full page reload to navigate to the url using `window.location.assign`.
*
* @example
* ```ts
@@ -802,8 +822,7 @@ export interface ApplicationStart {
*
* @param url - an absolute URL, an absolute path or a relative path, to navigate to.
*/
- navigateToUrl(url: string): Promise;
-
+ navigateToUrl(url: string, options?: NavigateToUrlOptions): Promise;
/**
* Returns the absolute path (or URL) to a given app, including the global base path.
*
diff --git a/src/core/public/chrome/ui/header/collapsible_nav.tsx b/src/core/public/chrome/ui/header/collapsible_nav.tsx
index 498efcfd9076e..54adb34550462 100644
--- a/src/core/public/chrome/ui/header/collapsible_nav.tsx
+++ b/src/core/public/chrome/ui/header/collapsible_nav.tsx
@@ -89,7 +89,7 @@ const overviewIDsToHide = ['kibanaOverview', 'enterpriseSearch'];
const overviewIDs = [
...overviewIDsToHide,
'observability-overview',
- 'securitySolutionUI:overview',
+ 'securitySolutionUI:get_started',
'management',
];
diff --git a/src/core/public/i18n/i18n_eui_mapping.test.ts b/src/core/public/i18n/i18n_eui_mapping.test.ts
index aa78345a86de1..a2d35b37ac569 100644
--- a/src/core/public/i18n/i18n_eui_mapping.test.ts
+++ b/src/core/public/i18n/i18n_eui_mapping.test.ts
@@ -17,6 +17,7 @@ import { getEuiContextMapping } from './i18n_eui_mapping';
const VALUES_REGEXP = /\{\w+\}/;
describe('@elastic/eui i18n tokens', () => {
+ const i18nTranslateActual = jest.requireActual('@kbn/i18n').i18n.translate;
const i18nTranslateMock = jest
.fn()
.mockImplementation((id, { defaultMessage }) => defaultMessage);
@@ -74,34 +75,9 @@ describe('@elastic/eui i18n tokens', () => {
});
test('defaultMessage is in sync with defString', () => {
- // Certain complex tokens (e.g. ones that have a function as a defaultMessage)
- // need custom i18n handling, and can't be checked for basic defString equality
- const tokensToSkip = [
- 'euiColumnSorting.buttonActive',
- 'euiSelectable.searchResults',
- 'euiPrettyDuration.lastDurationSeconds',
- 'euiPrettyDuration.nextDurationSeconds',
- 'euiPrettyDuration.lastDurationMinutes',
- 'euiPrettyDuration.nextDurationMinutes',
- 'euiPrettyDuration.lastDurationHours',
- 'euiPrettyDuration.nextDurationHours',
- 'euiPrettyDuration.lastDurationDays',
- 'euiPrettyDuration.nexttDurationDays',
- 'euiPrettyDuration.lastDurationWeeks',
- 'euiPrettyDuration.nextDurationWeeks',
- 'euiPrettyDuration.lastDurationMonths',
- 'euiPrettyDuration.nextDurationMonths',
- 'euiPrettyDuration.lastDurationYears',
- 'euiPrettyDuration.nextDurationYears',
- 'euiPrettyInterval.seconds',
- 'euiPrettyInterval.minutes',
- 'euiPrettyInterval.hours',
- 'euiPrettyInterval.days',
- 'euiPrettyInterval.weeks',
- 'euiPrettyInterval.months',
- 'euiPrettyInterval.years',
- ];
- if (tokensToSkip.includes(token)) return;
+ const isDefFunction = defString.includes('}) =>');
+ const isPluralizationDefFunction =
+ defString.includes(' === 1 ?') || defString.includes(' > 1 ?');
// Clean up typical errors from the `@elastic/eui` extraction token tool
const normalizedDefString = defString
@@ -114,7 +90,38 @@ describe('@elastic/eui i18n tokens', () => {
.replace(/\s{2,}/g, ' ')
.trim();
- expect(i18nTranslateCall[1].defaultMessage).toBe(normalizedDefString);
+ if (!isDefFunction) {
+ expect(i18nTranslateCall[1].defaultMessage).toBe(normalizedDefString);
+ } else {
+ // Certain EUI defStrings are actually functions (that currently primarily handle
+ // pluralization). To check EUI's pluralization against Kibana's pluralization, we
+ // need to eval the defString and then actually i18n.translate & compare the 2 outputs
+ const defFunction = eval(defString); // eslint-disable-line no-eval
+ const defFunctionArg = normalizedDefString.split('({ ')[1].split('})')[0]; // TODO: All EUI pluralization fns currently only pass 1 arg. If this changes in the future and 2 args are passed, we'll need to do some extra splitting by ','
+
+ if (isPluralizationDefFunction) {
+ const singularValue = { [defFunctionArg]: 1 };
+ expect(
+ i18nTranslateActual(token, {
+ defaultMessage: i18nTranslateCall[1].defaultMessage,
+ values: singularValue,
+ })
+ ).toEqual(defFunction(singularValue));
+
+ const pluralValue = { [defFunctionArg]: 2 };
+ expect(
+ i18nTranslateActual(token, {
+ defaultMessage: i18nTranslateCall[1].defaultMessage,
+ values: pluralValue,
+ })
+ ).toEqual(defFunction(pluralValue));
+ } else {
+ throw new Error(
+ `We currently only have logic written for EUI pluralization def functions.
+ This is a new type of def function that will need custom logic written for it.`
+ );
+ }
+ }
});
test('values should match', () => {
diff --git a/src/core/public/i18n/i18n_eui_mapping.tsx b/src/core/public/i18n/i18n_eui_mapping.tsx
index b58780db3087d..9969f4ee23f57 100644
--- a/src/core/public/i18n/i18n_eui_mapping.tsx
+++ b/src/core/public/i18n/i18n_eui_mapping.tsx
@@ -1268,7 +1268,7 @@ export const getEuiContextMapping = (): EuiTokensObject => {
),
'euiSelectable.searchResults': ({ resultsLength }: EuiValues) =>
i18n.translate('core.euiSelectable.searchResults', {
- defaultMessage: '{resultsLength, plural, one {# result} other {# results}}',
+ defaultMessage: '{resultsLength, plural, one {# result} other {# results}} available',
values: { resultsLength },
}),
'euiSelectable.placeholderName': i18n.translate('core.euiSelectable.placeholderName', {
diff --git a/src/core/public/index.ts b/src/core/public/index.ts
index 3b3bccd7ec18b..d62df68cf827d 100644
--- a/src/core/public/index.ts
+++ b/src/core/public/index.ts
@@ -91,6 +91,7 @@ export type {
PublicAppInfo,
PublicAppDeepLinkInfo,
NavigateToAppOptions,
+ NavigateToUrlOptions,
} from './application';
export { SimpleSavedObject } from './saved_objects';
diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md
index 44224e6fcaea7..b60e26d282dc3 100644
--- a/src/core/public/public.api.md
+++ b/src/core/public/public.api.md
@@ -160,7 +160,7 @@ export interface ApplicationStart {
deepLinkId?: string;
}): string;
navigateToApp(appId: string, options?: NavigateToAppOptions): Promise;
- navigateToUrl(url: string): Promise;
+ navigateToUrl(url: string, options?: NavigateToUrlOptions): Promise;
}
// @public
@@ -778,9 +778,16 @@ export interface NavigateToAppOptions {
openInNewTab?: boolean;
path?: string;
replace?: boolean;
+ skipAppLeave?: boolean;
state?: unknown;
}
+// @public
+export interface NavigateToUrlOptions {
+ forceRedirect?: boolean;
+ skipAppLeave?: boolean;
+}
+
// Warning: (ae-missing-release-tag) "NavType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
diff --git a/src/core/server/saved_objects/mappings/types.ts b/src/core/server/saved_objects/mappings/types.ts
index e225d0ff31022..3fc088d0e82c4 100644
--- a/src/core/server/saved_objects/mappings/types.ts
+++ b/src/core/server/saved_objects/mappings/types.ts
@@ -107,6 +107,11 @@ export type SavedObjectsFieldMapping = estypes.MappingProperty & {
* *never* use `dynamic: true`.
*/
dynamic?: false | 'strict';
+ /**
+ * Some mapping types do not accept the `properties` attributes. Explicitly adding it as optional to our type
+ * to avoid type failures on all code using accessing them via `SavedObjectsFieldMapping.properties`.
+ */
+ properties?: Record;
};
/** @internal */
diff --git a/src/core/server/saved_objects/migrations/integration_tests/cluster_routing_allocation_disabled.test.ts b/src/core/server/saved_objects/migrations/integration_tests/cluster_routing_allocation_disabled.test.ts
index 0f4522b156fe7..ea70478d6ce7b 100644
--- a/src/core/server/saved_objects/migrations/integration_tests/cluster_routing_allocation_disabled.test.ts
+++ b/src/core/server/saved_objects/migrations/integration_tests/cluster_routing_allocation_disabled.test.ts
@@ -113,8 +113,8 @@ describe('unsupported_cluster_routing_allocation', () => {
await root.preboot();
await root.setup();
- await expect(root.start()).rejects.toMatchInlineSnapshot(
- `[Error: Unable to complete saved object migrations for the [.kibana] index: The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue. To proceed, please remove the cluster routing allocation settings with PUT /_cluster/settings {"transient": {"cluster.routing.allocation.enable": null}, "persistent": {"cluster.routing.allocation.enable": null}}]`
+ await expect(root.start()).rejects.toThrowError(
+ /Unable to complete saved object migrations for the \[\.kibana.*\] index: The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue\. To proceed, please remove the cluster routing allocation settings with PUT \/_cluster\/settings {"transient": {"cluster\.routing\.allocation\.enable": null}, "persistent": {"cluster\.routing\.allocation\.enable": null}}/
);
await retryAsync(
@@ -126,8 +126,8 @@ describe('unsupported_cluster_routing_allocation', () => {
.map((str) => JSON5.parse(str)) as LogRecord[];
expect(
records.find((rec) =>
- rec.message.startsWith(
- `Unable to complete saved object migrations for the [.kibana] index: The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue.`
+ /^Unable to complete saved object migrations for the \[\.kibana.*\] index: The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue\./.test(
+ rec.message
)
)
).toBeDefined();
@@ -148,8 +148,8 @@ describe('unsupported_cluster_routing_allocation', () => {
await root.preboot();
await root.setup();
- await expect(root.start()).rejects.toMatchInlineSnapshot(
- `[Error: Unable to complete saved object migrations for the [.kibana] index: The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue. To proceed, please remove the cluster routing allocation settings with PUT /_cluster/settings {"transient": {"cluster.routing.allocation.enable": null}, "persistent": {"cluster.routing.allocation.enable": null}}]`
+ await expect(root.start()).rejects.toThrowError(
+ /Unable to complete saved object migrations for the \[\.kibana.*\] index: The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue\. To proceed, please remove the cluster routing allocation settings with PUT \/_cluster\/settings {"transient": {"cluster\.routing\.allocation\.enable": null}, "persistent": {"cluster\.routing\.allocation\.enable": null}}/
);
});
});
diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md
index c89a5fc89d2fa..7337a3809172e 100644
--- a/src/core/server/server.api.md
+++ b/src/core/server/server.api.md
@@ -2366,6 +2366,7 @@ export interface SavedObjectsExportTransformContext {
// @public
export type SavedObjectsFieldMapping = estypes.MappingProperty & {
dynamic?: false | 'strict';
+ properties?: Record;
};
// @public (undocumented)
diff --git a/src/dev/build/tasks/package_json/find_used_dependencies.ts b/src/dev/build/tasks/package_json/find_used_dependencies.ts
index 6fb0c0060ecc7..e49d57c6f794f 100644
--- a/src/dev/build/tasks/package_json/find_used_dependencies.ts
+++ b/src/dev/build/tasks/package_json/find_used_dependencies.ts
@@ -58,7 +58,7 @@ export async function findUsedDependencies(listedPkgDependencies: any, baseDir:
const listedDependencies = Object.keys(listedPkgDependencies);
const filteredListedDependencies = listedDependencies.filter((entry) => {
- return whiteListedModules.some((nonEntry) => entry.includes(nonEntry));
+ return whiteListedModules.some((nonEntry) => entry === nonEntry);
});
return filteredListedDependencies.reduce((foundUsedDeps: any, usedDep) => {
diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/expression_renderers/partition_vis_renderer.tsx b/src/plugins/chart_expressions/expression_partition_vis/public/expression_renderers/partition_vis_renderer.tsx
index 53e729466c1d2..b0fe277cebfd3 100644
--- a/src/plugins/chart_expressions/expression_partition_vis/public/expression_renderers/partition_vis_renderer.tsx
+++ b/src/plugins/chart_expressions/expression_partition_vis/public/expression_renderers/partition_vis_renderer.tsx
@@ -9,6 +9,7 @@
import React, { lazy } from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { I18nProvider } from '@kbn/i18n-react';
+import { css } from '@emotion/react';
import { i18n } from '@kbn/i18n';
import { ExpressionRenderDefinition } from '../../../../expressions/public';
import type { PersistedState } from '../../../../visualizations/public';
@@ -32,6 +33,12 @@ export const strings = {
const LazyPartitionVisComponent = lazy(() => import('../components/partition_vis_component'));
const PartitionVisComponent = withSuspense(LazyPartitionVisComponent);
+const partitionVisRenderer = css({
+ position: 'relative',
+ width: '100%',
+ height: '100%',
+});
+
export const getPartitionVisRenderer: (
deps: VisTypePieDependencies
) => ExpressionRenderDefinition = ({ theme, palettes, getStartDeps }) => ({
@@ -50,7 +57,7 @@ export const getPartitionVisRenderer: (
render(
-
+
onCancel(flyout),
+ onClose: (flyout) => {
+ onCancel(flyout);
+ setFlyoutRef(undefined);
+ },
}
);
+ setFlyoutRef(flyoutInstance);
});
initialInputPromise.then(
diff --git a/src/plugins/controls/public/control_group/editor/edit_control.tsx b/src/plugins/controls/public/control_group/editor/edit_control.tsx
index 5b7177a64c633..7c114350f3679 100644
--- a/src/plugins/controls/public/control_group/editor/edit_control.tsx
+++ b/src/plugins/controls/public/control_group/editor/edit_control.tsx
@@ -20,7 +20,7 @@ import { IEditableControlFactory, ControlInput } from '../../types';
import { controlGroupReducers } from '../state/control_group_reducers';
import { EmbeddableFactoryNotFoundError } from '../../../../embeddable/public';
import { useReduxContainerContext } from '../../../../presentation_util/public';
-import { ControlGroupContainer } from '../embeddable/control_group_container';
+import { ControlGroupContainer, setFlyoutRef } from '../embeddable/control_group_container';
export const EditControlButton = ({ embeddableId }: { embeddableId: string }) => {
// Controls Services Context
@@ -127,9 +127,13 @@ export const EditControlButton = ({ embeddableId }: { embeddableId: string }) =>
),
{
outsideClickCloses: false,
- onClose: (flyout) => onCancel(flyout),
+ onClose: (flyout) => {
+ setFlyoutRef(undefined);
+ onCancel(flyout);
+ },
}
);
+ setFlyoutRef(flyoutInstance);
};
return (
diff --git a/src/plugins/controls/public/control_group/editor/edit_control_group.tsx b/src/plugins/controls/public/control_group/editor/edit_control_group.tsx
index dcf955666657f..8d9f81637ef65 100644
--- a/src/plugins/controls/public/control_group/editor/edit_control_group.tsx
+++ b/src/plugins/controls/public/control_group/editor/edit_control_group.tsx
@@ -15,6 +15,7 @@ import { ControlGroupEditor } from './control_group_editor';
import { OverlayRef } from '../../../../../core/public';
import { pluginServices } from '../../services';
import { ControlGroupContainer } from '..';
+import { setFlyoutRef } from '../embeddable/control_group_container';
export interface EditControlGroupButtonProps {
controlGroupContainer: ControlGroupContainer;
@@ -60,9 +61,13 @@ export const EditControlGroup = ({
),
{
outsideClickCloses: false,
- onClose: () => flyoutInstance.close(),
+ onClose: () => {
+ flyoutInstance.close();
+ setFlyoutRef(undefined);
+ },
}
);
+ setFlyoutRef(flyoutInstance);
};
const commonButtonProps = {
diff --git a/src/plugins/controls/public/control_group/embeddable/control_group_container.tsx b/src/plugins/controls/public/control_group/embeddable/control_group_container.tsx
index 7abcfbb5af6a3..5ee41946a14aa 100644
--- a/src/plugins/controls/public/control_group/embeddable/control_group_container.tsx
+++ b/src/plugins/controls/public/control_group/embeddable/control_group_container.tsx
@@ -46,11 +46,17 @@ import { Container, EmbeddableFactory } from '../../../../embeddable/public';
import { ControlEmbeddable, ControlInput, ControlOutput } from '../../types';
import { ControlGroupChainingSystems } from './control_group_chaining_system';
import { CreateControlButton, CreateControlButtonTypes } from '../editor/create_control';
+import { OverlayRef } from '../../../../../core/public';
const ControlGroupReduxWrapper = withSuspense<
ReduxEmbeddableWrapperPropsWithChildren
>(LazyReduxEmbeddableWrapper);
+let flyoutRef: OverlayRef | undefined;
+export const setFlyoutRef = (newRef: OverlayRef | undefined) => {
+ flyoutRef = newRef;
+};
+
export interface ChildEmbeddableOrderCache {
IdsToOrder: { [key: string]: number };
idsInOrder: string[];
@@ -96,6 +102,11 @@ export class ControlGroupContainer extends Container<
return this.lastUsedDataViewId ?? this.relevantDataViewId;
};
+ public closeAllFlyouts() {
+ flyoutRef?.close();
+ flyoutRef = undefined;
+ }
+
/**
* Returns a button that allows controls to be created externally using the embeddable
* @param buttonType Controls the button styling
@@ -367,6 +378,7 @@ export class ControlGroupContainer extends Container<
public destroy() {
super.destroy();
+ this.closeAllFlyouts();
this.subscriptions.unsubscribe();
if (this.domNode) ReactDOM.unmountComponentAtNode(this.domNode);
}
diff --git a/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx b/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx
index e66525398b86b..23bc301f788c0 100644
--- a/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx
+++ b/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx
@@ -210,16 +210,17 @@ export function DashboardTopNav({
[stateTransferService, data.search.session, trackUiMetric]
);
- const clearAddPanel = useCallback(() => {
+ const closeAllFlyouts = useCallback(() => {
+ dashboardAppState.dashboardContainer.controlGroup?.closeAllFlyouts();
if (state.addPanelOverlay) {
state.addPanelOverlay.close();
setState((s) => ({ ...s, addPanelOverlay: undefined }));
}
- }, [state.addPanelOverlay]);
+ }, [state.addPanelOverlay, dashboardAppState.dashboardContainer.controlGroup]);
const onChangeViewMode = useCallback(
(newMode: ViewMode) => {
- clearAddPanel();
+ closeAllFlyouts();
const willLoseChanges = newMode === ViewMode.VIEW && dashboardAppState.hasUnsavedChanges;
if (!willLoseChanges) {
@@ -231,7 +232,7 @@ export function DashboardTopNav({
dashboardAppState.resetToLastSavedState?.()
);
},
- [clearAddPanel, core.overlays, dashboardAppState, dispatchDashboardStateChange]
+ [closeAllFlyouts, core.overlays, dashboardAppState, dispatchDashboardStateChange]
);
const runSaveAs = useCallback(async () => {
@@ -296,7 +297,7 @@ export function DashboardTopNav({
showCopyOnSave={lastDashboardId ? true : false}
/>
);
- clearAddPanel();
+ closeAllFlyouts();
showSaveModal(dashboardSaveModal, core.i18n.Context);
}, [
dispatchDashboardStateChange,
@@ -305,7 +306,7 @@ export function DashboardTopNav({
dashboardAppState,
core.i18n.Context,
chrome.docTitle,
- clearAddPanel,
+ closeAllFlyouts,
kibanaVersion,
timefilter,
redirectTo,
@@ -468,7 +469,7 @@ export function DashboardTopNav({
]);
UseUnmount(() => {
- clearAddPanel();
+ closeAllFlyouts();
setMounted(false);
});
diff --git a/src/plugins/data/common/index.ts b/src/plugins/data/common/index.ts
index a97b8025426f2..93aeb918bc53a 100644
--- a/src/plugins/data/common/index.ts
+++ b/src/plugins/data/common/index.ts
@@ -139,7 +139,6 @@ export {
DEFAULT_ASSETS_TO_IGNORE,
META_FIELDS,
DATA_VIEW_SAVED_OBJECT_TYPE,
- INDEX_PATTERN_SAVED_OBJECT_TYPE,
isFilterable,
fieldList,
DataViewField,
diff --git a/src/plugins/data_views/common/constants.ts b/src/plugins/data_views/common/constants.ts
index 42f869908ec25..d6a9def882a1b 100644
--- a/src/plugins/data_views/common/constants.ts
+++ b/src/plugins/data_views/common/constants.ts
@@ -37,10 +37,4 @@ export const META_FIELDS = 'metaFields';
/** @public **/
export const DATA_VIEW_SAVED_OBJECT_TYPE = 'index-pattern';
-/**
- * @deprecated Use DATA_VIEW_SAVED_OBJECT_TYPE. All index pattern interfaces were renamed.
- */
-
-export const INDEX_PATTERN_SAVED_OBJECT_TYPE = DATA_VIEW_SAVED_OBJECT_TYPE;
-
export const PLUGIN_NAME = 'DataViews';
diff --git a/src/plugins/data_views/common/index.ts b/src/plugins/data_views/common/index.ts
index 954d3ed7e3590..13842b62a9d53 100644
--- a/src/plugins/data_views/common/index.ts
+++ b/src/plugins/data_views/common/index.ts
@@ -11,7 +11,6 @@ export {
DEFAULT_ASSETS_TO_IGNORE,
META_FIELDS,
DATA_VIEW_SAVED_OBJECT_TYPE,
- INDEX_PATTERN_SAVED_OBJECT_TYPE,
} from './constants';
export type { IFieldType, IIndexPatternFieldList } from './fields';
export {
diff --git a/src/plugins/discover/public/application/context/components/action_bar/action_bar.tsx b/src/plugins/discover/public/application/context/components/action_bar/action_bar.tsx
index 9b7ba6345111f..07cb6029a77de 100644
--- a/src/plugins/discover/public/application/context/components/action_bar/action_bar.tsx
+++ b/src/plugins/discover/public/application/context/components/action_bar/action_bar.tsx
@@ -92,7 +92,6 @@ export function ActionBar({
{
diff --git a/src/plugins/discover/public/application/view_alert/view_alert_route.tsx b/src/plugins/discover/public/application/view_alert/view_alert_route.tsx
index 82481660d339c..2a6fa70ef0e2b 100644
--- a/src/plugins/discover/public/application/view_alert/view_alert_route.tsx
+++ b/src/plugins/discover/public/application/view_alert/view_alert_route.tsx
@@ -9,7 +9,7 @@
import { useEffect, useMemo } from 'react';
import { useHistory, useLocation, useParams } from 'react-router-dom';
import { sha256 } from 'js-sha256';
-import type { Alert } from '../../../../../../x-pack/plugins/alerting/common';
+import type { Rule } from '../../../../../../x-pack/plugins/alerting/common';
import { getTime, IndexPattern } from '../../../../data/common';
import type { Filter } from '../../../../data/public';
import { DiscoverAppLocatorParams } from '../../locator';
@@ -27,7 +27,7 @@ const isActualAlert = (queryParams: QueryParams): queryParams is NonNullableEntr
const buildTimeRangeFilter = (
dataView: IndexPattern,
- fetchedAlert: Alert,
+ fetchedAlert: Rule,
timeFieldName: string
) => {
const filter = getTime(dataView, {
diff --git a/src/plugins/discover/public/application/view_alert/view_alert_utils.tsx b/src/plugins/discover/public/application/view_alert/view_alert_utils.tsx
index b61f0c9a8720c..585da8c676417 100644
--- a/src/plugins/discover/public/application/view_alert/view_alert_utils.tsx
+++ b/src/plugins/discover/public/application/view_alert/view_alert_utils.tsx
@@ -9,13 +9,13 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { CoreStart, ToastsStart } from 'kibana/public';
-import type { Alert } from '../../../../../../x-pack/plugins/alerting/common';
-import type { AlertTypeParams } from '../../../../../../x-pack/plugins/alerting/common';
+import type { Rule } from '../../../../../../x-pack/plugins/alerting/common';
+import type { RuleTypeParams } from '../../../../../../x-pack/plugins/alerting/common';
import { SerializedSearchSourceFields } from '../../../../data/common';
import type { DataPublicPluginStart } from '../../../../data/public';
import { MarkdownSimple, toMountPoint } from '../../../../kibana_react/public';
-export interface SearchThresholdAlertParams extends AlertTypeParams {
+export interface SearchThresholdAlertParams extends RuleTypeParams {
searchConfiguration: SerializedSearchSourceFields;
}
@@ -78,7 +78,7 @@ export const getAlertUtils = (
const fetchAlert = async (id: string) => {
try {
- return await core.http.get>(
+ return await core.http.get>(
`${LEGACY_BASE_ALERT_API_PATH}/alert/${id}`
);
} catch (error) {
@@ -92,7 +92,7 @@ export const getAlertUtils = (
}
};
- const fetchSearchSource = async (fetchedAlert: Alert) => {
+ const fetchSearchSource = async (fetchedAlert: Rule) => {
try {
return await data.search.searchSource.create(fetchedAlert.params.searchConfiguration);
} catch (error) {
diff --git a/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/get_data_telemetry.ts b/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/get_data_telemetry.ts
index 3f98ead25ff4e..174e200a6c996 100644
--- a/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/get_data_telemetry.ts
+++ b/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/get_data_telemetry.ts
@@ -228,6 +228,7 @@ export async function getDataTelemetry(esClient: ElasticsearchClient) {
const indices = indexNames.map((name) => {
const baseIndexInfo = {
name,
+ // @ts-expect-error 'properties' does not exist on type 'MappingMatchOnlyTextProperty'
isECS: !!indexMappings[name]?.mappings?.properties?.ecs?.properties?.version?.type,
shipper: indexMappings[name]?.mappings?._meta?.beat,
packageName: indexMappings[name]?.mappings?._meta?.package?.name,
diff --git a/src/plugins/vis_types/vega/public/vega_view/vega_map_view/view.test.ts b/src/plugins/vis_types/vega/public/vega_view/vega_map_view/view.test.ts
index a09e92fe7dd80..c0453f470de4b 100644
--- a/src/plugins/vis_types/vega/public/vega_view/vega_map_view/view.test.ts
+++ b/src/plugins/vis_types/vega/public/vega_view/vega_map_view/view.test.ts
@@ -31,30 +31,43 @@ import { initVegaLayer, initTmsRasterLayer } from './layers';
import { mapboxgl } from '@kbn/mapbox-gl';
-jest.mock('@kbn/mapbox-gl', () => ({
- mapboxgl: {
- setRTLTextPlugin: jest.fn(),
- Map: jest.fn().mockImplementation(() => ({
- getLayer: () => '',
- removeLayer: jest.fn(),
- once: (eventName: string, handler: Function) => handler(),
- remove: () => jest.fn(),
- getCanvas: () => ({ clientWidth: 512, clientHeight: 512 }),
- getCenter: () => ({ lat: 20, lng: 20 }),
- getZoom: () => 3,
- addControl: jest.fn(),
- addLayer: jest.fn(),
- dragRotate: {
- disable: jest.fn(),
+jest.mock('@kbn/mapbox-gl', () => {
+ const zoomTo = jest.fn();
+ const setCenter = jest.fn();
+ const fitBounds = jest.fn();
+ return {
+ mapboxgl: {
+ mocks: {
+ zoomTo,
+ setCenter,
+ fitBounds,
},
- touchZoomRotate: {
- disableRotation: jest.fn(),
- },
- })),
- MapboxOptions: jest.fn(),
- NavigationControl: jest.fn(),
- },
-}));
+ setRTLTextPlugin: jest.fn(),
+ Map: jest.fn().mockImplementation(() => ({
+ getLayer: () => '',
+ removeLayer: jest.fn(),
+ once: (eventName: string, handler: Function) => handler(),
+ remove: () => jest.fn(),
+ getCanvas: () => ({ clientWidth: 512, clientHeight: 512 }),
+ getCenter: () => ({ lat: 20, lng: 20 }),
+ getZoom: () => 3,
+ zoomTo,
+ setCenter,
+ fitBounds,
+ addControl: jest.fn(),
+ addLayer: jest.fn(),
+ dragRotate: {
+ disable: jest.fn(),
+ },
+ touchZoomRotate: {
+ disableRotation: jest.fn(),
+ },
+ })),
+ MapboxOptions: jest.fn(),
+ NavigationControl: jest.fn(),
+ },
+ };
+});
jest.mock('./layers', () => ({
initVegaLayer: jest.fn(),
@@ -206,5 +219,57 @@ describe('vega_map_view/view', () => {
expect(mapboxgl.NavigationControl).toHaveBeenCalled();
});
+
+ describe('setMapView', () => {
+ let vegaMapView: VegaMapView;
+ beforeEach(async () => {
+ vegaMapView = await createVegaMapView();
+ await vegaMapView.init();
+ mapboxgl.mocks.setCenter.mockReset();
+ mapboxgl.mocks.zoomTo.mockReset();
+ mapboxgl.mocks.fitBounds.mockReset();
+ });
+
+ test('should set just lat lng', async () => {
+ vegaMapView.setMapViewHandler(1, 2);
+ expect(mapboxgl.mocks.setCenter).toHaveBeenCalledWith({ lat: 1, lng: 2 });
+ });
+
+ test('should set just lng lat via array', async () => {
+ vegaMapView.setMapViewHandler([1, 2]);
+ expect(mapboxgl.mocks.setCenter).toHaveBeenCalledWith({ lat: 2, lng: 1 });
+ });
+
+ test('should set lat lng and zoom', async () => {
+ vegaMapView.setMapViewHandler(1, 2, 6);
+ expect(mapboxgl.mocks.setCenter).toHaveBeenCalledWith({ lat: 1, lng: 2 });
+ expect(mapboxgl.mocks.zoomTo).toHaveBeenCalledWith(6);
+ });
+
+ test('should set bounds', async () => {
+ vegaMapView.setMapViewHandler([
+ [1, 2],
+ [6, 7],
+ ]);
+ expect(mapboxgl.mocks.fitBounds).toHaveBeenCalledWith([
+ { lat: 2, lng: 1 },
+ { lat: 7, lng: 6 },
+ ]);
+ });
+
+ test('should throw on invalid input', async () => {
+ expect(() => {
+ vegaMapView.setMapViewHandler(undefined);
+ }).toThrow();
+
+ expect(() => {
+ vegaMapView.setMapViewHandler(['a', 'b'] as unknown as [number, number]);
+ }).toThrow();
+
+ expect(() => {
+ vegaMapView.setMapViewHandler([1, 2, 3, 4, 5] as unknown as [number, number]);
+ }).toThrow();
+ });
+ });
});
});
diff --git a/src/plugins/vis_types/vega/public/vega_view/vega_map_view/view.ts b/src/plugins/vis_types/vega/public/vega_view/vega_map_view/view.ts
index fe8d85a011442..2050e0271d03f 100644
--- a/src/plugins/vis_types/vega/public/vega_view/vega_map_view/view.ts
+++ b/src/plugins/vis_types/vega/public/vega_view/vega_map_view/view.ts
@@ -9,7 +9,7 @@
import { i18n } from '@kbn/i18n';
import type { Map, Style, MapboxOptions } from '@kbn/mapbox-gl';
-import { View, parse } from 'vega';
+import { View, parse, expressionFunction } from 'vega';
import { mapboxgl } from '@kbn/mapbox-gl';
@@ -45,6 +45,30 @@ async function updateVegaView(mapBoxInstance: Map, vegaView: View) {
}
}
+type SetMapViewArgs =
+ | [number, number, number]
+ | [number, number]
+ | [[number, number], number]
+ | [[number, number]]
+ | [[[number, number], [number, number]]];
+
+expressionFunction(
+ 'setMapView',
+ function handlerFwd(
+ this: {
+ context: { dataflow: { _kibanaView: VegaMapView; runAfter: (fn: () => void) => void } };
+ },
+ ...args: SetMapViewArgs
+ ) {
+ const view = this.context.dataflow;
+ if (!('setMapViewHandler' in view._kibanaView)) {
+ // not a map view, don't do anything
+ return;
+ }
+ view.runAfter(() => view._kibanaView.setMapViewHandler(...args));
+ }
+);
+
export class VegaMapView extends VegaBaseView {
private mapBoxInstance?: Map;
@@ -200,4 +224,86 @@ export class VegaMapView extends VegaBaseView {
protected async onViewContainerResize() {
this.mapBoxInstance?.resize();
}
+
+ public setMapViewHandler(...args: SetMapViewArgs) {
+ if (!this.mapBoxInstance) {
+ return;
+ }
+ function throwError() {
+ throw new Error(
+ i18n.translate('visTypeVega.visualization.setMapViewErrorMessage', {
+ defaultMessage:
+ 'Unexpected setMapView() parameters. It could be called with a bounding box setMapView([[longitude1,latitude1],[longitude2,latitude2]]), or it could be the center point setMapView([longitude, latitude], optional_zoom), or it can be used as setMapView(latitude, longitude, optional_zoom)',
+ })
+ );
+ }
+
+ function checkArray(
+ val: number | [number, number] | [[number, number], [number, number]]
+ ): [number, number] {
+ if (
+ !Array.isArray(val) ||
+ val.length !== 2 ||
+ typeof val[0] !== 'number' ||
+ typeof val[1] !== 'number'
+ ) {
+ throwError();
+ }
+ return val as [number, number];
+ }
+
+ let lng: number | undefined;
+ let lat: number | undefined;
+ let zoom: number | undefined;
+ switch (args.length) {
+ default:
+ throwError();
+ break;
+ case 1: {
+ const arg = args[0];
+ if (
+ Array.isArray(arg) &&
+ arg.length === 2 &&
+ Array.isArray(arg[0]) &&
+ Array.isArray(arg[1])
+ ) {
+ // called with a bounding box, need to reverse order
+ const [lng1, lat1] = checkArray(arg[0]);
+ const [lng2, lat2] = checkArray(arg[1]);
+ this.mapBoxInstance.fitBounds([
+ { lat: lat1, lng: lng1 },
+ { lat: lat2, lng: lng2 },
+ ]);
+ } else {
+ // called with a center point and no zoom
+ [lng, lat] = checkArray(arg);
+ }
+ break;
+ }
+ case 2:
+ if (Array.isArray(args[0])) {
+ [lng, lat] = checkArray(args[0]);
+ zoom = args[1];
+ } else {
+ [lat, lng] = args;
+ }
+ break;
+ case 3:
+ [lat, lng, zoom] = args;
+ break;
+ }
+
+ if (lat !== undefined && lng !== undefined) {
+ if (typeof lat !== 'number' || typeof lng !== 'number') {
+ throwError();
+ }
+ if (zoom !== undefined && typeof zoom !== 'number') {
+ throwError();
+ }
+ this.mapBoxInstance.setCenter({ lat, lng });
+ if (zoom !== undefined) {
+ this.mapBoxInstance.zoomTo(zoom);
+ }
+ }
+ }
}
diff --git a/test/functional/apps/dashboard_elements/controls/control_group_settings.ts b/test/functional/apps/dashboard_elements/controls/control_group_settings.ts
index ffda165443337..3ca09bba99cea 100644
--- a/test/functional/apps/dashboard_elements/controls/control_group_settings.ts
+++ b/test/functional/apps/dashboard_elements/controls/control_group_settings.ts
@@ -99,5 +99,33 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await dashboardControls.deleteAllControls();
});
});
+
+ describe('control group settings flyout closes', async () => {
+ it('on save', async () => {
+ await dashboardControls.openControlGroupSettingsFlyout();
+ await dashboard.saveDashboard('Test Control Group Settings', {
+ saveAsNew: false,
+ exitFromEditMode: false,
+ });
+ await testSubjects.missingOrFail('control-group-settings-flyout');
+ });
+
+ it('on view mode change', async () => {
+ await dashboardControls.openControlGroupSettingsFlyout();
+ await dashboard.clickCancelOutOfEditMode();
+ await testSubjects.missingOrFail('control-group-settings-flyout');
+ });
+
+ it('when navigating away from dashboard', async () => {
+ await dashboard.switchToEditMode();
+ await dashboardControls.openControlGroupSettingsFlyout();
+ await dashboard.gotoDashboardLandingPage();
+ await testSubjects.missingOrFail('control-group-settings-flyout');
+ });
+
+ after(async () => {
+ await dashboard.loadSavedDashboard('Test Control Group Settings');
+ });
+ });
});
}
diff --git a/test/package/roles/assert_kibana_available/tasks/main.yml b/test/package/roles/assert_kibana_available/tasks/main.yml
index db3805f7ad7fb..29b82aa7b39f8 100644
--- a/test/package/roles/assert_kibana_available/tasks/main.yml
+++ b/test/package/roles/assert_kibana_available/tasks/main.yml
@@ -4,6 +4,6 @@
status_code: [200, 401]
timeout: 120
register: result
- until: result.status != 503
+ until: result.status not in [503, -1]
retries: 3
delay: 30
diff --git a/versions.json b/versions.json
new file mode 100644
index 0000000000000..6dfe620c9fd7e
--- /dev/null
+++ b/versions.json
@@ -0,0 +1,27 @@
+{
+ "notice": "This file is not maintained outside of the main branch and should only be used for tooling.",
+ "versions": [
+ {
+ "version": "8.3.0",
+ "branch": "main",
+ "currentMajor": true,
+ "currentMinor": true
+ },
+ {
+ "version": "8.2.0",
+ "branch": "8.2",
+ "currentMajor": true,
+ "previousMinor": true
+ },
+ {
+ "version": "8.1.3",
+ "branch": "8.1",
+ "currentMajor": true
+ },
+ {
+ "version": "7.17.3",
+ "branch": "7.17",
+ "previousMajor": true
+ }
+ ]
+}
diff --git a/x-pack/examples/alerting_example/README.md b/x-pack/examples/alerting_example/README.md
index bf963c64586d3..f9e2f6009b12f 100644
--- a/x-pack/examples/alerting_example/README.md
+++ b/x-pack/examples/alerting_example/README.md
@@ -1,5 +1,5 @@
## Alerting Example
-This example plugin shows you how to create a custom Alert Type, create alerts based on that type and corresponding UI for viewing the details of all the alerts within the custom plugin.
+This example plugin shows you how to create a custom Rule Type, create rules based on that type and corresponding UI for viewing the details of all the rules within the custom plugin.
To run this example, use the command `yarn start --run-examples`.
\ No newline at end of file
diff --git a/x-pack/examples/alerting_example/common/constants.ts b/x-pack/examples/alerting_example/common/constants.ts
index 14342e3381531..83cb074328f42 100644
--- a/x-pack/examples/alerting_example/common/constants.ts
+++ b/x-pack/examples/alerting_example/common/constants.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { AlertTypeParams } from '../../../plugins/alerting/common';
+import { RuleTypeParams } from '../../../plugins/alerting/common';
export const ALERTING_EXAMPLE_APP_ID = 'AlertingExample';
@@ -16,7 +16,7 @@ export interface AlwaysFiringThresholds {
medium?: number;
large?: number;
}
-export interface AlwaysFiringParams extends AlertTypeParams {
+export interface AlwaysFiringParams extends RuleTypeParams {
instances?: number;
thresholds?: AlwaysFiringThresholds;
}
diff --git a/x-pack/examples/alerting_example/public/alert_types/astros.tsx b/x-pack/examples/alerting_example/public/alert_types/astros.tsx
index 63ffa48c94399..d7fe322a083b1 100644
--- a/x-pack/examples/alerting_example/public/alert_types/astros.tsx
+++ b/x-pack/examples/alerting_example/public/alert_types/astros.tsx
@@ -20,7 +20,7 @@ import {
import { i18n } from '@kbn/i18n';
import { flatten } from 'lodash';
import { ALERTING_EXAMPLE_APP_ID, Craft, Operator } from '../../common/constants';
-import { SanitizedAlert } from '../../../../plugins/alerting/common';
+import { SanitizedRule } from '../../../../plugins/alerting/common';
import { PluginSetupContract as AlertingSetup } from '../../../../plugins/alerting/public';
import { RuleTypeModel } from '../../../../plugins/triggers_actions_ui/public';
@@ -28,7 +28,7 @@ export function registerNavigation(alerting: AlertingSetup) {
alerting.registerNavigation(
ALERTING_EXAMPLE_APP_ID,
'example.people-in-space',
- (alert: SanitizedAlert) => `/astros/${alert.id}`
+ (rule: SanitizedRule) => `/astros/${rule.id}`
);
}
@@ -49,8 +49,8 @@ export function getAlertType(): RuleTypeModel {
iconClass: 'globe',
documentationUrl: null,
ruleParamsExpression: PeopleinSpaceExpression,
- validate: (alertParams: PeopleinSpaceParamsProps['ruleParams']) => {
- const { outerSpaceCapacity, craft, op } = alertParams;
+ validate: (ruleParams: PeopleinSpaceParamsProps['ruleParams']) => {
+ const { outerSpaceCapacity, craft, op } = ruleParams;
const validationResult = {
errors: {
diff --git a/x-pack/examples/alerting_example/public/alert_types/index.ts b/x-pack/examples/alerting_example/public/alert_types/index.ts
index 93c59c55bf3ce..5b62fe138c018 100644
--- a/x-pack/examples/alerting_example/public/alert_types/index.ts
+++ b/x-pack/examples/alerting_example/public/alert_types/index.ts
@@ -7,14 +7,14 @@
import { registerNavigation as registerPeopleInSpaceNavigation } from './astros';
import { ALERTING_EXAMPLE_APP_ID } from '../../common/constants';
-import { SanitizedAlert } from '../../../../plugins/alerting/common';
+import { SanitizedRule } from '../../../../plugins/alerting/common';
import { PluginSetupContract as AlertingSetup } from '../../../../plugins/alerting/public';
export function registerNavigation(alerting: AlertingSetup) {
// register default navigation
alerting.registerDefaultNavigation(
ALERTING_EXAMPLE_APP_ID,
- (alert: SanitizedAlert) => `/rule/${alert.id}`
+ (rule: SanitizedRule) => `/rule/${rule.id}`
);
registerPeopleInSpaceNavigation(alerting);
diff --git a/x-pack/plugins/alerting/README.md b/x-pack/plugins/alerting/README.md
index 6dde7de84aab4..c77e600df5f0e 100644
--- a/x-pack/plugins/alerting/README.md
+++ b/x-pack/plugins/alerting/README.md
@@ -224,28 +224,28 @@ This example rule type receives server and threshold as parameters. It will read
```typescript
import { schema } from '@kbn/config-schema';
-import { RuleType, AlertExecutorOptions } from '../../../alerting/server';
+import { RuleType, RuleExecutorOptions } from '../../../alerting/server';
// These type names will eventually be updated to reflect the new terminology
import {
- AlertTypeParams,
- AlertTypeState,
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
} from '../../../alerting/common';
...
-interface MyRuleTypeParams extends AlertTypeParams {
+interface MyRuleTypeParams extends RuleTypeParams {
server: string;
threshold: number;
testSavedObjectId: string;
}
-interface MyRuleTypeExtractedParams extends AlertTypeParams {
+interface MyRuleTypeExtractedParams extends RuleTypeParams {
server: string;
threshold: number;
testSavedObjectRef: string;
}
-interface MyRuleTypeState extends AlertTypeState {
+interface MyRuleTypeState extends RuleTypeState {
lastChecked: Date;
}
@@ -306,7 +306,7 @@ const myRuleType: RuleType<
params,
state,
rule,
- }: AlertExecutorOptions<
+ }: RuleExecutorOptions<
MyRuleTypeParams,
MyRuleTypeExtractedParams,
MyRuleTypeState,
@@ -677,8 +677,8 @@ The signature of such a handler is:
```typescript
type AlertNavigationHandler = (
- alert: SanitizedAlert,
- alertType: RuleType
+ rule: SanitizedRule,
+ ruleType: RuleType
) => string;
```
@@ -692,7 +692,7 @@ The _registerNavigation_ api allows you to register a handler for a specific ale
alerting.registerNavigation(
'my-application-id',
'my-application-id.my-rule-type',
- (alert: SanitizedAlert) => `/my-unique-rule/${rule.id}`
+ (rule: SanitizedRule) => `/my-unique-rule/${rule.id}`
);
```
@@ -708,7 +708,7 @@ The _registerDefaultNavigation_ API allows you to register a handler for any rul
```
alerting.registerDefaultNavigation(
'my-application-id',
- (alert: SanitizedAlert) => `/my-other-rules/${rule.id}`
+ (rule: SanitizedRule) => `/my-other-rules/${rule.id}`
);
```
diff --git a/x-pack/plugins/alerting/common/execution_log_types.ts b/x-pack/plugins/alerting/common/execution_log_types.ts
index e5047aae9f154..df74c46ad9b43 100644
--- a/x-pack/plugins/alerting/common/execution_log_types.ts
+++ b/x-pack/plugins/alerting/common/execution_log_types.ts
@@ -36,7 +36,21 @@ export interface IExecutionLog {
timed_out: boolean;
}
+export interface IExecutionErrors {
+ id: string;
+ timestamp: string;
+ type: string;
+ message: string;
+}
+
+export interface IExecutionErrorsResult {
+ totalErrors: number;
+ errors: IExecutionErrors[];
+}
+
export interface IExecutionLogResult {
total: number;
data: IExecutionLog[];
}
+
+export type IExecutionLogWithErrorsResult = IExecutionLogResult & IExecutionErrorsResult;
diff --git a/x-pack/plugins/alerting/common/index.ts b/x-pack/plugins/alerting/common/index.ts
index 732d9061e58da..f056ad7e0e4b7 100644
--- a/x-pack/plugins/alerting/common/index.ts
+++ b/x-pack/plugins/alerting/common/index.ts
@@ -8,17 +8,17 @@
// TODO: https://github.com/elastic/kibana/issues/110895
/* eslint-disable @kbn/eslint/no_export_all */
-import { AlertsHealth } from './alert';
+import { AlertsHealth } from './rule';
-export * from './alert';
+export * from './rule';
export * from './rule_type';
-export * from './alert_instance';
export * from './rule_task_instance';
-export * from './alert_navigation';
+export * from './rule_navigation';
+export * from './alert_instance';
export * from './alert_summary';
export * from './builtin_action_groups';
export * from './disabled_action_groups';
-export * from './alert_notify_when_type';
+export * from './rule_notify_when_type';
export * from './parse_duration';
export * from './execution_log_types';
diff --git a/x-pack/plugins/alerting/common/alert.ts b/x-pack/plugins/alerting/common/rule.ts
similarity index 72%
rename from x-pack/plugins/alerting/common/alert.ts
rename to x-pack/plugins/alerting/common/rule.ts
index 9e48acd523d22..d6904c7164600 100644
--- a/x-pack/plugins/alerting/common/alert.ts
+++ b/x-pack/plugins/alerting/common/rule.ts
@@ -11,10 +11,10 @@ import {
SavedObjectsResolveResponse,
} from 'kibana/server';
import { RuleExecutionMetrics } from '.';
-import { AlertNotifyWhenType } from './alert_notify_when_type';
+import { RuleNotifyWhenType } from './rule_notify_when_type';
-export type AlertTypeState = Record;
-export type AlertTypeParams = Record;
+export type RuleTypeState = Record;
+export type RuleTypeParams = Record;
export interface IntervalSchedule extends SavedObjectAttributes {
interval: string;
@@ -22,7 +22,7 @@ export interface IntervalSchedule extends SavedObjectAttributes {
// for the `typeof ThingValues[number]` types below, become string types that
// only accept the values in the associated string arrays
-export const AlertExecutionStatusValues = [
+export const RuleExecutionStatusValues = [
'ok',
'active',
'error',
@@ -30,9 +30,9 @@ export const AlertExecutionStatusValues = [
'unknown',
'warning',
] as const;
-export type AlertExecutionStatuses = typeof AlertExecutionStatusValues[number];
+export type RuleExecutionStatuses = typeof RuleExecutionStatusValues[number];
-export enum AlertExecutionStatusErrorReasons {
+export enum RuleExecutionStatusErrorReasons {
Read = 'read',
Decrypt = 'decrypt',
Execute = 'execute',
@@ -42,38 +42,38 @@ export enum AlertExecutionStatusErrorReasons {
Disabled = 'disabled',
}
-export enum AlertExecutionStatusWarningReasons {
+export enum RuleExecutionStatusWarningReasons {
MAX_EXECUTABLE_ACTIONS = 'maxExecutableActions',
}
-export interface AlertExecutionStatus {
- status: AlertExecutionStatuses;
+export interface RuleExecutionStatus {
+ status: RuleExecutionStatuses;
numberOfTriggeredActions?: number;
numberOfScheduledActions?: number;
metrics?: RuleExecutionMetrics;
lastExecutionDate: Date;
lastDuration?: number;
error?: {
- reason: AlertExecutionStatusErrorReasons;
+ reason: RuleExecutionStatusErrorReasons;
message: string;
};
warning?: {
- reason: AlertExecutionStatusWarningReasons;
+ reason: RuleExecutionStatusWarningReasons;
message: string;
};
}
-export type AlertActionParams = SavedObjectAttributes;
-export type AlertActionParam = SavedObjectAttribute;
+export type RuleActionParams = SavedObjectAttributes;
+export type RuleActionParam = SavedObjectAttribute;
-export interface AlertAction {
+export interface RuleAction {
group: string;
id: string;
actionTypeId: string;
- params: AlertActionParams;
+ params: RuleActionParams;
}
-export interface AlertAggregations {
+export interface RuleAggregations {
alertExecutionStatus: { [status: string]: number };
ruleEnabledStatus: { enabled: number; disabled: number };
ruleMutedStatus: { muted: number; unmuted: number };
@@ -87,15 +87,15 @@ export interface MappedParamsProperties {
export type MappedParams = SavedObjectAttributes & MappedParamsProperties;
-export interface Alert {
+export interface Rule {
id: string;
enabled: boolean;
name: string;
tags: string[];
- alertTypeId: string;
+ alertTypeId: string; // this is persisted in the Rule saved object so we would need a migration to change this to ruleTypeId
consumer: string;
schedule: IntervalSchedule;
- actions: AlertAction[];
+ actions: RuleAction[];
params: Params;
mapped_params?: MappedParams;
scheduledTaskId?: string;
@@ -106,20 +106,20 @@ export interface Alert {
apiKey: string | null;
apiKeyOwner: string | null;
throttle: string | null;
- notifyWhen: AlertNotifyWhenType | null;
+ notifyWhen: RuleNotifyWhenType | null;
muteAll: boolean;
mutedInstanceIds: string[];
- executionStatus: AlertExecutionStatus;
+ executionStatus: RuleExecutionStatus;
monitoring?: RuleMonitoring;
snoozeEndTime?: Date | null; // Remove ? when this parameter is made available in the public API
}
-export type SanitizedAlert = Omit, 'apiKey'>;
-export type ResolvedSanitizedRule = SanitizedAlert &
+export type SanitizedRule = Omit, 'apiKey'>;
+export type ResolvedSanitizedRule = SanitizedRule &
Omit;
export type SanitizedRuleConfig = Pick<
- SanitizedAlert,
+ SanitizedRule,
| 'name'
| 'tags'
| 'consumer'
diff --git a/x-pack/plugins/alerting/common/alert_navigation.ts b/x-pack/plugins/alerting/common/rule_navigation.ts
similarity index 69%
rename from x-pack/plugins/alerting/common/alert_navigation.ts
rename to x-pack/plugins/alerting/common/rule_navigation.ts
index 6ac21232b51a5..abc109a31c432 100644
--- a/x-pack/plugins/alerting/common/alert_navigation.ts
+++ b/x-pack/plugins/alerting/common/rule_navigation.ts
@@ -6,10 +6,10 @@
*/
import { JsonObject } from '@kbn/utility-types';
-export interface AlertUrlNavigation {
+export interface RuleUrlNavigation {
path: string;
}
-export interface AlertStateNavigation {
+export interface RuleStateNavigation {
state: JsonObject;
}
-export type AlertNavigation = AlertUrlNavigation | AlertStateNavigation;
+export type RuleNavigation = RuleUrlNavigation | RuleStateNavigation;
diff --git a/x-pack/plugins/alerting/common/alert_notify_when_type.test.ts b/x-pack/plugins/alerting/common/rule_notify_when_type.test.ts
similarity index 83%
rename from x-pack/plugins/alerting/common/alert_notify_when_type.test.ts
rename to x-pack/plugins/alerting/common/rule_notify_when_type.test.ts
index 3bfaf0ea7cc7e..dca2296aaa7e5 100644
--- a/x-pack/plugins/alerting/common/alert_notify_when_type.test.ts
+++ b/x-pack/plugins/alerting/common/rule_notify_when_type.test.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { validateNotifyWhenType } from './alert_notify_when_type';
+import { validateNotifyWhenType } from './rule_notify_when_type';
test('validates valid notify when type', () => {
expect(validateNotifyWhenType('onActionGroupChange')).toBeUndefined();
@@ -14,6 +14,6 @@ test('validates valid notify when type', () => {
});
test('returns error string if input is not valid notify when type', () => {
expect(validateNotifyWhenType('randomString')).toEqual(
- `string is not a valid AlertNotifyWhenType: randomString`
+ `string is not a valid RuleNotifyWhenType: randomString`
);
});
diff --git a/x-pack/plugins/alerting/common/alert_notify_when_type.ts b/x-pack/plugins/alerting/common/rule_notify_when_type.ts
similarity index 61%
rename from x-pack/plugins/alerting/common/alert_notify_when_type.ts
rename to x-pack/plugins/alerting/common/rule_notify_when_type.ts
index fe7ca715e2bfb..700c87acdbdbb 100644
--- a/x-pack/plugins/alerting/common/alert_notify_when_type.ts
+++ b/x-pack/plugins/alerting/common/rule_notify_when_type.ts
@@ -5,16 +5,16 @@
* 2.0.
*/
-const AlertNotifyWhenTypeValues = [
+const RuleNotifyWhenTypeValues = [
'onActionGroupChange',
'onActiveAlert',
'onThrottleInterval',
] as const;
-export type AlertNotifyWhenType = typeof AlertNotifyWhenTypeValues[number];
+export type RuleNotifyWhenType = typeof RuleNotifyWhenTypeValues[number];
export function validateNotifyWhenType(notifyWhen: string) {
- if (AlertNotifyWhenTypeValues.includes(notifyWhen as AlertNotifyWhenType)) {
+ if (RuleNotifyWhenTypeValues.includes(notifyWhen as RuleNotifyWhenType)) {
return;
}
- return `string is not a valid AlertNotifyWhenType: ${notifyWhen}`;
+ return `string is not a valid RuleNotifyWhenType: ${notifyWhen}`;
}
diff --git a/x-pack/plugins/alerting/common/rule_task_instance.ts b/x-pack/plugins/alerting/common/rule_task_instance.ts
index 54483babdfdd3..01d97efd57b15 100644
--- a/x-pack/plugins/alerting/common/rule_task_instance.ts
+++ b/x-pack/plugins/alerting/common/rule_task_instance.ts
@@ -8,7 +8,7 @@
import * as t from 'io-ts';
import { rawAlertInstance } from './alert_instance';
import { DateFromString } from './date_from_string';
-import { IntervalSchedule, RuleMonitoring } from './alert';
+import { IntervalSchedule, RuleMonitoring } from './rule';
export const ruleStateSchema = t.partial({
alertTypeState: t.record(t.string, t.unknown),
diff --git a/x-pack/plugins/alerting/public/alert_api.test.ts b/x-pack/plugins/alerting/public/alert_api.test.ts
index 8e6331a29c1c5..eae4bc72a02e8 100644
--- a/x-pack/plugins/alerting/public/alert_api.test.ts
+++ b/x-pack/plugins/alerting/public/alert_api.test.ts
@@ -5,19 +5,19 @@
* 2.0.
*/
-import { Alert, RuleType } from '../common';
+import { Rule, RuleType } from '../common';
import { httpServiceMock } from '../../../../src/core/public/mocks';
-import { loadAlert, loadAlertType, loadAlertTypes } from './alert_api';
+import { loadRule, loadRuleType, loadRuleTypes } from './alert_api';
const http = httpServiceMock.createStartContract();
beforeEach(() => jest.resetAllMocks());
-describe('loadAlertTypes', () => {
- test('should call get alert types API', async () => {
+describe('loadRuleTypes', () => {
+ test('should call get rule types API', async () => {
http.get.mockResolvedValueOnce([getApiRuleType()]);
- const result = await loadAlertTypes({ http });
+ const result = await loadRuleTypes({ http });
expect(result).toMatchInlineSnapshot(`
Array [
Object {
@@ -77,22 +77,22 @@ describe('loadAlertTypes', () => {
});
});
-describe('loadAlertType', () => {
- test('should call get alert types API', async () => {
+describe('loadRuleType', () => {
+ test('should call get rule types API', async () => {
const ruleType = getApiRuleType();
http.get.mockResolvedValueOnce([ruleType]);
- const result = await loadAlertType({ http, id: ruleType.id });
+ const result = await loadRuleType({ http, id: ruleType.id });
expect(result).toEqual(getRuleType());
});
});
-describe('loadAlert', () => {
+describe('loadRule', () => {
test('should call get API with base parameters', async () => {
const apiRule = getApiRule();
http.get.mockResolvedValueOnce(apiRule);
- const res = await loadAlert({ http, alertId: apiRule.id });
+ const res = await loadRule({ http, ruleId: apiRule.id });
expect(res).toEqual(getRule());
const fixedDate = new Date('2021-12-11T16:59:50.152Z');
@@ -292,7 +292,7 @@ function getApiRule() {
};
}
-function getRule(): Alert<{ x: number }> {
+function getRule(): Rule<{ x: number }> {
return {
id: '3d534c70-582b-11ec-8995-2b1578a3bc5d',
notifyWhen: 'onActiveAlert',
diff --git a/x-pack/plugins/alerting/public/alert_api.ts b/x-pack/plugins/alerting/public/alert_api.ts
index e64a236d5302b..93ea8c79bdd34 100644
--- a/x-pack/plugins/alerting/public/alert_api.ts
+++ b/x-pack/plugins/alerting/public/alert_api.ts
@@ -7,35 +7,35 @@
import { HttpSetup } from 'kibana/public';
import { BASE_ALERTING_API_PATH, INTERNAL_BASE_ALERTING_API_PATH } from '../common';
-import type { Alert, RuleType } from '../common';
+import type { Rule, RuleType } from '../common';
import { AsApiContract } from '../../actions/common';
-import { transformAlert, transformRuleType, ApiAlert } from './lib/common_transformations';
+import { transformRule, transformRuleType, ApiRule } from './lib/common_transformations';
-export async function loadAlertTypes({ http }: { http: HttpSetup }): Promise {
+export async function loadRuleTypes({ http }: { http: HttpSetup }): Promise {
const res = await http.get>>(
`${BASE_ALERTING_API_PATH}/rule_types`
);
return res.map((ruleType) => transformRuleType(ruleType));
}
-export async function loadAlertType({
+export async function loadRuleType({
http,
id,
}: {
http: HttpSetup;
id: RuleType['id'];
}): Promise {
- const ruleTypes = await loadAlertTypes({ http });
+ const ruleTypes = await loadRuleTypes({ http });
return ruleTypes.find((type) => type.id === id);
}
-export async function loadAlert({
+export async function loadRule({
http,
- alertId,
+ ruleId,
}: {
http: HttpSetup;
- alertId: string;
-}): Promise {
- const res = await http.get(`${INTERNAL_BASE_ALERTING_API_PATH}/rule/${alertId}`);
- return transformAlert(res);
+ ruleId: string;
+}): Promise {
+ const res = await http.get(`${INTERNAL_BASE_ALERTING_API_PATH}/rule/${ruleId}`);
+ return transformRule(res);
}
diff --git a/x-pack/plugins/alerting/public/alert_navigation_registry/alert_navigation_registry.test.ts b/x-pack/plugins/alerting/public/alert_navigation_registry/alert_navigation_registry.test.ts
index 0d07b708825cb..204076151614b 100644
--- a/x-pack/plugins/alerting/public/alert_navigation_registry/alert_navigation_registry.test.ts
+++ b/x-pack/plugins/alerting/public/alert_navigation_registry/alert_navigation_registry.test.ts
@@ -6,12 +6,12 @@
*/
import { AlertNavigationRegistry } from './alert_navigation_registry';
-import { RuleType, RecoveredActionGroup, SanitizedAlert } from '../../common';
+import { RuleType, RecoveredActionGroup, SanitizedRule } from '../../common';
import uuid from 'uuid';
beforeEach(() => jest.resetAllMocks());
-const mockAlertType = (id: string): RuleType => ({
+const mockRuleType = (id: string): RuleType => ({
id,
name: id,
actionGroups: [],
@@ -30,33 +30,33 @@ const mockAlertType = (id: string): RuleType => ({
});
describe('AlertNavigationRegistry', () => {
- function handler(alert: SanitizedAlert) {
+ function handler(rule: SanitizedRule) {
return {};
}
describe('has()', () => {
test('returns false for unregistered consumer handlers', () => {
const registry = new AlertNavigationRegistry();
- expect(registry.has('siem', mockAlertType(uuid.v4()))).toEqual(false);
+ expect(registry.has('siem', mockRuleType(uuid.v4()))).toEqual(false);
});
- test('returns false for unregistered alert types handlers', () => {
+ test('returns false for unregistered rule types handlers', () => {
const registry = new AlertNavigationRegistry();
- expect(registry.has('siem', mockAlertType('index_threshold'))).toEqual(false);
+ expect(registry.has('siem', mockRuleType('index_threshold'))).toEqual(false);
});
- test('returns true for registered consumer & alert types handlers', () => {
+ test('returns true for registered consumer & rule types handlers', () => {
const registry = new AlertNavigationRegistry();
- const alertType = mockAlertType('index_threshold');
- registry.register('siem', alertType.id, handler);
- expect(registry.has('siem', alertType)).toEqual(true);
+ const ruleType = mockRuleType('index_threshold');
+ registry.register('siem', ruleType.id, handler);
+ expect(registry.has('siem', ruleType)).toEqual(true);
});
test('returns true for registered consumer with default handler', () => {
const registry = new AlertNavigationRegistry();
- const alertType = mockAlertType('index_threshold');
+ const ruleType = mockRuleType('index_threshold');
registry.registerDefault('siem', handler);
- expect(registry.has('siem', alertType)).toEqual(true);
+ expect(registry.has('siem', ruleType)).toEqual(true);
});
});
@@ -75,42 +75,42 @@ describe('AlertNavigationRegistry', () => {
});
describe('register()', () => {
- test('registers a handler by consumer & Alert Type', () => {
+ test('registers a handler by consumer & Rule Type', () => {
const registry = new AlertNavigationRegistry();
- const alertType = mockAlertType('index_threshold');
- registry.register('siem', alertType.id, handler);
- expect(registry.has('siem', alertType)).toEqual(true);
+ const ruleType = mockRuleType('index_threshold');
+ registry.register('siem', ruleType.id, handler);
+ expect(registry.has('siem', ruleType)).toEqual(true);
});
test('allows registeration of multiple handlers for the same consumer', () => {
const registry = new AlertNavigationRegistry();
- const indexThresholdAlertType = mockAlertType('index_threshold');
+ const indexThresholdAlertType = mockRuleType('index_threshold');
registry.register('siem', indexThresholdAlertType.id, handler);
expect(registry.has('siem', indexThresholdAlertType)).toEqual(true);
- const geoAlertType = mockAlertType('geogrid');
- registry.register('siem', geoAlertType.id, handler);
- expect(registry.has('siem', geoAlertType)).toEqual(true);
+ const geoRuleType = mockRuleType('geogrid');
+ registry.register('siem', geoRuleType.id, handler);
+ expect(registry.has('siem', geoRuleType)).toEqual(true);
});
- test('allows registeration of multiple handlers for the same Alert Type', () => {
+ test('allows registeration of multiple handlers for the same Rule Type', () => {
const registry = new AlertNavigationRegistry();
- const indexThresholdAlertType = mockAlertType('geogrid');
- registry.register('siem', indexThresholdAlertType.id, handler);
- expect(registry.has('siem', indexThresholdAlertType)).toEqual(true);
+ const indexThresholdRuleType = mockRuleType('geogrid');
+ registry.register('siem', indexThresholdRuleType.id, handler);
+ expect(registry.has('siem', indexThresholdRuleType)).toEqual(true);
- registry.register('apm', indexThresholdAlertType.id, handler);
- expect(registry.has('apm', indexThresholdAlertType)).toEqual(true);
+ registry.register('apm', indexThresholdRuleType.id, handler);
+ expect(registry.has('apm', indexThresholdRuleType)).toEqual(true);
});
test('throws if an existing handler is registered', () => {
const registry = new AlertNavigationRegistry();
- const alertType = mockAlertType('index_threshold');
- registry.register('siem', alertType.id, handler);
+ const ruleType = mockRuleType('index_threshold');
+ registry.register('siem', ruleType.id, handler);
expect(() => {
- registry.register('siem', alertType.id, handler);
+ registry.register('siem', ruleType.id, handler);
}).toThrowErrorMatchingInlineSnapshot(
`"Navigation for Alert type \\"index_threshold\\" within \\"siem\\" is already registered."`
);
@@ -130,9 +130,9 @@ describe('AlertNavigationRegistry', () => {
registry.registerDefault('siem', handler);
expect(registry.hasDefaultHandler('siem')).toEqual(true);
- const geoAlertType = mockAlertType('geogrid');
- registry.register('siem', geoAlertType.id, handler);
- expect(registry.has('siem', geoAlertType)).toEqual(true);
+ const geoRuleType = mockRuleType('geogrid');
+ registry.register('siem', geoRuleType.id, handler);
+ expect(registry.has('siem', geoRuleType)).toEqual(true);
});
test('throws if an existing handler is registered', () => {
@@ -147,47 +147,47 @@ describe('AlertNavigationRegistry', () => {
});
describe('get()', () => {
- test('returns registered handlers by consumer & Alert Type', () => {
+ test('returns registered handlers by consumer & Rule Type', () => {
const registry = new AlertNavigationRegistry();
- function indexThresholdHandler(alert: SanitizedAlert) {
+ function indexThresholdHandler(rule: SanitizedRule) {
return {};
}
- const indexThresholdAlertType = mockAlertType('indexThreshold');
- registry.register('siem', indexThresholdAlertType.id, indexThresholdHandler);
- expect(registry.get('siem', indexThresholdAlertType)).toEqual(indexThresholdHandler);
+ const indexThresholdRuleType = mockRuleType('indexThreshold');
+ registry.register('siem', indexThresholdRuleType.id, indexThresholdHandler);
+ expect(registry.get('siem', indexThresholdRuleType)).toEqual(indexThresholdHandler);
});
- test('returns default handlers by consumer when there is no handler for requested alert type', () => {
+ test('returns default handlers by consumer when there is no handler for requested rule type', () => {
const registry = new AlertNavigationRegistry();
- function defaultHandler(alert: SanitizedAlert) {
+ function defaultHandler(rule: SanitizedRule) {
return {};
}
registry.registerDefault('siem', defaultHandler);
- expect(registry.get('siem', mockAlertType('geogrid'))).toEqual(defaultHandler);
+ expect(registry.get('siem', mockRuleType('geogrid'))).toEqual(defaultHandler);
});
- test('returns default handlers by consumer when there are other alert type handler', () => {
+ test('returns default handlers by consumer when there are other rule type handler', () => {
const registry = new AlertNavigationRegistry();
- registry.register('siem', mockAlertType('indexThreshold').id, () => ({}));
+ registry.register('siem', mockRuleType('indexThreshold').id, () => ({}));
- function defaultHandler(alert: SanitizedAlert) {
+ function defaultHandler(rule: SanitizedRule) {
return {};
}
registry.registerDefault('siem', defaultHandler);
- expect(registry.get('siem', mockAlertType('geogrid'))).toEqual(defaultHandler);
+ expect(registry.get('siem', mockRuleType('geogrid'))).toEqual(defaultHandler);
});
test('throws if a handler isnt registered', () => {
const registry = new AlertNavigationRegistry();
- const alertType = mockAlertType('index_threshold');
+ const ruleType = mockRuleType('index_threshold');
- expect(() => registry.get('siem', alertType)).toThrowErrorMatchingInlineSnapshot(
+ expect(() => registry.get('siem', ruleType)).toThrowErrorMatchingInlineSnapshot(
`"Navigation for Alert type \\"index_threshold\\" within \\"siem\\" is not registered."`
);
});
diff --git a/x-pack/plugins/alerting/public/alert_navigation_registry/types.ts b/x-pack/plugins/alerting/public/alert_navigation_registry/types.ts
index ea36d0edd1366..3c7b7aa3c8c06 100644
--- a/x-pack/plugins/alerting/public/alert_navigation_registry/types.ts
+++ b/x-pack/plugins/alerting/public/alert_navigation_registry/types.ts
@@ -6,7 +6,7 @@
*/
import { JsonObject } from '@kbn/utility-types';
-import { SanitizedAlert } from '../../common';
+import { SanitizedRule } from '../../common';
/**
* Returns information that can be used to navigate to a specific page to view the given rule.
@@ -17,4 +17,4 @@ import { SanitizedAlert } from '../../common';
* originally registered to {@link PluginSetupContract.registerNavigation}.
*
*/
-export type AlertNavigationHandler = (alert: SanitizedAlert) => JsonObject | string;
+export type AlertNavigationHandler = (rule: SanitizedRule) => JsonObject | string;
diff --git a/x-pack/plugins/alerting/public/lib/common_transformations.test.ts b/x-pack/plugins/alerting/public/lib/common_transformations.test.ts
index 00d830bcf7611..51d24538b449e 100644
--- a/x-pack/plugins/alerting/public/lib/common_transformations.test.ts
+++ b/x-pack/plugins/alerting/public/lib/common_transformations.test.ts
@@ -5,8 +5,8 @@
* 2.0.
*/
-import { ApiAlert, transformAlert } from './common_transformations';
-import { AlertExecutionStatusErrorReasons } from '../../common';
+import { ApiRule, transformRule } from './common_transformations';
+import { RuleExecutionStatusErrorReasons } from '../../common';
beforeEach(() => jest.resetAllMocks());
@@ -16,8 +16,8 @@ const dateUpdated = new Date(dateFixed - 1000);
const dateExecuted = new Date(dateFixed);
describe('common_transformations', () => {
- test('transformAlert() with all optional fields', () => {
- const apiAlert: ApiAlert = {
+ test('transformRule() with all optional fields', () => {
+ const apiRule: ApiRule = {
id: 'some-id',
name: 'some-name',
enabled: true,
@@ -50,12 +50,12 @@ describe('common_transformations', () => {
last_duration: 42,
status: 'error',
error: {
- reason: AlertExecutionStatusErrorReasons.Unknown,
+ reason: RuleExecutionStatusErrorReasons.Unknown,
message: 'this is just a test',
},
},
};
- expect(transformAlert(apiAlert)).toMatchInlineSnapshot(`
+ expect(transformRule(apiRule)).toMatchInlineSnapshot(`
Object {
"actions": Array [
Object {
@@ -120,8 +120,8 @@ describe('common_transformations', () => {
`);
});
- test('transformAlert() with no optional fields', () => {
- const apiAlert: ApiAlert = {
+ test('transformRule() with no optional fields', () => {
+ const apiRule: ApiRule = {
id: 'some-id',
name: 'some-name',
enabled: true,
@@ -153,7 +153,7 @@ describe('common_transformations', () => {
status: 'error',
},
};
- expect(transformAlert(apiAlert)).toMatchInlineSnapshot(`
+ expect(transformRule(apiRule)).toMatchInlineSnapshot(`
Object {
"actions": Array [
Object {
diff --git a/x-pack/plugins/alerting/public/lib/common_transformations.ts b/x-pack/plugins/alerting/public/lib/common_transformations.ts
index 4d2d0e3387082..8f1f0c5c72d84 100644
--- a/x-pack/plugins/alerting/public/lib/common_transformations.ts
+++ b/x-pack/plugins/alerting/public/lib/common_transformations.ts
@@ -4,21 +4,21 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { AlertExecutionStatus, Alert, AlertAction, RuleType } from '../../common';
+import { RuleExecutionStatus, Rule, RuleAction, RuleType } from '../../common';
import { AsApiContract } from '../../../actions/common';
-function transformAction(input: AsApiContract): AlertAction {
+function transformAction(input: AsApiContract): RuleAction {
const { connector_type_id: actionTypeId, ...rest } = input;
return { actionTypeId, ...rest };
}
// AsApiContract does not deal with object properties that are dates - the
// API version needs to be a string, and the non-API version needs to be a Date
-type ApiAlertExecutionStatus = Omit, 'last_execution_date'> & {
+type ApiRuleExecutionStatus = Omit, 'last_execution_date'> & {
last_execution_date: string;
};
-function transformExecutionStatus(input: ApiAlertExecutionStatus): AlertExecutionStatus {
+function transformExecutionStatus(input: ApiRuleExecutionStatus): RuleExecutionStatus {
const { last_execution_date: lastExecutionDate, last_duration: lastDuration, ...rest } = input;
return {
lastExecutionDate: new Date(lastExecutionDate),
@@ -29,8 +29,8 @@ function transformExecutionStatus(input: ApiAlertExecutionStatus): AlertExecutio
// AsApiContract does not deal with object properties that also
// need snake -> camel conversion, Dates, are renamed, etc, so we do by hand
-export type ApiAlert = Omit<
- AsApiContract,
+export type ApiRule = Omit<
+ AsApiContract,
| 'execution_status'
| 'actions'
| 'created_at'
@@ -38,15 +38,15 @@ export type ApiAlert = Omit<
| 'alert_type_id'
| 'muted_instance_ids'
> & {
- execution_status: ApiAlertExecutionStatus;
- actions: Array>;
+ execution_status: ApiRuleExecutionStatus;
+ actions: Array>;
created_at: string;
updated_at: string;
rule_type_id: string;
muted_alert_ids: string[];
};
-export function transformAlert(input: ApiAlert): Alert {
+export function transformRule(input: ApiRule): Rule {
const {
rule_type_id: alertTypeId,
created_by: createdBy,
diff --git a/x-pack/plugins/alerting/public/plugin.ts b/x-pack/plugins/alerting/public/plugin.ts
index 71fb0c7fe32b2..e1d683d74cc9f 100644
--- a/x-pack/plugins/alerting/public/plugin.ts
+++ b/x-pack/plugins/alerting/public/plugin.ts
@@ -8,8 +8,8 @@
import { CoreSetup, Plugin, CoreStart } from 'src/core/public';
import { AlertNavigationRegistry, AlertNavigationHandler } from './alert_navigation_registry';
-import { loadAlert, loadAlertType } from './alert_api';
-import { Alert, AlertNavigation } from '../common';
+import { loadRule, loadRuleType } from './alert_api';
+import { Rule, RuleNavigation } from '../common';
export interface PluginSetupContract {
/**
@@ -18,7 +18,7 @@ export interface PluginSetupContract {
* anything with this information, but it can be used by other plugins via the `getNavigation` functionality. Currently
* the trigger_actions_ui plugin uses it to expose the link from the generic rule details view in Stack Management.
*
- * @param applicationId The application id that the user should be navigated to, to view a particular alert in a custom way.
+ * @param applicationId The application id that the user should be navigated to, to view a particular rule in a custom way.
* @param ruleType The rule type that has been registered with Alerting.Server.PluginSetupContract.registerType. If
* no such rule with that id exists, a warning is output to the console log. It used to throw an error, but that was temporarily moved
* because it was causing flaky test failures with https://github.com/elastic/kibana/issues/59229 and needs to be
@@ -39,14 +39,14 @@ export interface PluginSetupContract {
* anything with this information, but it can be used by other plugins via the `getNavigation` functionality. Currently
* the trigger_actions_ui plugin uses it to expose the link from the generic rule details view in Stack Management.
*
- * @param applicationId The application id that the user should be navigated to, to view a particular alert in a custom way.
+ * @param applicationId The application id that the user should be navigated to, to view a particular rule in a custom way.
* @param handler The navigation handler should return either a relative URL, or a state object. This information can be used,
* in conjunction with the consumer id, to navigate the user to a custom URL to view a rule's details.
*/
registerDefaultNavigation: (applicationId: string, handler: AlertNavigationHandler) => void;
}
export interface PluginStartContract {
- getNavigation: (alertId: Alert['id']) => Promise;
+ getNavigation: (ruleId: Rule['id']) => Promise;
}
export class AlertingPublicPlugin implements Plugin {
@@ -75,21 +75,21 @@ export class AlertingPublicPlugin implements Plugin {
- const alert = await loadAlert({ http: core.http, alertId });
- const alertType = await loadAlertType({ http: core.http, id: alert.alertTypeId });
+ getNavigation: async (ruleId: Rule['id']) => {
+ const rule = await loadRule({ http: core.http, ruleId });
+ const ruleType = await loadRuleType({ http: core.http, id: rule.alertTypeId });
- if (!alertType) {
+ if (!ruleType) {
// eslint-disable-next-line no-console
console.log(
- `Unable to get navigation for alert type "${alert.alertTypeId}" because it is not registered on the server side.`
+ `Unable to get navigation for rule type "${rule.alertTypeId}" because it is not registered on the server side.`
);
return;
}
- if (this.alertNavigationRegistry!.has(alert.consumer, alertType)) {
- const navigationHandler = this.alertNavigationRegistry!.get(alert.consumer, alertType);
- const state = navigationHandler(alert);
+ if (this.alertNavigationRegistry!.has(rule.consumer, ruleType)) {
+ const navigationHandler = this.alertNavigationRegistry!.get(rule.consumer, ruleType);
+ const state = navigationHandler(rule);
return typeof state === 'string' ? { path: state } : { state };
}
},
diff --git a/x-pack/plugins/alerting/server/health/get_health.test.ts b/x-pack/plugins/alerting/server/health/get_health.test.ts
index c31a71138248b..19d528d44e54f 100644
--- a/x-pack/plugins/alerting/server/health/get_health.test.ts
+++ b/x-pack/plugins/alerting/server/health/get_health.test.ts
@@ -9,13 +9,13 @@ import {
savedObjectsRepositoryMock,
savedObjectsServiceMock,
} from '../../../../../src/core/server/mocks';
-import { AlertExecutionStatusErrorReasons, HealthStatus } from '../types';
+import { RuleExecutionStatusErrorReasons, HealthStatus } from '../types';
import { getAlertingHealthStatus, getHealth } from './get_health';
const savedObjectsRepository = savedObjectsRepositoryMock.create();
describe('getHealth()', () => {
- test('return true if some of alerts has a decryption error', async () => {
+ test('return true if some rules has a decryption error', async () => {
const lastExecutionDateError = new Date().toISOString();
const lastExecutionDate = new Date().toISOString();
savedObjectsRepository.find.mockResolvedValueOnce({
@@ -46,7 +46,7 @@ describe('getHealth()', () => {
status: 'error',
lastExecutionDate: lastExecutionDateError,
error: {
- reason: AlertExecutionStatusErrorReasons.Decrypt,
+ reason: RuleExecutionStatusErrorReasons.Decrypt,
message: 'Failed decrypt',
},
},
@@ -120,7 +120,7 @@ describe('getHealth()', () => {
expect(savedObjectsRepository.find).toHaveBeenCalledTimes(4);
});
- test('return false if no alerts with a decryption error', async () => {
+ test('return false if no rules with a decryption error', async () => {
const lastExecutionDateError = new Date().toISOString();
const lastExecutionDate = new Date().toISOString();
savedObjectsRepository.find.mockResolvedValueOnce({
@@ -158,7 +158,7 @@ describe('getHealth()', () => {
status: 'error',
lastExecutionDate: lastExecutionDateError,
error: {
- reason: AlertExecutionStatusErrorReasons.Execute,
+ reason: RuleExecutionStatusErrorReasons.Execute,
message: 'Failed',
},
},
@@ -226,7 +226,7 @@ describe('getHealth()', () => {
});
describe('getAlertingHealthStatus()', () => {
- test('return the proper framework state if some of alerts has a decryption error', async () => {
+ test('return the proper framework state if some rules has a decryption error', async () => {
const savedObjects = savedObjectsServiceMock.createStartContract();
const lastExecutionDateError = new Date().toISOString();
savedObjectsRepository.find.mockResolvedValueOnce({
@@ -257,7 +257,7 @@ describe('getAlertingHealthStatus()', () => {
status: 'error',
lastExecutionDate: lastExecutionDateError,
error: {
- reason: AlertExecutionStatusErrorReasons.Decrypt,
+ reason: RuleExecutionStatusErrorReasons.Decrypt,
message: 'Failed decrypt',
},
},
diff --git a/x-pack/plugins/alerting/server/health/get_health.ts b/x-pack/plugins/alerting/server/health/get_health.ts
index 09a5922576192..2bf554894917d 100644
--- a/x-pack/plugins/alerting/server/health/get_health.ts
+++ b/x-pack/plugins/alerting/server/health/get_health.ts
@@ -6,7 +6,7 @@
*/
import { ISavedObjectsRepository, SavedObjectsServiceStart } from 'src/core/server';
-import { AlertsHealth, HealthStatus, RawRule, AlertExecutionStatusErrorReasons } from '../types';
+import { AlertsHealth, HealthStatus, RawRule, RuleExecutionStatusErrorReasons } from '../types';
export const getHealth = async (
internalSavedObjectsRepository: ISavedObjectsRepository
@@ -27,7 +27,7 @@ export const getHealth = async (
};
const { saved_objects: decryptErrorData } = await internalSavedObjectsRepository.find({
- filter: `alert.attributes.executionStatus.status:error and alert.attributes.executionStatus.error.reason:${AlertExecutionStatusErrorReasons.Decrypt}`,
+ filter: `alert.attributes.executionStatus.status:error and alert.attributes.executionStatus.error.reason:${RuleExecutionStatusErrorReasons.Decrypt}`,
fields: ['executionStatus'],
type: 'alert',
sortField: 'executionStatus.lastExecutionDate',
@@ -45,7 +45,7 @@ export const getHealth = async (
}
const { saved_objects: executeErrorData } = await internalSavedObjectsRepository.find({
- filter: `alert.attributes.executionStatus.status:error and alert.attributes.executionStatus.error.reason:${AlertExecutionStatusErrorReasons.Execute}`,
+ filter: `alert.attributes.executionStatus.status:error and alert.attributes.executionStatus.error.reason:${RuleExecutionStatusErrorReasons.Execute}`,
fields: ['executionStatus'],
type: 'alert',
sortField: 'executionStatus.lastExecutionDate',
@@ -63,7 +63,7 @@ export const getHealth = async (
}
const { saved_objects: readErrorData } = await internalSavedObjectsRepository.find({
- filter: `alert.attributes.executionStatus.status:error and alert.attributes.executionStatus.error.reason:${AlertExecutionStatusErrorReasons.Read}`,
+ filter: `alert.attributes.executionStatus.status:error and alert.attributes.executionStatus.error.reason:${RuleExecutionStatusErrorReasons.Read}`,
fields: ['executionStatus'],
type: 'alert',
sortField: 'executionStatus.lastExecutionDate',
diff --git a/x-pack/plugins/alerting/server/index.ts b/x-pack/plugins/alerting/server/index.ts
index b44df6c3d1c86..f73fb7f964b25 100644
--- a/x-pack/plugins/alerting/server/index.ts
+++ b/x-pack/plugins/alerting/server/index.ts
@@ -18,12 +18,12 @@ export type {
ActionGroup,
ActionGroupIdsOf,
AlertingPlugin,
- AlertExecutorOptions,
- AlertActionParams,
- AlertServices,
- AlertTypeState,
- AlertTypeParams,
- PartialAlert,
+ RuleExecutorOptions,
+ RuleExecutorServices,
+ RuleActionParams,
+ RuleTypeState,
+ RuleTypeParams,
+ PartialRule,
AlertInstanceState,
AlertInstanceContext,
AlertingApiRequestHandlerContext,
diff --git a/x-pack/plugins/alerting/server/lib/alert_summary_from_event_log.test.ts b/x-pack/plugins/alerting/server/lib/alert_summary_from_event_log.test.ts
index 6290d5d213046..b0a46807af5c1 100644
--- a/x-pack/plugins/alerting/server/lib/alert_summary_from_event_log.test.ts
+++ b/x-pack/plugins/alerting/server/lib/alert_summary_from_event_log.test.ts
@@ -6,7 +6,7 @@
*/
import { random, mean } from 'lodash';
-import { SanitizedAlert, AlertSummary } from '../types';
+import { SanitizedRule, AlertSummary } from '../types';
import { IValidatedEvent } from '../../../event_log/server';
import { EVENT_LOG_ACTIONS, EVENT_LOG_PROVIDER, LEGACY_EVENT_LOG_ACTIONS } from '../plugin';
import { alertSummaryFromEventLog } from './alert_summary_from_event_log';
@@ -716,11 +716,11 @@ export class EventsFactory {
}
}
-function createRule(overrides: Partial): SanitizedAlert<{ bar: boolean }> {
+function createRule(overrides: Partial): SanitizedRule<{ bar: boolean }> {
return { ...BaseRule, ...overrides };
}
-const BaseRule: SanitizedAlert<{ bar: boolean }> = {
+const BaseRule: SanitizedRule<{ bar: boolean }> = {
id: 'rule-123',
alertTypeId: '123',
schedule: { interval: '10s' },
diff --git a/x-pack/plugins/alerting/server/lib/alert_summary_from_event_log.ts b/x-pack/plugins/alerting/server/lib/alert_summary_from_event_log.ts
index 9a40c4ebf1940..e42a135b3de04 100644
--- a/x-pack/plugins/alerting/server/lib/alert_summary_from_event_log.ts
+++ b/x-pack/plugins/alerting/server/lib/alert_summary_from_event_log.ts
@@ -6,14 +6,14 @@
*/
import { mean } from 'lodash';
-import { SanitizedAlert, AlertSummary, AlertStatus } from '../types';
+import { SanitizedRule, AlertSummary, AlertStatus } from '../types';
import { IEvent } from '../../../event_log/server';
import { EVENT_LOG_ACTIONS, EVENT_LOG_PROVIDER, LEGACY_EVENT_LOG_ACTIONS } from '../plugin';
const Millis2Nanos = 1000 * 1000;
export interface AlertSummaryFromEventLogParams {
- rule: SanitizedAlert<{ bar: boolean }>;
+ rule: SanitizedRule<{ bar: boolean }>;
events: IEvent[];
executionEvents: IEvent[];
dateStart: string;
diff --git a/x-pack/plugins/alerting/server/lib/error_with_reason.test.ts b/x-pack/plugins/alerting/server/lib/error_with_reason.test.ts
index 0316db497124a..2370e2d6fef20 100644
--- a/x-pack/plugins/alerting/server/lib/error_with_reason.test.ts
+++ b/x-pack/plugins/alerting/server/lib/error_with_reason.test.ts
@@ -6,21 +6,21 @@
*/
import { ErrorWithReason, getReasonFromError, isErrorWithReason } from './error_with_reason';
-import { AlertExecutionStatusErrorReasons } from '../types';
+import { RuleExecutionStatusErrorReasons } from '../types';
describe('ErrorWithReason', () => {
const plainError = new Error('well, actually');
- const errorWithReason = new ErrorWithReason(AlertExecutionStatusErrorReasons.Decrypt, plainError);
+ const errorWithReason = new ErrorWithReason(RuleExecutionStatusErrorReasons.Decrypt, plainError);
test('ErrorWithReason class', () => {
expect(errorWithReason.message).toBe(plainError.message);
expect(errorWithReason.error).toBe(plainError);
- expect(errorWithReason.reason).toBe(AlertExecutionStatusErrorReasons.Decrypt);
+ expect(errorWithReason.reason).toBe(RuleExecutionStatusErrorReasons.Decrypt);
});
test('getReasonFromError()', () => {
expect(getReasonFromError(plainError)).toBe('unknown');
- expect(getReasonFromError(errorWithReason)).toBe(AlertExecutionStatusErrorReasons.Decrypt);
+ expect(getReasonFromError(errorWithReason)).toBe(RuleExecutionStatusErrorReasons.Decrypt);
});
test('isErrorWithReason()', () => {
diff --git a/x-pack/plugins/alerting/server/lib/error_with_reason.ts b/x-pack/plugins/alerting/server/lib/error_with_reason.ts
index 018694cb32c46..4c474d39426e3 100644
--- a/x-pack/plugins/alerting/server/lib/error_with_reason.ts
+++ b/x-pack/plugins/alerting/server/lib/error_with_reason.ts
@@ -5,24 +5,24 @@
* 2.0.
*/
-import { AlertExecutionStatusErrorReasons } from '../types';
+import { RuleExecutionStatusErrorReasons } from '../types';
export class ErrorWithReason extends Error {
- public readonly reason: AlertExecutionStatusErrorReasons;
+ public readonly reason: RuleExecutionStatusErrorReasons;
public readonly error: Error;
- constructor(reason: AlertExecutionStatusErrorReasons, error: Error) {
+ constructor(reason: RuleExecutionStatusErrorReasons, error: Error) {
super(error.message);
this.error = error;
this.reason = reason;
}
}
-export function getReasonFromError(error: Error): AlertExecutionStatusErrorReasons {
+export function getReasonFromError(error: Error): RuleExecutionStatusErrorReasons {
if (isErrorWithReason(error)) {
return error.reason;
}
- return AlertExecutionStatusErrorReasons.Unknown;
+ return RuleExecutionStatusErrorReasons.Unknown;
}
export function isErrorWithReason(error: Error | ErrorWithReason): error is ErrorWithReason {
diff --git a/x-pack/plugins/alerting/server/lib/errors/index.ts b/x-pack/plugins/alerting/server/lib/errors/index.ts
index 7ac8d9fced5cd..a2dcd45bbb63b 100644
--- a/x-pack/plugins/alerting/server/lib/errors/index.ts
+++ b/x-pack/plugins/alerting/server/lib/errors/index.ts
@@ -16,6 +16,6 @@ export function isErrorThatHandlesItsOwnResponse(
export type { ErrorThatHandlesItsOwnResponse, ElasticsearchError };
export { getEsErrorMessage };
-export type { AlertTypeDisabledReason } from './alert_type_disabled';
-export { AlertTypeDisabledError } from './alert_type_disabled';
+export type { RuleTypeDisabledReason } from './rule_type_disabled';
+export { RuleTypeDisabledError } from './rule_type_disabled';
export { RuleMutedError } from './rule_muted';
diff --git a/x-pack/plugins/alerting/server/lib/errors/alert_type_disabled.ts b/x-pack/plugins/alerting/server/lib/errors/rule_type_disabled.ts
similarity index 72%
rename from x-pack/plugins/alerting/server/lib/errors/alert_type_disabled.ts
rename to x-pack/plugins/alerting/server/lib/errors/rule_type_disabled.ts
index 554497cc6c22b..f907436ddf955 100644
--- a/x-pack/plugins/alerting/server/lib/errors/alert_type_disabled.ts
+++ b/x-pack/plugins/alerting/server/lib/errors/rule_type_disabled.ts
@@ -8,16 +8,16 @@
import { KibanaResponseFactory } from '../../../../../../src/core/server';
import { ErrorThatHandlesItsOwnResponse } from './types';
-export type AlertTypeDisabledReason =
+export type RuleTypeDisabledReason =
| 'config'
| 'license_unavailable'
| 'license_invalid'
| 'license_expired';
-export class AlertTypeDisabledError extends Error implements ErrorThatHandlesItsOwnResponse {
- public readonly reason: AlertTypeDisabledReason;
+export class RuleTypeDisabledError extends Error implements ErrorThatHandlesItsOwnResponse {
+ public readonly reason: RuleTypeDisabledReason;
- constructor(message: string, reason: AlertTypeDisabledReason) {
+ constructor(message: string, reason: RuleTypeDisabledReason) {
super(message);
this.reason = reason;
}
diff --git a/x-pack/plugins/alerting/server/lib/format_execution_log_errors.ts b/x-pack/plugins/alerting/server/lib/format_execution_log_errors.ts
index a169640c4fc83..ef5b931310f6a 100644
--- a/x-pack/plugins/alerting/server/lib/format_execution_log_errors.ts
+++ b/x-pack/plugins/alerting/server/lib/format_execution_log_errors.ts
@@ -7,6 +7,7 @@
import { get } from 'lodash';
import { QueryEventsBySavedObjectResult, IValidatedEvent } from '../../../event_log/server';
+import { IExecutionErrors, IExecutionErrorsResult } from '../../common';
const EXECUTION_UUID_FIELD = 'kibana.alert.rule.execution.uuid';
const TIMESTAMP_FIELD = '@timestamp';
@@ -14,18 +15,6 @@ const PROVIDER_FIELD = 'event.provider';
const MESSAGE_FIELD = 'message';
const ERROR_MESSAGE_FIELD = 'error.message';
-export interface IExecutionErrors {
- id: string;
- timestamp: string;
- type: string;
- message: string;
-}
-
-export interface IExecutionErrorsResult {
- totalErrors: number;
- errors: IExecutionErrors[];
-}
-
export const EMPTY_EXECUTION_ERRORS_RESULT = {
totalErrors: 0,
errors: [],
diff --git a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts
index 75022427bea27..80090effca9d1 100644
--- a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts
+++ b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts
@@ -11,6 +11,7 @@ import {
formatExecutionLogResult,
formatSortForBucketSort,
formatSortForTermSort,
+ ExecutionUuidAggResult,
} from './get_execution_log_aggregation';
describe('formatSortForBucketSort', () => {
@@ -128,92 +129,111 @@ describe('getExecutionLogAggregation', () => {
sort: [{ timestamp: { order: 'asc' } }, { execution_duration: { order: 'desc' } }],
})
).toEqual({
- executionUuidCardinality: { cardinality: { field: 'kibana.alert.rule.execution.uuid' } },
- executionUuid: {
- terms: {
- field: 'kibana.alert.rule.execution.uuid',
- size: 1000,
- order: [
- { 'ruleExecution>executeStartTime': 'asc' },
- { 'ruleExecution>executionDuration': 'desc' },
- ],
+ excludeExecuteStart: {
+ filter: {
+ bool: {
+ must_not: [
+ {
+ term: {
+ 'event.action': 'execute-start',
+ },
+ },
+ ],
+ },
},
aggs: {
- executionUuidSorted: {
- bucket_sort: {
- sort: [
- { 'ruleExecution>executeStartTime': { order: 'asc' } },
- { 'ruleExecution>executionDuration': { order: 'desc' } },
+ executionUuidCardinality: { cardinality: { field: 'kibana.alert.rule.execution.uuid' } },
+ executionUuid: {
+ terms: {
+ field: 'kibana.alert.rule.execution.uuid',
+ size: 1000,
+ order: [
+ { 'ruleExecution>executeStartTime': 'asc' },
+ { 'ruleExecution>executionDuration': 'desc' },
],
- from: 10,
- size: 10,
- gap_policy: 'insert_zeros',
- },
- },
- alertCounts: {
- filters: {
- filters: {
- newAlerts: { match: { 'event.action': 'new-instance' } },
- activeAlerts: { match: { 'event.action': 'active-instance' } },
- recoveredAlerts: { match: { 'event.action': 'recovered-instance' } },
- },
- },
- },
- actionExecution: {
- filter: {
- bool: {
- must: [
- { match: { 'event.action': 'execute' } },
- { match: { 'event.provider': 'actions' } },
- ],
- },
- },
- aggs: { actionOutcomes: { terms: { field: 'event.outcome', size: 2 } } },
- },
- ruleExecution: {
- filter: {
- bool: {
- must: [
- { match: { 'event.action': 'execute' } },
- { match: { 'event.provider': 'alerting' } },
- ],
- },
},
aggs: {
- executeStartTime: { min: { field: 'event.start' } },
- scheduleDelay: {
- max: {
- field: 'kibana.task.schedule_delay',
+ executionUuidSorted: {
+ bucket_sort: {
+ sort: [
+ { 'ruleExecution>executeStartTime': { order: 'asc' } },
+ { 'ruleExecution>executionDuration': { order: 'desc' } },
+ ],
+ from: 10,
+ size: 10,
+ gap_policy: 'insert_zeros',
},
},
- totalSearchDuration: {
- max: { field: 'kibana.alert.rule.execution.metrics.total_search_duration_ms' },
- },
- esSearchDuration: {
- max: { field: 'kibana.alert.rule.execution.metrics.es_search_duration_ms' },
- },
- numTriggeredActions: {
- max: { field: 'kibana.alert.rule.execution.metrics.number_of_triggered_actions' },
+ alertCounts: {
+ filters: {
+ filters: {
+ newAlerts: { match: { 'event.action': 'new-instance' } },
+ activeAlerts: { match: { 'event.action': 'active-instance' } },
+ recoveredAlerts: { match: { 'event.action': 'recovered-instance' } },
+ },
+ },
},
- numScheduledActions: {
- max: { field: 'kibana.alert.rule.execution.metrics.number_of_scheduled_actions' },
+ actionExecution: {
+ filter: {
+ bool: {
+ must: [
+ { match: { 'event.action': 'execute' } },
+ { match: { 'event.provider': 'actions' } },
+ ],
+ },
+ },
+ aggs: { actionOutcomes: { terms: { field: 'event.outcome', size: 2 } } },
},
- executionDuration: { max: { field: 'event.duration' } },
- outcomeAndMessage: {
- top_hits: {
- size: 1,
- _source: { includes: ['event.outcome', 'message', 'error.message'] },
+ ruleExecution: {
+ filter: {
+ bool: {
+ must: [
+ { match: { 'event.action': 'execute' } },
+ { match: { 'event.provider': 'alerting' } },
+ ],
+ },
+ },
+ aggs: {
+ executeStartTime: { min: { field: 'event.start' } },
+ scheduleDelay: {
+ max: {
+ field: 'kibana.task.schedule_delay',
+ },
+ },
+ totalSearchDuration: {
+ max: { field: 'kibana.alert.rule.execution.metrics.total_search_duration_ms' },
+ },
+ esSearchDuration: {
+ max: { field: 'kibana.alert.rule.execution.metrics.es_search_duration_ms' },
+ },
+ numTriggeredActions: {
+ max: {
+ field: 'kibana.alert.rule.execution.metrics.number_of_triggered_actions',
+ },
+ },
+ numScheduledActions: {
+ max: {
+ field: 'kibana.alert.rule.execution.metrics.number_of_scheduled_actions',
+ },
+ },
+ executionDuration: { max: { field: 'event.duration' } },
+ outcomeAndMessage: {
+ top_hits: {
+ size: 1,
+ _source: { includes: ['event.outcome', 'message', 'error.message'] },
+ },
+ },
},
},
- },
- },
- timeoutMessage: {
- filter: {
- bool: {
- must: [
- { match: { 'event.action': 'execute-timeout' } },
- { match: { 'event.provider': 'alerting' } },
- ],
+ timeoutMessage: {
+ filter: {
+ bool: {
+ must: [
+ { match: { 'event.action': 'execute-timeout' } },
+ { match: { 'event.provider': 'alerting' } },
+ ],
+ },
+ },
},
},
},
@@ -230,188 +250,202 @@ describe('formatExecutionLogResult', () => {
data: [],
});
});
+ test('should return empty results if aggregations.excludeExecuteStart are undefined', () => {
+ expect(
+ formatExecutionLogResult({
+ aggregations: { excludeExecuteStart: undefined as unknown as ExecutionUuidAggResult },
+ })
+ ).toEqual({
+ total: 0,
+ data: [],
+ });
+ });
test('should format results correctly', () => {
const results = {
aggregations: {
- executionUuid: {
+ excludeExecuteStart: {
meta: {},
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [
- {
- key: '6705da7d-2635-499d-a6a8-1aee1ae1eac9',
- doc_count: 27,
- timeoutMessage: {
- meta: {},
- doc_count: 0,
- },
- alertCounts: {
- meta: {},
- buckets: {
- activeAlerts: {
- doc_count: 5,
+ doc_count: 875,
+ executionUuid: {
+ meta: {},
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
+ {
+ key: '6705da7d-2635-499d-a6a8-1aee1ae1eac9',
+ doc_count: 27,
+ timeoutMessage: {
+ meta: {},
+ doc_count: 0,
+ },
+ alertCounts: {
+ meta: {},
+ buckets: {
+ activeAlerts: {
+ doc_count: 5,
+ },
+ newAlerts: {
+ doc_count: 5,
+ },
+ recoveredAlerts: {
+ doc_count: 0,
+ },
},
- newAlerts: {
- doc_count: 5,
+ },
+ ruleExecution: {
+ meta: {},
+ doc_count: 1,
+ numTriggeredActions: {
+ value: 5.0,
},
- recoveredAlerts: {
- doc_count: 0,
+ numScheduledActions: {
+ value: 5.0,
},
- },
- },
- ruleExecution: {
- meta: {},
- doc_count: 1,
- numTriggeredActions: {
- value: 5.0,
- },
- numScheduledActions: {
- value: 5.0,
- },
- outcomeAndMessage: {
- hits: {
- total: {
- value: 1,
- relation: 'eq',
- },
- max_score: 1.0,
- hits: [
- {
- _index: '.kibana-event-log-8.2.0-000001',
- _id: 'S4wIZX8B8TGQpG7XQZns',
- _score: 1.0,
- _source: {
- event: {
- outcome: 'success',
+ outcomeAndMessage: {
+ hits: {
+ total: {
+ value: 1,
+ relation: 'eq',
+ },
+ max_score: 1.0,
+ hits: [
+ {
+ _index: '.kibana-event-log-8.2.0-000001',
+ _id: 'S4wIZX8B8TGQpG7XQZns',
+ _score: 1.0,
+ _source: {
+ event: {
+ outcome: 'success',
+ },
+ message:
+ "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
},
- message:
- "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
},
+ ],
+ },
+ },
+ scheduleDelay: {
+ value: 3.074e9,
+ },
+ totalSearchDuration: {
+ value: 0.0,
+ },
+ esSearchDuration: {
+ value: 0.0,
+ },
+ executionDuration: {
+ value: 1.056e9,
+ },
+ executeStartTime: {
+ value: 1.646667512617e12,
+ value_as_string: '2022-03-07T15:38:32.617Z',
+ },
+ },
+ actionExecution: {
+ meta: {},
+ doc_count: 5,
+ actionOutcomes: {
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
+ {
+ key: 'success',
+ doc_count: 5,
},
],
},
},
- scheduleDelay: {
- value: 3.074e9,
- },
- totalSearchDuration: {
- value: 0.0,
- },
- esSearchDuration: {
- value: 0.0,
- },
- executionDuration: {
- value: 1.056e9,
- },
- executeStartTime: {
- value: 1.646667512617e12,
- value_as_string: '2022-03-07T15:38:32.617Z',
- },
},
- actionExecution: {
- meta: {},
- doc_count: 5,
- actionOutcomes: {
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [
- {
- key: 'success',
+ {
+ key: '41b2755e-765a-4044-9745-b03875d5e79a',
+ doc_count: 32,
+ timeoutMessage: {
+ meta: {},
+ doc_count: 0,
+ },
+ alertCounts: {
+ meta: {},
+ buckets: {
+ activeAlerts: {
doc_count: 5,
},
- ],
+ newAlerts: {
+ doc_count: 5,
+ },
+ recoveredAlerts: {
+ doc_count: 5,
+ },
+ },
},
- },
- },
- {
- key: '41b2755e-765a-4044-9745-b03875d5e79a',
- doc_count: 32,
- timeoutMessage: {
- meta: {},
- doc_count: 0,
- },
- alertCounts: {
- meta: {},
- buckets: {
- activeAlerts: {
- doc_count: 5,
+ ruleExecution: {
+ meta: {},
+ doc_count: 1,
+ numTriggeredActions: {
+ value: 5.0,
},
- newAlerts: {
- doc_count: 5,
+ numScheduledActions: {
+ value: 5.0,
},
- recoveredAlerts: {
- doc_count: 5,
+ outcomeAndMessage: {
+ hits: {
+ total: {
+ value: 1,
+ relation: 'eq',
+ },
+ max_score: 1.0,
+ hits: [
+ {
+ _index: '.kibana-event-log-8.2.0-000001',
+ _id: 'a4wIZX8B8TGQpG7Xwpnz',
+ _score: 1.0,
+ _source: {
+ event: {
+ outcome: 'success',
+ },
+ message:
+ "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
+ },
+ },
+ ],
+ },
+ },
+ scheduleDelay: {
+ value: 3.126e9,
+ },
+ totalSearchDuration: {
+ value: 0.0,
+ },
+ esSearchDuration: {
+ value: 0.0,
+ },
+ executionDuration: {
+ value: 1.165e9,
+ },
+ executeStartTime: {
+ value: 1.646667545604e12,
+ value_as_string: '2022-03-07T15:39:05.604Z',
},
},
- },
- ruleExecution: {
- meta: {},
- doc_count: 1,
- numTriggeredActions: {
- value: 5.0,
- },
- numScheduledActions: {
- value: 5.0,
- },
- outcomeAndMessage: {
- hits: {
- total: {
- value: 1,
- relation: 'eq',
- },
- max_score: 1.0,
- hits: [
+ actionExecution: {
+ meta: {},
+ doc_count: 5,
+ actionOutcomes: {
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
{
- _index: '.kibana-event-log-8.2.0-000001',
- _id: 'a4wIZX8B8TGQpG7Xwpnz',
- _score: 1.0,
- _source: {
- event: {
- outcome: 'success',
- },
- message:
- "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
- },
+ key: 'success',
+ doc_count: 5,
},
],
},
},
- scheduleDelay: {
- value: 3.126e9,
- },
- totalSearchDuration: {
- value: 0.0,
- },
- esSearchDuration: {
- value: 0.0,
- },
- executionDuration: {
- value: 1.165e9,
- },
- executeStartTime: {
- value: 1.646667545604e12,
- value_as_string: '2022-03-07T15:39:05.604Z',
- },
},
- actionExecution: {
- meta: {},
- doc_count: 5,
- actionOutcomes: {
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [
- {
- key: 'success',
- doc_count: 5,
- },
- ],
- },
- },
- },
- ],
- },
- executionUuidCardinality: {
- value: 374,
+ ],
+ },
+ executionUuidCardinality: {
+ value: 374,
+ },
},
},
};
@@ -463,188 +497,192 @@ describe('formatExecutionLogResult', () => {
test('should format results correctly with rule execution errors', () => {
const results = {
aggregations: {
- executionUuid: {
+ excludeExecuteStart: {
meta: {},
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [
- {
- key: '6705da7d-2635-499d-a6a8-1aee1ae1eac9',
- doc_count: 27,
- timeoutMessage: {
- meta: {},
- doc_count: 0,
- },
- alertCounts: {
- meta: {},
- buckets: {
- activeAlerts: {
- doc_count: 5,
+ doc_count: 875,
+ executionUuid: {
+ meta: {},
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
+ {
+ key: '6705da7d-2635-499d-a6a8-1aee1ae1eac9',
+ doc_count: 27,
+ timeoutMessage: {
+ meta: {},
+ doc_count: 0,
+ },
+ alertCounts: {
+ meta: {},
+ buckets: {
+ activeAlerts: {
+ doc_count: 5,
+ },
+ newAlerts: {
+ doc_count: 5,
+ },
+ recoveredAlerts: {
+ doc_count: 0,
+ },
},
- newAlerts: {
- doc_count: 5,
+ },
+ ruleExecution: {
+ meta: {},
+ doc_count: 1,
+ numTriggeredActions: {
+ value: 5.0,
},
- recoveredAlerts: {
- doc_count: 0,
+ numScheduledActions: {
+ value: 5.0,
},
- },
- },
- ruleExecution: {
- meta: {},
- doc_count: 1,
- numTriggeredActions: {
- value: 5.0,
- },
- numScheduledActions: {
- value: 5.0,
- },
- outcomeAndMessage: {
- hits: {
- total: {
- value: 1,
- relation: 'eq',
- },
- max_score: 1.0,
- hits: [
- {
- _index: '.kibana-event-log-8.2.0-000001',
- _id: 'S4wIZX8B8TGQpG7XQZns',
- _score: 1.0,
- _source: {
- event: {
- outcome: 'failure',
- },
- message:
- "rule execution failure: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
- error: {
- message: 'I am erroring in rule execution!!',
+ outcomeAndMessage: {
+ hits: {
+ total: {
+ value: 1,
+ relation: 'eq',
+ },
+ max_score: 1.0,
+ hits: [
+ {
+ _index: '.kibana-event-log-8.2.0-000001',
+ _id: 'S4wIZX8B8TGQpG7XQZns',
+ _score: 1.0,
+ _source: {
+ event: {
+ outcome: 'failure',
+ },
+ message:
+ "rule execution failure: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
+ error: {
+ message: 'I am erroring in rule execution!!',
+ },
},
},
+ ],
+ },
+ },
+ scheduleDelay: {
+ value: 3.074e9,
+ },
+ totalSearchDuration: {
+ value: 0.0,
+ },
+ esSearchDuration: {
+ value: 0.0,
+ },
+ executionDuration: {
+ value: 1.056e9,
+ },
+ executeStartTime: {
+ value: 1.646667512617e12,
+ value_as_string: '2022-03-07T15:38:32.617Z',
+ },
+ },
+ actionExecution: {
+ meta: {},
+ doc_count: 5,
+ actionOutcomes: {
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
+ {
+ key: 'success',
+ doc_count: 5,
},
],
},
},
- scheduleDelay: {
- value: 3.074e9,
- },
- totalSearchDuration: {
- value: 0.0,
- },
- esSearchDuration: {
- value: 0.0,
- },
- executionDuration: {
- value: 1.056e9,
- },
- executeStartTime: {
- value: 1.646667512617e12,
- value_as_string: '2022-03-07T15:38:32.617Z',
- },
},
- actionExecution: {
- meta: {},
- doc_count: 5,
- actionOutcomes: {
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [
- {
- key: 'success',
+ {
+ key: '41b2755e-765a-4044-9745-b03875d5e79a',
+ doc_count: 32,
+ timeoutMessage: {
+ meta: {},
+ doc_count: 0,
+ },
+ alertCounts: {
+ meta: {},
+ buckets: {
+ activeAlerts: {
doc_count: 5,
},
- ],
+ newAlerts: {
+ doc_count: 5,
+ },
+ recoveredAlerts: {
+ doc_count: 5,
+ },
+ },
},
- },
- },
- {
- key: '41b2755e-765a-4044-9745-b03875d5e79a',
- doc_count: 32,
- timeoutMessage: {
- meta: {},
- doc_count: 0,
- },
- alertCounts: {
- meta: {},
- buckets: {
- activeAlerts: {
- doc_count: 5,
+ ruleExecution: {
+ meta: {},
+ doc_count: 1,
+ numTriggeredActions: {
+ value: 5.0,
},
- newAlerts: {
- doc_count: 5,
+ numScheduledActions: {
+ value: 5.0,
},
- recoveredAlerts: {
- doc_count: 5,
+ outcomeAndMessage: {
+ hits: {
+ total: {
+ value: 1,
+ relation: 'eq',
+ },
+ max_score: 1.0,
+ hits: [
+ {
+ _index: '.kibana-event-log-8.2.0-000001',
+ _id: 'a4wIZX8B8TGQpG7Xwpnz',
+ _score: 1.0,
+ _source: {
+ event: {
+ outcome: 'success',
+ },
+ message:
+ "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
+ },
+ },
+ ],
+ },
+ },
+ scheduleDelay: {
+ value: 3.126e9,
+ },
+ totalSearchDuration: {
+ value: 0.0,
+ },
+ esSearchDuration: {
+ value: 0.0,
+ },
+ executionDuration: {
+ value: 1.165e9,
+ },
+ executeStartTime: {
+ value: 1.646667545604e12,
+ value_as_string: '2022-03-07T15:39:05.604Z',
},
},
- },
- ruleExecution: {
- meta: {},
- doc_count: 1,
- numTriggeredActions: {
- value: 5.0,
- },
- numScheduledActions: {
- value: 5.0,
- },
- outcomeAndMessage: {
- hits: {
- total: {
- value: 1,
- relation: 'eq',
- },
- max_score: 1.0,
- hits: [
+ actionExecution: {
+ meta: {},
+ doc_count: 5,
+ actionOutcomes: {
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
{
- _index: '.kibana-event-log-8.2.0-000001',
- _id: 'a4wIZX8B8TGQpG7Xwpnz',
- _score: 1.0,
- _source: {
- event: {
- outcome: 'success',
- },
- message:
- "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
- },
+ key: 'success',
+ doc_count: 5,
},
],
},
},
- scheduleDelay: {
- value: 3.126e9,
- },
- totalSearchDuration: {
- value: 0.0,
- },
- esSearchDuration: {
- value: 0.0,
- },
- executionDuration: {
- value: 1.165e9,
- },
- executeStartTime: {
- value: 1.646667545604e12,
- value_as_string: '2022-03-07T15:39:05.604Z',
- },
},
- actionExecution: {
- meta: {},
- doc_count: 5,
- actionOutcomes: {
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [
- {
- key: 'success',
- doc_count: 5,
- },
- ],
- },
- },
- },
- ],
- },
- executionUuidCardinality: {
- value: 374,
+ ],
+ },
+ executionUuidCardinality: {
+ value: 374,
+ },
},
},
};
@@ -696,180 +734,184 @@ describe('formatExecutionLogResult', () => {
test('should format results correctly when execution timeouts occur', () => {
const results = {
aggregations: {
- executionUuid: {
+ excludeExecuteStart: {
meta: {},
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [
- {
- key: '09b5aeab-d50d-43b2-88e7-f1a20f682b3f',
- doc_count: 3,
- timeoutMessage: {
- meta: {},
- doc_count: 1,
- },
- alertCounts: {
- meta: {},
- buckets: {
- activeAlerts: {
- doc_count: 0,
+ doc_count: 875,
+ executionUuid: {
+ meta: {},
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
+ {
+ key: '09b5aeab-d50d-43b2-88e7-f1a20f682b3f',
+ doc_count: 3,
+ timeoutMessage: {
+ meta: {},
+ doc_count: 1,
+ },
+ alertCounts: {
+ meta: {},
+ buckets: {
+ activeAlerts: {
+ doc_count: 0,
+ },
+ newAlerts: {
+ doc_count: 0,
+ },
+ recoveredAlerts: {
+ doc_count: 0,
+ },
},
- newAlerts: {
- doc_count: 0,
+ },
+ ruleExecution: {
+ meta: {},
+ doc_count: 1,
+ numTriggeredActions: {
+ value: 0.0,
},
- recoveredAlerts: {
- doc_count: 0,
+ numScheduledActions: {
+ value: 0.0,
},
- },
- },
- ruleExecution: {
- meta: {},
- doc_count: 1,
- numTriggeredActions: {
- value: 0.0,
- },
- numScheduledActions: {
- value: 0.0,
- },
- outcomeAndMessage: {
- hits: {
- total: {
- value: 1,
- relation: 'eq',
- },
- max_score: 1.0,
- hits: [
- {
- _index: '.kibana-event-log-8.2.0-000001',
- _id: 'dJkWa38B1ylB1EvsAckB',
- _score: 1.0,
- _source: {
- event: {
- outcome: 'success',
+ outcomeAndMessage: {
+ hits: {
+ total: {
+ value: 1,
+ relation: 'eq',
+ },
+ max_score: 1.0,
+ hits: [
+ {
+ _index: '.kibana-event-log-8.2.0-000001',
+ _id: 'dJkWa38B1ylB1EvsAckB',
+ _score: 1.0,
+ _source: {
+ event: {
+ outcome: 'success',
+ },
+ message:
+ "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
},
- message:
- "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
},
- },
- ],
+ ],
+ },
+ },
+ scheduleDelay: {
+ value: 3.074e9,
+ },
+ totalSearchDuration: {
+ value: 0.0,
+ },
+ esSearchDuration: {
+ value: 0.0,
+ },
+ executionDuration: {
+ value: 1.0279e10,
+ },
+ executeStartTime: {
+ value: 1.646769067607e12,
+ value_as_string: '2022-03-08T19:51:07.607Z',
},
},
- scheduleDelay: {
- value: 3.074e9,
- },
- totalSearchDuration: {
- value: 0.0,
- },
- esSearchDuration: {
- value: 0.0,
- },
- executionDuration: {
- value: 1.0279e10,
- },
- executeStartTime: {
- value: 1.646769067607e12,
- value_as_string: '2022-03-08T19:51:07.607Z',
+ actionExecution: {
+ meta: {},
+ doc_count: 0,
+ actionOutcomes: {
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [],
+ },
},
},
- actionExecution: {
- meta: {},
- doc_count: 0,
- actionOutcomes: {
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [],
+ {
+ key: '41b2755e-765a-4044-9745-b03875d5e79a',
+ doc_count: 32,
+ timeoutMessage: {
+ meta: {},
+ doc_count: 0,
+ },
+ alertCounts: {
+ meta: {},
+ buckets: {
+ activeAlerts: {
+ doc_count: 5,
+ },
+ newAlerts: {
+ doc_count: 5,
+ },
+ recoveredAlerts: {
+ doc_count: 5,
+ },
+ },
},
- },
- },
- {
- key: '41b2755e-765a-4044-9745-b03875d5e79a',
- doc_count: 32,
- timeoutMessage: {
- meta: {},
- doc_count: 0,
- },
- alertCounts: {
- meta: {},
- buckets: {
- activeAlerts: {
- doc_count: 5,
+ ruleExecution: {
+ meta: {},
+ doc_count: 1,
+ numTriggeredActions: {
+ value: 5.0,
},
- newAlerts: {
- doc_count: 5,
+ numScheduledActions: {
+ value: 5.0,
},
- recoveredAlerts: {
- doc_count: 5,
+ outcomeAndMessage: {
+ hits: {
+ total: {
+ value: 1,
+ relation: 'eq',
+ },
+ max_score: 1.0,
+ hits: [
+ {
+ _index: '.kibana-event-log-8.2.0-000001',
+ _id: 'a4wIZX8B8TGQpG7Xwpnz',
+ _score: 1.0,
+ _source: {
+ event: {
+ outcome: 'success',
+ },
+ message:
+ "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
+ },
+ },
+ ],
+ },
+ },
+ scheduleDelay: {
+ value: 3.126e9,
+ },
+ totalSearchDuration: {
+ value: 0.0,
+ },
+ esSearchDuration: {
+ value: 0.0,
+ },
+ executionDuration: {
+ value: 1.165e9,
+ },
+ executeStartTime: {
+ value: 1.646667545604e12,
+ value_as_string: '2022-03-07T15:39:05.604Z',
},
},
- },
- ruleExecution: {
- meta: {},
- doc_count: 1,
- numTriggeredActions: {
- value: 5.0,
- },
- numScheduledActions: {
- value: 5.0,
- },
- outcomeAndMessage: {
- hits: {
- total: {
- value: 1,
- relation: 'eq',
- },
- max_score: 1.0,
- hits: [
+ actionExecution: {
+ meta: {},
+ doc_count: 5,
+ actionOutcomes: {
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
{
- _index: '.kibana-event-log-8.2.0-000001',
- _id: 'a4wIZX8B8TGQpG7Xwpnz',
- _score: 1.0,
- _source: {
- event: {
- outcome: 'success',
- },
- message:
- "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
- },
+ key: 'success',
+ doc_count: 5,
},
],
},
},
- scheduleDelay: {
- value: 3.126e9,
- },
- totalSearchDuration: {
- value: 0.0,
- },
- esSearchDuration: {
- value: 0.0,
- },
- executionDuration: {
- value: 1.165e9,
- },
- executeStartTime: {
- value: 1.646667545604e12,
- value_as_string: '2022-03-07T15:39:05.604Z',
- },
},
- actionExecution: {
- meta: {},
- doc_count: 5,
- actionOutcomes: {
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [
- {
- key: 'success',
- doc_count: 5,
- },
- ],
- },
- },
- },
- ],
- },
- executionUuidCardinality: {
- value: 374,
+ ],
+ },
+ executionUuidCardinality: {
+ value: 374,
+ },
},
},
};
@@ -921,185 +963,189 @@ describe('formatExecutionLogResult', () => {
test('should format results correctly when action errors occur', () => {
const results = {
aggregations: {
- executionUuid: {
+ excludeExecuteStart: {
meta: {},
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [
- {
- key: 'ecf7ac4c-1c15-4a1d-818a-cacbf57f6158',
- doc_count: 32,
- timeoutMessage: {
- meta: {},
- doc_count: 0,
- },
- alertCounts: {
- meta: {},
- buckets: {
- activeAlerts: {
- doc_count: 5,
+ doc_count: 875,
+ executionUuid: {
+ meta: {},
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
+ {
+ key: 'ecf7ac4c-1c15-4a1d-818a-cacbf57f6158',
+ doc_count: 32,
+ timeoutMessage: {
+ meta: {},
+ doc_count: 0,
+ },
+ alertCounts: {
+ meta: {},
+ buckets: {
+ activeAlerts: {
+ doc_count: 5,
+ },
+ newAlerts: {
+ doc_count: 5,
+ },
+ recoveredAlerts: {
+ doc_count: 5,
+ },
},
- newAlerts: {
- doc_count: 5,
+ },
+ ruleExecution: {
+ meta: {},
+ doc_count: 1,
+ numTriggeredActions: {
+ value: 5.0,
},
- recoveredAlerts: {
- doc_count: 5,
+ numScheduledActions: {
+ value: 5.0,
},
- },
- },
- ruleExecution: {
- meta: {},
- doc_count: 1,
- numTriggeredActions: {
- value: 5.0,
- },
- numScheduledActions: {
- value: 5.0,
- },
- outcomeAndMessage: {
- hits: {
- total: {
- value: 1,
- relation: 'eq',
- },
- max_score: 1.0,
- hits: [
- {
- _index: '.kibana-event-log-8.2.0-000001',
- _id: '7xKcb38BcntAq5ycFwiu',
- _score: 1.0,
- _source: {
- event: {
- outcome: 'success',
+ outcomeAndMessage: {
+ hits: {
+ total: {
+ value: 1,
+ relation: 'eq',
+ },
+ max_score: 1.0,
+ hits: [
+ {
+ _index: '.kibana-event-log-8.2.0-000001',
+ _id: '7xKcb38BcntAq5ycFwiu',
+ _score: 1.0,
+ _source: {
+ event: {
+ outcome: 'success',
+ },
+ message:
+ "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
},
- message:
- "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
},
+ ],
+ },
+ },
+ scheduleDelay: {
+ value: 3.126e9,
+ },
+ totalSearchDuration: {
+ value: 0.0,
+ },
+ esSearchDuration: {
+ value: 0.0,
+ },
+ executionDuration: {
+ value: 1.374e9,
+ },
+ executeStartTime: {
+ value: 1.646844973039e12,
+ value_as_string: '2022-03-09T16:56:13.039Z',
+ },
+ },
+ actionExecution: {
+ meta: {},
+ doc_count: 5,
+ actionOutcomes: {
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
+ {
+ key: 'failure',
+ doc_count: 5,
},
],
},
},
- scheduleDelay: {
- value: 3.126e9,
- },
- totalSearchDuration: {
- value: 0.0,
- },
- esSearchDuration: {
- value: 0.0,
- },
- executionDuration: {
- value: 1.374e9,
- },
- executeStartTime: {
- value: 1.646844973039e12,
- value_as_string: '2022-03-09T16:56:13.039Z',
- },
},
- actionExecution: {
- meta: {},
- doc_count: 5,
- actionOutcomes: {
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [
- {
- key: 'failure',
+ {
+ key: '61bb867b-661a-471f-bf92-23471afa10b3',
+ doc_count: 32,
+ timeoutMessage: {
+ meta: {},
+ doc_count: 0,
+ },
+ alertCounts: {
+ meta: {},
+ buckets: {
+ activeAlerts: {
doc_count: 5,
},
- ],
+ newAlerts: {
+ doc_count: 5,
+ },
+ recoveredAlerts: {
+ doc_count: 5,
+ },
+ },
},
- },
- },
- {
- key: '61bb867b-661a-471f-bf92-23471afa10b3',
- doc_count: 32,
- timeoutMessage: {
- meta: {},
- doc_count: 0,
- },
- alertCounts: {
- meta: {},
- buckets: {
- activeAlerts: {
- doc_count: 5,
+ ruleExecution: {
+ meta: {},
+ doc_count: 1,
+ numTriggeredActions: {
+ value: 5.0,
},
- newAlerts: {
- doc_count: 5,
+ numScheduledActions: {
+ value: 5.0,
},
- recoveredAlerts: {
- doc_count: 5,
+ outcomeAndMessage: {
+ hits: {
+ total: {
+ value: 1,
+ relation: 'eq',
+ },
+ max_score: 1.0,
+ hits: [
+ {
+ _index: '.kibana-event-log-8.2.0-000001',
+ _id: 'zRKbb38BcntAq5ycOwgk',
+ _score: 1.0,
+ _source: {
+ event: {
+ outcome: 'success',
+ },
+ message:
+ "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
+ },
+ },
+ ],
+ },
+ },
+ scheduleDelay: {
+ value: 3.133e9,
+ },
+ totalSearchDuration: {
+ value: 0.0,
+ },
+ esSearchDuration: {
+ value: 0.0,
+ },
+ executionDuration: {
+ value: 4.18e8,
+ },
+ executeStartTime: {
+ value: 1.646844917518e12,
+ value_as_string: '2022-03-09T16:55:17.518Z',
},
},
- },
- ruleExecution: {
- meta: {},
- doc_count: 1,
- numTriggeredActions: {
- value: 5.0,
- },
- numScheduledActions: {
- value: 5.0,
- },
- outcomeAndMessage: {
- hits: {
- total: {
- value: 1,
- relation: 'eq',
- },
- max_score: 1.0,
- hits: [
+ actionExecution: {
+ meta: {},
+ doc_count: 5,
+ actionOutcomes: {
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
{
- _index: '.kibana-event-log-8.2.0-000001',
- _id: 'zRKbb38BcntAq5ycOwgk',
- _score: 1.0,
- _source: {
- event: {
- outcome: 'success',
- },
- message:
- "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
- },
+ key: 'success',
+ doc_count: 5,
},
],
},
},
- scheduleDelay: {
- value: 3.133e9,
- },
- totalSearchDuration: {
- value: 0.0,
- },
- esSearchDuration: {
- value: 0.0,
- },
- executionDuration: {
- value: 4.18e8,
- },
- executeStartTime: {
- value: 1.646844917518e12,
- value_as_string: '2022-03-09T16:55:17.518Z',
- },
},
- actionExecution: {
- meta: {},
- doc_count: 5,
- actionOutcomes: {
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [
- {
- key: 'success',
- doc_count: 5,
- },
- ],
- },
- },
- },
- ],
- },
- executionUuidCardinality: {
- value: 417,
+ ],
+ },
+ executionUuidCardinality: {
+ value: 417,
+ },
},
},
};
diff --git a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts
index 6f8d0d8059b69..fbe72508dab2b 100644
--- a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts
+++ b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts
@@ -68,10 +68,15 @@ interface IExecutionUuidAggBucket extends estypes.AggregationsStringTermsBucketK
};
}
-interface ExecutionUuidAggResult
+export interface ExecutionUuidAggResult
extends estypes.AggregationsAggregateBase {
buckets: TBucket[];
}
+
+interface ExcludeExecuteStartAggResult extends estypes.AggregationsAggregateBase {
+ executionUuid: ExecutionUuidAggResult;
+ executionUuidCardinality: estypes.AggregationsCardinalityAggregate;
+}
export interface IExecutionLogAggOptions {
page: number;
perPage: number;
@@ -112,104 +117,119 @@ export function getExecutionLogAggregation({ page, perPage, sort }: IExecutionLo
}
return {
- // Get total number of executions
- executionUuidCardinality: {
- cardinality: {
- field: EXECUTION_UUID_FIELD,
- },
- },
- executionUuid: {
- // Bucket by execution UUID
- terms: {
- field: EXECUTION_UUID_FIELD,
- size: DEFAULT_MAX_BUCKETS_LIMIT,
- order: formatSortForTermSort(sort),
+ excludeExecuteStart: {
+ filter: {
+ bool: {
+ must_not: [
+ {
+ term: {
+ [ACTION_FIELD]: 'execute-start',
+ },
+ },
+ ],
+ },
},
aggs: {
- // Bucket sort to allow paging through executions
- executionUuidSorted: {
- bucket_sort: {
- sort: formatSortForBucketSort(sort),
- from: (page - 1) * perPage,
- size: perPage,
- gap_policy: 'insert_zeros' as estypes.AggregationsGapPolicy,
+ // Get total number of executions
+ executionUuidCardinality: {
+ cardinality: {
+ field: EXECUTION_UUID_FIELD,
},
},
- // Get counts for types of alerts and whether there was an execution timeout
- alertCounts: {
- filters: {
- filters: {
- newAlerts: { match: { [ACTION_FIELD]: 'new-instance' } },
- activeAlerts: { match: { [ACTION_FIELD]: 'active-instance' } },
- recoveredAlerts: { match: { [ACTION_FIELD]: 'recovered-instance' } },
- },
+ executionUuid: {
+ // Bucket by execution UUID
+ terms: {
+ field: EXECUTION_UUID_FIELD,
+ size: DEFAULT_MAX_BUCKETS_LIMIT,
+ order: formatSortForTermSort(sort),
},
- },
- // Filter by action execute doc and get information from this event
- actionExecution: {
- filter: getProviderAndActionFilter('actions', 'execute'),
aggs: {
- actionOutcomes: {
- terms: {
- field: OUTCOME_FIELD,
- size: 2,
- },
- },
- },
- },
- // Filter by rule execute doc and get information from this event
- ruleExecution: {
- filter: getProviderAndActionFilter('alerting', 'execute'),
- aggs: {
- executeStartTime: {
- min: {
- field: START_FIELD,
- },
- },
- scheduleDelay: {
- max: {
- field: SCHEDULE_DELAY_FIELD,
- },
- },
- totalSearchDuration: {
- max: {
- field: TOTAL_SEARCH_DURATION_FIELD,
- },
- },
- esSearchDuration: {
- max: {
- field: ES_SEARCH_DURATION_FIELD,
- },
- },
- numTriggeredActions: {
- max: {
- field: NUMBER_OF_TRIGGERED_ACTIONS_FIELD,
+ // Bucket sort to allow paging through executions
+ executionUuidSorted: {
+ bucket_sort: {
+ sort: formatSortForBucketSort(sort),
+ from: (page - 1) * perPage,
+ size: perPage,
+ gap_policy: 'insert_zeros' as estypes.AggregationsGapPolicy,
},
},
- numScheduledActions: {
- max: {
- field: NUMBER_OF_SCHEDULED_ACTIONS_FIELD,
+ // Get counts for types of alerts and whether there was an execution timeout
+ alertCounts: {
+ filters: {
+ filters: {
+ newAlerts: { match: { [ACTION_FIELD]: 'new-instance' } },
+ activeAlerts: { match: { [ACTION_FIELD]: 'active-instance' } },
+ recoveredAlerts: { match: { [ACTION_FIELD]: 'recovered-instance' } },
+ },
},
},
- executionDuration: {
- max: {
- field: DURATION_FIELD,
+ // Filter by action execute doc and get information from this event
+ actionExecution: {
+ filter: getProviderAndActionFilter('actions', 'execute'),
+ aggs: {
+ actionOutcomes: {
+ terms: {
+ field: OUTCOME_FIELD,
+ size: 2,
+ },
+ },
},
},
- outcomeAndMessage: {
- top_hits: {
- size: 1,
- _source: {
- includes: [OUTCOME_FIELD, MESSAGE_FIELD, ERROR_MESSAGE_FIELD],
+ // Filter by rule execute doc and get information from this event
+ ruleExecution: {
+ filter: getProviderAndActionFilter('alerting', 'execute'),
+ aggs: {
+ executeStartTime: {
+ min: {
+ field: START_FIELD,
+ },
+ },
+ scheduleDelay: {
+ max: {
+ field: SCHEDULE_DELAY_FIELD,
+ },
+ },
+ totalSearchDuration: {
+ max: {
+ field: TOTAL_SEARCH_DURATION_FIELD,
+ },
+ },
+ esSearchDuration: {
+ max: {
+ field: ES_SEARCH_DURATION_FIELD,
+ },
+ },
+ numTriggeredActions: {
+ max: {
+ field: NUMBER_OF_TRIGGERED_ACTIONS_FIELD,
+ },
+ },
+ numScheduledActions: {
+ max: {
+ field: NUMBER_OF_SCHEDULED_ACTIONS_FIELD,
+ },
+ },
+ executionDuration: {
+ max: {
+ field: DURATION_FIELD,
+ },
+ },
+ outcomeAndMessage: {
+ top_hits: {
+ size: 1,
+ _source: {
+ includes: [OUTCOME_FIELD, MESSAGE_FIELD, ERROR_MESSAGE_FIELD],
+ },
+ },
},
},
},
+ // If there was a timeout, this filter will return non-zero doc count
+ timeoutMessage: {
+ filter: getProviderAndActionFilter('alerting', 'execute-timeout'),
+ },
},
},
- // If there was a timeout, this filter will return non-zero doc count
- timeoutMessage: {
- filter: getProviderAndActionFilter('alerting', 'execute-timeout'),
- },
},
},
};
@@ -280,13 +300,14 @@ export function formatExecutionLogResult(
): IExecutionLogResult {
const { aggregations } = results;
- if (!aggregations) {
+ if (!aggregations || !aggregations.excludeExecuteStart) {
return EMPTY_EXECUTION_LOG_RESULT;
}
- const total = (aggregations.executionUuidCardinality as estypes.AggregationsCardinalityAggregate)
- .value;
- const buckets = (aggregations.executionUuid as ExecutionUuidAggResult).buckets;
+ const aggs = aggregations.excludeExecuteStart as ExcludeExecuteStartAggResult;
+
+ const total = aggs.executionUuidCardinality.value;
+ const buckets = aggs.executionUuid.buckets;
return {
total,
diff --git a/x-pack/plugins/alerting/server/lib/get_alert_notify_when_type.test.ts b/x-pack/plugins/alerting/server/lib/get_rule_notify_when_type.test.ts
similarity index 64%
rename from x-pack/plugins/alerting/server/lib/get_alert_notify_when_type.test.ts
rename to x-pack/plugins/alerting/server/lib/get_rule_notify_when_type.test.ts
index 92e7673c2e48e..747f5a8a8cd21 100644
--- a/x-pack/plugins/alerting/server/lib/get_alert_notify_when_type.test.ts
+++ b/x-pack/plugins/alerting/server/lib/get_rule_notify_when_type.test.ts
@@ -5,20 +5,20 @@
* 2.0.
*/
-import { getAlertNotifyWhenType } from './get_alert_notify_when_type';
+import { getRuleNotifyWhenType } from './get_rule_notify_when_type';
test(`should return 'notifyWhen' value if value is set and throttle is null`, () => {
- expect(getAlertNotifyWhenType('onActionGroupChange', null)).toEqual('onActionGroupChange');
+ expect(getRuleNotifyWhenType('onActionGroupChange', null)).toEqual('onActionGroupChange');
});
test(`should return 'notifyWhen' value if value is set and throttle is defined`, () => {
- expect(getAlertNotifyWhenType('onActionGroupChange', '10m')).toEqual('onActionGroupChange');
+ expect(getRuleNotifyWhenType('onActionGroupChange', '10m')).toEqual('onActionGroupChange');
});
test(`should return 'onThrottleInterval' value if 'notifyWhen' is null and throttle is defined`, () => {
- expect(getAlertNotifyWhenType(null, '10m')).toEqual('onThrottleInterval');
+ expect(getRuleNotifyWhenType(null, '10m')).toEqual('onThrottleInterval');
});
test(`should return 'onActiveAlert' value if 'notifyWhen' is null and throttle is null`, () => {
- expect(getAlertNotifyWhenType(null, null)).toEqual('onActiveAlert');
+ expect(getRuleNotifyWhenType(null, null)).toEqual('onActiveAlert');
});
diff --git a/x-pack/plugins/alerting/server/lib/get_alert_notify_when_type.ts b/x-pack/plugins/alerting/server/lib/get_rule_notify_when_type.ts
similarity index 77%
rename from x-pack/plugins/alerting/server/lib/get_alert_notify_when_type.ts
rename to x-pack/plugins/alerting/server/lib/get_rule_notify_when_type.ts
index a4bb0fe68a25b..53ccacde75e5c 100644
--- a/x-pack/plugins/alerting/server/lib/get_alert_notify_when_type.ts
+++ b/x-pack/plugins/alerting/server/lib/get_rule_notify_when_type.ts
@@ -5,12 +5,12 @@
* 2.0.
*/
-import { AlertNotifyWhenType } from '../types';
+import { RuleNotifyWhenType } from '../types';
-export function getAlertNotifyWhenType(
- notifyWhen: AlertNotifyWhenType | null,
+export function getRuleNotifyWhenType(
+ notifyWhen: RuleNotifyWhenType | null,
throttle: string | null
-): AlertNotifyWhenType {
+): RuleNotifyWhenType {
// We allow notifyWhen to be null for backwards compatibility. If it is null, determine its
// value based on whether the throttle is set to a value or null
return notifyWhen ? notifyWhen! : throttle ? 'onThrottleInterval' : 'onActiveAlert';
diff --git a/x-pack/plugins/alerting/server/lib/index.ts b/x-pack/plugins/alerting/server/lib/index.ts
index 22dbeff82b2d1..57c9a92a8d915 100644
--- a/x-pack/plugins/alerting/server/lib/index.ts
+++ b/x-pack/plugins/alerting/server/lib/index.ts
@@ -9,15 +9,15 @@ export { parseDuration, validateDurationSchema } from '../../common/parse_durati
export type { ILicenseState } from './license_state';
export { LicenseState } from './license_state';
export { validateRuleTypeParams } from './validate_rule_type_params';
-export { getAlertNotifyWhenType } from './get_alert_notify_when_type';
+export { getRuleNotifyWhenType } from './get_rule_notify_when_type';
export { verifyApiAccess } from './license_api_access';
export { ErrorWithReason, getReasonFromError, isErrorWithReason } from './error_with_reason';
export type {
- AlertTypeDisabledReason,
+ RuleTypeDisabledReason,
ErrorThatHandlesItsOwnResponse,
ElasticsearchError,
} from './errors';
-export { AlertTypeDisabledError, RuleMutedError, isErrorThatHandlesItsOwnResponse } from './errors';
+export { RuleTypeDisabledError, RuleMutedError, isErrorThatHandlesItsOwnResponse } from './errors';
export {
executionStatusFromState,
executionStatusFromError,
diff --git a/x-pack/plugins/alerting/server/lib/is_alerting_error.test.ts b/x-pack/plugins/alerting/server/lib/is_alerting_error.test.ts
index 643ca9b3f752b..214b95c5ef50c 100644
--- a/x-pack/plugins/alerting/server/lib/is_alerting_error.test.ts
+++ b/x-pack/plugins/alerting/server/lib/is_alerting_error.test.ts
@@ -9,7 +9,7 @@ import { isAlertSavedObjectNotFoundError, isEsUnavailableError } from './is_aler
import { ErrorWithReason } from './error_with_reason';
import { SavedObjectsErrorHelpers } from '../../../../../src/core/server';
import uuid from 'uuid';
-import { AlertExecutionStatusErrorReasons } from '../types';
+import { RuleExecutionStatusErrorReasons } from '../types';
describe('isAlertSavedObjectNotFoundError', () => {
const id = uuid.v4();
@@ -27,7 +27,7 @@ describe('isAlertSavedObjectNotFoundError', () => {
});
test('identifies SavedObjects Not Found errors wrapped in an ErrorWithReason', () => {
- const error = new ErrorWithReason(AlertExecutionStatusErrorReasons.Read, errorSONF);
+ const error = new ErrorWithReason(RuleExecutionStatusErrorReasons.Read, errorSONF);
expect(isAlertSavedObjectNotFoundError(error, id)).toBe(true);
});
});
@@ -48,7 +48,7 @@ describe('isEsUnavailableError', () => {
});
test('identifies es unavailable errors wrapped in an ErrorWithReason', () => {
- const error = new ErrorWithReason(AlertExecutionStatusErrorReasons.Read, errorSONF);
+ const error = new ErrorWithReason(RuleExecutionStatusErrorReasons.Read, errorSONF);
expect(isEsUnavailableError(error, id)).toBe(true);
});
});
diff --git a/x-pack/plugins/alerting/server/lib/license_state.ts b/x-pack/plugins/alerting/server/lib/license_state.ts
index 162823f8d5850..340d608002fc5 100644
--- a/x-pack/plugins/alerting/server/lib/license_state.ts
+++ b/x-pack/plugins/alerting/server/lib/license_state.ts
@@ -17,12 +17,12 @@ import { PLUGIN } from '../constants/plugin';
import { getRuleTypeFeatureUsageName } from './get_rule_type_feature_usage_name';
import {
RuleType,
- AlertTypeParams,
- AlertTypeState,
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
} from '../types';
-import { AlertTypeDisabledError } from './errors/alert_type_disabled';
+import { RuleTypeDisabledError } from './errors/rule_type_disabled';
export type ILicenseState = PublicMethodsOf;
@@ -148,9 +148,9 @@ export class LicenseState {
}
public ensureLicenseForRuleType<
- Params extends AlertTypeParams,
- ExtractedParams extends AlertTypeParams,
- State extends AlertTypeState,
+ Params extends RuleTypeParams,
+ ExtractedParams extends RuleTypeParams,
+ State extends RuleTypeState,
InstanceState extends AlertInstanceState,
InstanceContext extends AlertInstanceContext,
ActionGroupIds extends string,
@@ -179,7 +179,7 @@ export class LicenseState {
}
switch (check.reason) {
case 'unavailable':
- throw new AlertTypeDisabledError(
+ throw new RuleTypeDisabledError(
i18n.translate('xpack.alerting.serverSideErrors.unavailableLicenseErrorMessage', {
defaultMessage:
'Rule type {ruleTypeId} is disabled because license information is not available at this time.',
@@ -190,7 +190,7 @@ export class LicenseState {
'license_unavailable'
);
case 'expired':
- throw new AlertTypeDisabledError(
+ throw new RuleTypeDisabledError(
i18n.translate('xpack.alerting.serverSideErrors.expirerdLicenseErrorMessage', {
defaultMessage:
'Rule type {ruleTypeId} is disabled because your {licenseType} license has expired.',
@@ -199,7 +199,7 @@ export class LicenseState {
'license_expired'
);
case 'invalid':
- throw new AlertTypeDisabledError(
+ throw new RuleTypeDisabledError(
i18n.translate('xpack.alerting.serverSideErrors.invalidLicenseErrorMessage', {
defaultMessage:
'Rule {ruleTypeId} is disabled because it requires a {licenseType} license. Go to License Management to view upgrade options.',
diff --git a/x-pack/plugins/alerting/server/lib/rule_execution_status.test.ts b/x-pack/plugins/alerting/server/lib/rule_execution_status.test.ts
index 44a9e41c89052..ff43f4ffac8a9 100644
--- a/x-pack/plugins/alerting/server/lib/rule_execution_status.test.ts
+++ b/x-pack/plugins/alerting/server/lib/rule_execution_status.test.ts
@@ -7,8 +7,8 @@
import { loggingSystemMock } from '../../../../../src/core/server/mocks';
import {
- AlertExecutionStatusErrorReasons,
- AlertExecutionStatusWarningReasons,
+ RuleExecutionStatusErrorReasons,
+ RuleExecutionStatusWarningReasons,
RuleExecutionState,
} from '../types';
import {
@@ -115,7 +115,7 @@ describe('RuleExecutionStatus', () => {
checkDateIsNearNow(status.lastExecutionDate);
expect(status.warning).toEqual({
message: translations.taskRunner.warning.maxExecutableActions,
- reason: AlertExecutionStatusWarningReasons.MAX_EXECUTABLE_ACTIONS,
+ reason: RuleExecutionStatusWarningReasons.MAX_EXECUTABLE_ACTIONS,
});
expect(status.status).toBe('warning');
expect(status.error).toBe(undefined);
@@ -136,7 +136,7 @@ describe('RuleExecutionStatus', () => {
test('error with a reason', () => {
const status = executionStatusFromError(
- new ErrorWithReason(AlertExecutionStatusErrorReasons.Execute, new Error('hoo!'))
+ new ErrorWithReason(RuleExecutionStatusErrorReasons.Execute, new Error('hoo!'))
);
expect(status.status).toBe('error');
expect(status.error).toMatchInlineSnapshot(`
@@ -151,7 +151,7 @@ describe('RuleExecutionStatus', () => {
describe('ruleExecutionStatusToRaw()', () => {
const date = new Date('2020-09-03T16:26:58Z');
const status = 'ok';
- const reason = AlertExecutionStatusErrorReasons.Decrypt;
+ const reason = RuleExecutionStatusErrorReasons.Decrypt;
const error = { reason, message: 'wops' };
test('status without an error', () => {
@@ -213,7 +213,7 @@ describe('RuleExecutionStatus', () => {
describe('ruleExecutionStatusFromRaw()', () => {
const date = new Date('2020-09-03T16:26:58Z').toISOString();
const status = 'active';
- const reason = AlertExecutionStatusErrorReasons.Execute;
+ const reason = RuleExecutionStatusErrorReasons.Execute;
const error = { reason, message: 'wops' };
test('no input', () => {
diff --git a/x-pack/plugins/alerting/server/lib/rule_execution_status.ts b/x-pack/plugins/alerting/server/lib/rule_execution_status.ts
index 9a446d2383c66..a87aed321b16b 100644
--- a/x-pack/plugins/alerting/server/lib/rule_execution_status.ts
+++ b/x-pack/plugins/alerting/server/lib/rule_execution_status.ts
@@ -7,29 +7,29 @@
import { Logger } from 'src/core/server';
import {
- AlertExecutionStatus,
- AlertExecutionStatusValues,
- AlertExecutionStatusWarningReasons,
+ RuleExecutionStatus,
+ RuleExecutionStatusValues,
+ RuleExecutionStatusWarningReasons,
RawRuleExecutionStatus,
RuleExecutionState,
} from '../types';
import { getReasonFromError } from './error_with_reason';
import { getEsErrorMessage } from './errors';
-import { AlertExecutionStatuses } from '../../common';
+import { RuleExecutionStatuses } from '../../common';
import { translations } from '../constants/translations';
import { ActionsCompletion } from '../task_runner/types';
-export function executionStatusFromState(state: RuleExecutionState): AlertExecutionStatus {
+export function executionStatusFromState(state: RuleExecutionState): RuleExecutionStatus {
const alertIds = Object.keys(state.alertInstances ?? {});
const hasIncompleteAlertExecution =
state.alertExecutionStore.triggeredActionsStatus === ActionsCompletion.PARTIAL;
- let status: AlertExecutionStatuses =
- alertIds.length === 0 ? AlertExecutionStatusValues[0] : AlertExecutionStatusValues[1];
+ let status: RuleExecutionStatuses =
+ alertIds.length === 0 ? RuleExecutionStatusValues[0] : RuleExecutionStatusValues[1];
if (hasIncompleteAlertExecution) {
- status = AlertExecutionStatusValues[5];
+ status = RuleExecutionStatusValues[5];
}
return {
@@ -40,14 +40,14 @@ export function executionStatusFromState(state: RuleExecutionState): AlertExecut
status,
...(hasIncompleteAlertExecution && {
warning: {
- reason: AlertExecutionStatusWarningReasons.MAX_EXECUTABLE_ACTIONS,
+ reason: RuleExecutionStatusWarningReasons.MAX_EXECUTABLE_ACTIONS,
message: translations.taskRunner.warning.maxExecutableActions,
},
}),
};
}
-export function executionStatusFromError(error: Error): AlertExecutionStatus {
+export function executionStatusFromError(error: Error): RuleExecutionStatus {
return {
lastExecutionDate: new Date(),
status: 'error',
@@ -64,7 +64,7 @@ export function ruleExecutionStatusToRaw({
status,
error,
warning,
-}: AlertExecutionStatus): RawRuleExecutionStatus {
+}: RuleExecutionStatus): RawRuleExecutionStatus {
return {
lastExecutionDate: lastExecutionDate.toISOString(),
lastDuration: lastDuration ?? 0,
@@ -79,7 +79,7 @@ export function ruleExecutionStatusFromRaw(
logger: Logger,
ruleId: string,
rawRuleExecutionStatus?: Partial | null | undefined
-): AlertExecutionStatus | undefined {
+): RuleExecutionStatus | undefined {
if (!rawRuleExecutionStatus) return undefined;
const {
@@ -98,7 +98,7 @@ export function ruleExecutionStatusFromRaw(
parsedDateMillis = Date.now();
}
- const executionStatus: AlertExecutionStatus = {
+ const executionStatus: RuleExecutionStatus = {
status,
lastExecutionDate: new Date(parsedDateMillis),
};
@@ -119,7 +119,7 @@ export function ruleExecutionStatusFromRaw(
}
export const getRuleExecutionStatusPending = (lastExecutionDate: string) => ({
- status: 'pending' as AlertExecutionStatuses,
+ status: 'pending' as RuleExecutionStatuses,
lastExecutionDate,
error: null,
warning: null,
diff --git a/x-pack/plugins/alerting/server/lib/validate_rule_type_params.ts b/x-pack/plugins/alerting/server/lib/validate_rule_type_params.ts
index eef6ecb32c1b1..b791b05499263 100644
--- a/x-pack/plugins/alerting/server/lib/validate_rule_type_params.ts
+++ b/x-pack/plugins/alerting/server/lib/validate_rule_type_params.ts
@@ -6,11 +6,11 @@
*/
import Boom from '@hapi/boom';
-import { AlertTypeParams, AlertTypeParamsValidator } from '../types';
+import { RuleTypeParams, RuleTypeParamsValidator } from '../types';
-export function validateRuleTypeParams(
+export function validateRuleTypeParams(
params: Record,
- validator?: AlertTypeParamsValidator
+ validator?: RuleTypeParamsValidator
): Params {
if (!validator) {
return params as Params;
diff --git a/x-pack/plugins/alerting/server/lib/wrap_scoped_cluster_client.ts b/x-pack/plugins/alerting/server/lib/wrap_scoped_cluster_client.ts
index 69d4817f21a4e..914d6f8c6da30 100644
--- a/x-pack/plugins/alerting/server/lib/wrap_scoped_cluster_client.ts
+++ b/x-pack/plugins/alerting/server/lib/wrap_scoped_cluster_client.ts
@@ -22,7 +22,7 @@ import type {
} from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { IScopedClusterClient, ElasticsearchClient, Logger } from 'src/core/server';
import { RuleExecutionMetrics } from '../types';
-import { Alert as Rule } from '../types';
+import { Rule } from '../types';
type RuleInfo = Pick & { spaceId: string };
interface WrapScopedClusterClientFactoryOpts {
diff --git a/x-pack/plugins/alerting/server/mocks.ts b/x-pack/plugins/alerting/server/mocks.ts
index c952e9182190c..d9951b4a79759 100644
--- a/x-pack/plugins/alerting/server/mocks.ts
+++ b/x-pack/plugins/alerting/server/mocks.ts
@@ -96,7 +96,7 @@ const createAbortableSearchServiceMock = () => {
};
};
-const createAlertServicesMock = <
+const createRuleExecutorServicesMock = <
InstanceState extends AlertInstanceState = AlertInstanceState,
InstanceContext extends AlertInstanceContext = AlertInstanceContext
>() => {
@@ -120,11 +120,11 @@ const createAlertServicesMock = <
),
};
};
-export type AlertServicesMock = ReturnType;
+export type RuleExecutorServicesMock = ReturnType;
export const alertsMock = {
createAlertFactory: createAlertFactoryMock,
createSetup: createSetupMock,
createStart: createStartMock,
- createAlertServices: createAlertServicesMock,
+ createRuleExecutorServices: createRuleExecutorServicesMock,
};
diff --git a/x-pack/plugins/alerting/server/plugin.ts b/x-pack/plugins/alerting/server/plugin.ts
index 47e2450b7a85c..85279ec615331 100644
--- a/x-pack/plugins/alerting/server/plugin.ts
+++ b/x-pack/plugins/alerting/server/plugin.ts
@@ -45,8 +45,8 @@ import {
AlertInstanceState,
AlertsHealth,
RuleType,
- AlertTypeParams,
- AlertTypeState,
+ RuleTypeParams,
+ RuleTypeState,
} from './types';
import { registerAlertingUsageCollector } from './usage';
import { initializeAlertingTelemetry, scheduleAlertingTelemetry } from './usage/task';
@@ -85,9 +85,9 @@ export const LEGACY_EVENT_LOG_ACTIONS = {
export interface PluginSetupContract {
registerType<
- Params extends AlertTypeParams = AlertTypeParams,
- ExtractedParams extends AlertTypeParams = AlertTypeParams,
- State extends AlertTypeState = AlertTypeState,
+ Params extends RuleTypeParams = RuleTypeParams,
+ ExtractedParams extends RuleTypeParams = RuleTypeParams,
+ State extends RuleTypeState = RuleTypeState,
InstanceState extends AlertInstanceState = AlertInstanceState,
InstanceContext extends AlertInstanceContext = AlertInstanceContext,
ActionGroupIds extends string = never,
@@ -287,9 +287,9 @@ export class AlertingPlugin {
return {
registerType: <
- Params extends AlertTypeParams = never,
- ExtractedParams extends AlertTypeParams = never,
- State extends AlertTypeState = never,
+ Params extends RuleTypeParams = never,
+ ExtractedParams extends RuleTypeParams = never,
+ State extends RuleTypeState = never,
InstanceState extends AlertInstanceState = never,
InstanceContext extends AlertInstanceContext = never,
ActionGroupIds extends string = never,
diff --git a/x-pack/plugins/alerting/server/routes/create_rule.test.ts b/x-pack/plugins/alerting/server/routes/create_rule.test.ts
index c878d8da218b1..62c7819fb5b05 100644
--- a/x-pack/plugins/alerting/server/routes/create_rule.test.ts
+++ b/x-pack/plugins/alerting/server/routes/create_rule.test.ts
@@ -13,9 +13,9 @@ import { verifyApiAccess } from '../lib/license_api_access';
import { mockHandlerArguments } from './_mock_handler_arguments';
import { CreateOptions } from '../rules_client';
import { rulesClientMock } from '../rules_client.mock';
-import { AlertTypeDisabledError } from '../lib';
+import { RuleTypeDisabledError } from '../lib';
import { AsApiContract } from './lib';
-import { SanitizedAlert } from '../types';
+import { SanitizedRule } from '../types';
import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/mocks';
import { usageCountersServiceMock } from 'src/plugins/usage_collection/server/usage_counters/usage_counters_service.mock';
@@ -33,7 +33,7 @@ describe('createRuleRoute', () => {
const createdAt = new Date();
const updatedAt = new Date();
- const mockedAlert: SanitizedAlert<{ bar: boolean }> = {
+ const mockedAlert: SanitizedRule<{ bar: boolean }> = {
alertTypeId: '1',
consumer: 'bar',
name: 'abc',
@@ -82,7 +82,7 @@ describe('createRuleRoute', () => {
],
};
- const createResult: AsApiContract> = {
+ const createResult: AsApiContract> = {
...ruleToCreate,
mute_all: mockedAlert.muteAll,
created_by: mockedAlert.createdBy,
@@ -471,7 +471,7 @@ describe('createRuleRoute', () => {
const [, handler] = router.post.mock.calls[0];
- rulesClient.create.mockRejectedValue(new AlertTypeDisabledError('Fail', 'license_invalid'));
+ rulesClient.create.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
const [context, req, res] = mockHandlerArguments({ rulesClient }, { body: ruleToCreate }, [
'ok',
diff --git a/x-pack/plugins/alerting/server/routes/create_rule.ts b/x-pack/plugins/alerting/server/routes/create_rule.ts
index ed124bfbd3a2d..5278f748f0ce4 100644
--- a/x-pack/plugins/alerting/server/routes/create_rule.ts
+++ b/x-pack/plugins/alerting/server/routes/create_rule.ts
@@ -6,7 +6,7 @@
*/
import { schema } from '@kbn/config-schema';
-import { validateDurationSchema, AlertTypeDisabledError } from '../lib';
+import { validateDurationSchema, RuleTypeDisabledError } from '../lib';
import { CreateOptions } from '../rules_client';
import {
RewriteRequestCase,
@@ -16,11 +16,11 @@ import {
countUsageOfPredefinedIds,
} from './lib';
import {
- SanitizedAlert,
+ SanitizedRule,
validateNotifyWhenType,
- AlertTypeParams,
+ RuleTypeParams,
BASE_ALERTING_API_PATH,
- AlertNotifyWhenType,
+ RuleNotifyWhenType,
} from '../types';
import { RouteOptions } from '.';
@@ -46,7 +46,7 @@ export const bodySchema = schema.object({
notify_when: schema.string({ validate: validateNotifyWhenType }),
});
-const rewriteBodyReq: RewriteRequestCase['data']> = ({
+const rewriteBodyReq: RewriteRequestCase['data']> = ({
rule_type_id: alertTypeId,
notify_when: notifyWhen,
...rest
@@ -55,7 +55,7 @@ const rewriteBodyReq: RewriteRequestCase['data']>
alertTypeId,
notifyWhen,
});
-const rewriteBodyRes: RewriteResponseCase> = ({
+const rewriteBodyRes: RewriteResponseCase> = ({
actions,
alertTypeId,
scheduledTaskId,
@@ -121,11 +121,11 @@ export const createRuleRoute = ({ router, licenseState, usageCounter }: RouteOpt
});
try {
- const createdRule: SanitizedAlert =
- await rulesClient.create({
+ const createdRule: SanitizedRule =
+ await rulesClient.create({
data: rewriteBodyReq({
...rule,
- notify_when: rule.notify_when as AlertNotifyWhenType,
+ notify_when: rule.notify_when as RuleNotifyWhenType,
}),
options: { id: params?.id },
});
@@ -133,7 +133,7 @@ export const createRuleRoute = ({ router, licenseState, usageCounter }: RouteOpt
body: rewriteBodyRes(createdRule),
});
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/disable_rule.test.ts b/x-pack/plugins/alerting/server/routes/disable_rule.test.ts
index 173f1df7e1e73..baecc8f198fff 100644
--- a/x-pack/plugins/alerting/server/routes/disable_rule.test.ts
+++ b/x-pack/plugins/alerting/server/routes/disable_rule.test.ts
@@ -10,7 +10,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../lib/license_state.mock';
import { mockHandlerArguments } from './_mock_handler_arguments';
import { rulesClientMock } from '../rules_client.mock';
-import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled';
const rulesClient = rulesClientMock.create();
@@ -67,7 +67,7 @@ describe('disableRuleRoute', () => {
const [, handler] = router.post.mock.calls[0];
- rulesClient.disable.mockRejectedValue(new AlertTypeDisabledError('Fail', 'license_invalid'));
+ rulesClient.disable.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
'ok',
diff --git a/x-pack/plugins/alerting/server/routes/disable_rule.ts b/x-pack/plugins/alerting/server/routes/disable_rule.ts
index 81f77cb130d50..74bf9d11166be 100644
--- a/x-pack/plugins/alerting/server/routes/disable_rule.ts
+++ b/x-pack/plugins/alerting/server/routes/disable_rule.ts
@@ -7,7 +7,7 @@
import { IRouter } from 'kibana/server';
import { schema } from '@kbn/config-schema';
-import { ILicenseState, AlertTypeDisabledError } from '../lib';
+import { ILicenseState, RuleTypeDisabledError } from '../lib';
import { verifyAccessAndContext } from './lib';
import { AlertingRequestHandlerContext, BASE_ALERTING_API_PATH } from '../types';
@@ -34,7 +34,7 @@ export const disableRuleRoute = (
await rulesClient.disable({ id });
return res.noContent();
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/enable_rule.test.ts b/x-pack/plugins/alerting/server/routes/enable_rule.test.ts
index 4c0bae2587924..9a8b3fe1b4226 100644
--- a/x-pack/plugins/alerting/server/routes/enable_rule.test.ts
+++ b/x-pack/plugins/alerting/server/routes/enable_rule.test.ts
@@ -10,7 +10,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../lib/license_state.mock';
import { mockHandlerArguments } from './_mock_handler_arguments';
import { rulesClientMock } from '../rules_client.mock';
-import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled';
const rulesClient = rulesClientMock.create();
@@ -67,7 +67,7 @@ describe('enableRuleRoute', () => {
const [, handler] = router.post.mock.calls[0];
- rulesClient.enable.mockRejectedValue(new AlertTypeDisabledError('Fail', 'license_invalid'));
+ rulesClient.enable.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
'ok',
diff --git a/x-pack/plugins/alerting/server/routes/enable_rule.ts b/x-pack/plugins/alerting/server/routes/enable_rule.ts
index 5d77e375cfce6..e62e6aa30221f 100644
--- a/x-pack/plugins/alerting/server/routes/enable_rule.ts
+++ b/x-pack/plugins/alerting/server/routes/enable_rule.ts
@@ -7,7 +7,7 @@
import { IRouter } from 'kibana/server';
import { schema } from '@kbn/config-schema';
-import { ILicenseState, AlertTypeDisabledError } from '../lib';
+import { ILicenseState, RuleTypeDisabledError } from '../lib';
import { verifyAccessAndContext } from './lib';
import { AlertingRequestHandlerContext, BASE_ALERTING_API_PATH } from '../types';
@@ -34,7 +34,7 @@ export const enableRuleRoute = (
await rulesClient.enable({ id });
return res.noContent();
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/find_rules.ts b/x-pack/plugins/alerting/server/routes/find_rules.ts
index 1202d56edb21c..7d7f878780ac3 100644
--- a/x-pack/plugins/alerting/server/routes/find_rules.ts
+++ b/x-pack/plugins/alerting/server/routes/find_rules.ts
@@ -13,7 +13,7 @@ import { ILicenseState } from '../lib';
import { FindOptions, FindResult } from '../rules_client';
import { RewriteRequestCase, RewriteResponseCase, verifyAccessAndContext } from './lib';
import {
- AlertTypeParams,
+ RuleTypeParams,
AlertingRequestHandlerContext,
BASE_ALERTING_API_PATH,
INTERNAL_BASE_ALERTING_API_PATH,
@@ -62,7 +62,7 @@ const rewriteQueryReq: RewriteRequestCase = ({
...(hasReference ? { hasReference } : {}),
...(searchFields ? { searchFields } : {}),
});
-const rewriteBodyRes: RewriteResponseCase> = ({
+const rewriteBodyRes: RewriteResponseCase> = ({
perPage,
data,
...restOfResult
diff --git a/x-pack/plugins/alerting/server/routes/get_rule.test.ts b/x-pack/plugins/alerting/server/routes/get_rule.test.ts
index 47503374394f8..4384e02352d95 100644
--- a/x-pack/plugins/alerting/server/routes/get_rule.test.ts
+++ b/x-pack/plugins/alerting/server/routes/get_rule.test.ts
@@ -12,7 +12,7 @@ import { licenseStateMock } from '../lib/license_state.mock';
import { verifyApiAccess } from '../lib/license_api_access';
import { mockHandlerArguments } from './_mock_handler_arguments';
import { rulesClientMock } from '../rules_client.mock';
-import { SanitizedAlert } from '../types';
+import { SanitizedRule } from '../types';
import { AsApiContract } from './lib';
const rulesClient = rulesClientMock.create();
@@ -25,7 +25,7 @@ beforeEach(() => {
});
describe('getRuleRoute', () => {
- const mockedAlert: SanitizedAlert<{
+ const mockedAlert: SanitizedRule<{
bar: boolean;
}> = {
id: '1',
@@ -63,7 +63,7 @@ describe('getRuleRoute', () => {
},
};
- const getResult: AsApiContract> = {
+ const getResult: AsApiContract> = {
...pick(mockedAlert, 'consumer', 'name', 'schedule', 'tags', 'params', 'throttle', 'enabled'),
rule_type_id: mockedAlert.alertTypeId,
notify_when: mockedAlert.notifyWhen,
diff --git a/x-pack/plugins/alerting/server/routes/get_rule.ts b/x-pack/plugins/alerting/server/routes/get_rule.ts
index 8e0e89c379fcc..52b73d22680f9 100644
--- a/x-pack/plugins/alerting/server/routes/get_rule.ts
+++ b/x-pack/plugins/alerting/server/routes/get_rule.ts
@@ -11,18 +11,18 @@ import { IRouter } from 'kibana/server';
import { ILicenseState } from '../lib';
import { verifyAccessAndContext, RewriteResponseCase } from './lib';
import {
- AlertTypeParams,
+ RuleTypeParams,
AlertingRequestHandlerContext,
BASE_ALERTING_API_PATH,
INTERNAL_BASE_ALERTING_API_PATH,
- SanitizedAlert,
+ SanitizedRule,
} from '../types';
const paramSchema = schema.object({
id: schema.string(),
});
-const rewriteBodyRes: RewriteResponseCase> = ({
+const rewriteBodyRes: RewriteResponseCase> = ({
alertTypeId,
createdBy,
updatedBy,
diff --git a/x-pack/plugins/alerting/server/routes/get_rule_execution_log.test.ts b/x-pack/plugins/alerting/server/routes/get_rule_execution_log.test.ts
index f304c7be86131..2394e159a9f19 100644
--- a/x-pack/plugins/alerting/server/routes/get_rule_execution_log.test.ts
+++ b/x-pack/plugins/alerting/server/routes/get_rule_execution_log.test.ts
@@ -11,7 +11,7 @@ import { licenseStateMock } from '../lib/license_state.mock';
import { mockHandlerArguments } from './_mock_handler_arguments';
import { SavedObjectsErrorHelpers } from 'src/core/server';
import { rulesClientMock } from '../rules_client.mock';
-import { IExecutionLogWithErrorsResult } from '../rules_client';
+import { IExecutionLogWithErrorsResult } from '../../common';
const rulesClient = rulesClientMock.create();
jest.mock('../lib/license_api_access.ts', () => ({
diff --git a/x-pack/plugins/alerting/server/routes/legacy/create.test.ts b/x-pack/plugins/alerting/server/routes/legacy/create.test.ts
index cfbef73ea58db..cd584543d57e0 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/create.test.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/create.test.ts
@@ -12,8 +12,8 @@ import { licenseStateMock } from '../../lib/license_state.mock';
import { verifyApiAccess } from '../../lib/license_api_access';
import { mockHandlerArguments } from './../_mock_handler_arguments';
import { rulesClientMock } from '../../rules_client.mock';
-import { Alert } from '../../../common/alert';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { Rule } from '../../../common/rule';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { encryptedSavedObjectsMock } from '../../../../encrypted_saved_objects/server/mocks';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
@@ -57,7 +57,7 @@ describe('createAlertRoute', () => {
],
};
- const createResult: Alert<{ bar: boolean }> = {
+ const createResult: Rule<{ bar: boolean }> = {
...mockedAlert,
enabled: true,
muteAll: false,
@@ -436,7 +436,7 @@ describe('createAlertRoute', () => {
const [, handler] = router.post.mock.calls[0];
- rulesClient.create.mockRejectedValue(new AlertTypeDisabledError('Fail', 'license_invalid'));
+ rulesClient.create.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
const [context, req, res] = mockHandlerArguments({ rulesClient }, {}, ['ok', 'forbidden']);
diff --git a/x-pack/plugins/alerting/server/routes/legacy/create.ts b/x-pack/plugins/alerting/server/routes/legacy/create.ts
index 8deeb733fd3b5..b6669a605022d 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/create.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/create.ts
@@ -10,13 +10,13 @@ import { verifyApiAccess } from '../../lib/license_api_access';
import { validateDurationSchema } from '../../lib';
import { handleDisabledApiKeysError } from './../lib/error_handler';
import {
- SanitizedAlert,
- AlertNotifyWhenType,
- AlertTypeParams,
+ SanitizedRule,
+ RuleNotifyWhenType,
+ RuleTypeParams,
LEGACY_BASE_ALERT_API_PATH,
validateNotifyWhenType,
} from '../../types';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { RouteOptions } from '..';
import { countUsageOfPredefinedIds } from '../lib';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
@@ -67,7 +67,7 @@ export const createAlertRoute = ({ router, licenseState, usageCounter }: RouteOp
const rulesClient = context.alerting.getRulesClient();
const alert = req.body;
const params = req.params;
- const notifyWhen = alert?.notifyWhen ? (alert.notifyWhen as AlertNotifyWhenType) : null;
+ const notifyWhen = alert?.notifyWhen ? (alert.notifyWhen as RuleNotifyWhenType) : null;
trackLegacyRouteUsage('create', usageCounter);
@@ -78,16 +78,15 @@ export const createAlertRoute = ({ router, licenseState, usageCounter }: RouteOp
});
try {
- const alertRes: SanitizedAlert =
- await rulesClient.create({
- data: { ...alert, notifyWhen },
- options: { id: params?.id },
- });
+ const alertRes: SanitizedRule = await rulesClient.create({
+ data: { ...alert, notifyWhen },
+ options: { id: params?.id },
+ });
return res.ok({
body: alertRes,
});
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/legacy/disable.test.ts b/x-pack/plugins/alerting/server/routes/legacy/disable.test.ts
index ac44ab37761bc..1e9f5531d19d2 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/disable.test.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/disable.test.ts
@@ -10,7 +10,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../../lib/license_state.mock';
import { mockHandlerArguments } from './../_mock_handler_arguments';
import { rulesClientMock } from '../../rules_client.mock';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const rulesClient = rulesClientMock.create();
@@ -72,7 +72,7 @@ describe('disableAlertRoute', () => {
const [, handler] = router.post.mock.calls[0];
- rulesClient.disable.mockRejectedValue(new AlertTypeDisabledError('Fail', 'license_invalid'));
+ rulesClient.disable.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
'ok',
diff --git a/x-pack/plugins/alerting/server/routes/legacy/disable.ts b/x-pack/plugins/alerting/server/routes/legacy/disable.ts
index 1cba654e11a51..1345c4ae4428a 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/disable.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/disable.ts
@@ -11,7 +11,7 @@ import type { AlertingRouter } from '../../types';
import { ILicenseState } from '../../lib/license_state';
import { verifyApiAccess } from '../../lib/license_api_access';
import { LEGACY_BASE_ALERT_API_PATH } from '../../../common';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const paramSchema = schema.object({
@@ -42,7 +42,7 @@ export const disableAlertRoute = (
await rulesClient.disable({ id });
return res.noContent();
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/legacy/enable.test.ts b/x-pack/plugins/alerting/server/routes/legacy/enable.test.ts
index c35fb191fae6f..eb839ba3e7b83 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/enable.test.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/enable.test.ts
@@ -10,7 +10,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../../lib/license_state.mock';
import { mockHandlerArguments } from './../_mock_handler_arguments';
import { rulesClientMock } from '../../rules_client.mock';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const rulesClient = rulesClientMock.create();
@@ -72,7 +72,7 @@ describe('enableAlertRoute', () => {
const [, handler] = router.post.mock.calls[0];
- rulesClient.enable.mockRejectedValue(new AlertTypeDisabledError('Fail', 'license_invalid'));
+ rulesClient.enable.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
'ok',
diff --git a/x-pack/plugins/alerting/server/routes/legacy/enable.ts b/x-pack/plugins/alerting/server/routes/legacy/enable.ts
index 000d165ff169d..ec3b4b0a0fc20 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/enable.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/enable.ts
@@ -12,7 +12,7 @@ import { ILicenseState } from '../../lib/license_state';
import { verifyApiAccess } from '../../lib/license_api_access';
import { LEGACY_BASE_ALERT_API_PATH } from '../../../common';
import { handleDisabledApiKeysError } from './../lib/error_handler';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const paramSchema = schema.object({
@@ -44,7 +44,7 @@ export const enableAlertRoute = (
await rulesClient.enable({ id });
return res.noContent();
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/legacy/get.test.ts b/x-pack/plugins/alerting/server/routes/legacy/get.test.ts
index 40c7b224c7150..8c2233ae280b7 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/get.test.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/get.test.ts
@@ -12,7 +12,7 @@ import { licenseStateMock } from '../../lib/license_state.mock';
import { verifyApiAccess } from '../../lib/license_api_access';
import { mockHandlerArguments } from './../_mock_handler_arguments';
import { rulesClientMock } from '../../rules_client.mock';
-import { Alert } from '../../../common';
+import { Rule } from '../../../common';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const rulesClient = rulesClientMock.create();
@@ -29,7 +29,7 @@ beforeEach(() => {
});
describe('getAlertRoute', () => {
- const mockedAlert: Alert<{
+ const mockedAlert: Rule<{
bar: true;
}> = {
id: '1',
diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_all.test.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_all.test.ts
index 131b5ed7960bd..9d84fd75a68c5 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/mute_all.test.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/mute_all.test.ts
@@ -11,7 +11,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../../lib/license_state.mock';
import { mockHandlerArguments } from './../_mock_handler_arguments';
import { rulesClientMock } from '../../rules_client.mock';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const rulesClient = rulesClientMock.create();
@@ -72,7 +72,7 @@ describe('muteAllAlertRoute', () => {
const [, handler] = router.post.mock.calls[0];
- rulesClient.muteAll.mockRejectedValue(new AlertTypeDisabledError('Fail', 'license_invalid'));
+ rulesClient.muteAll.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
'ok',
diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts
index 222abc806ede2..f35ffe93ccda4 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts
@@ -11,7 +11,7 @@ import type { AlertingRouter } from '../../types';
import { ILicenseState } from '../../lib/license_state';
import { verifyApiAccess } from '../../lib/license_api_access';
import { LEGACY_BASE_ALERT_API_PATH } from '../../../common';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const paramSchema = schema.object({
@@ -42,7 +42,7 @@ export const muteAllAlertRoute = (
await rulesClient.muteAll({ id });
return res.noContent();
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.test.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_instance.test.ts
index 19ce9e1d2b107..5e17c42528e14 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.test.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/mute_instance.test.ts
@@ -11,7 +11,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../../lib/license_state.mock';
import { mockHandlerArguments } from './../_mock_handler_arguments';
import { rulesClientMock } from '../../rules_client.mock';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const rulesClient = rulesClientMock.create();
@@ -77,7 +77,7 @@ describe('muteAlertInstanceRoute', () => {
const [, handler] = router.post.mock.calls[0];
rulesClient.muteInstance.mockRejectedValue(
- new AlertTypeDisabledError('Fail', 'license_invalid')
+ new RuleTypeDisabledError('Fail', 'license_invalid')
);
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts
index be1c0876d5d2e..af6aea1e0f6c7 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts
@@ -13,7 +13,7 @@ import { verifyApiAccess } from '../../lib/license_api_access';
import { LEGACY_BASE_ALERT_API_PATH } from '../../../common';
import { renameKeys } from './../lib/rename_keys';
import { MuteOptions } from '../../rules_client';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const paramSchema = schema.object({
@@ -53,7 +53,7 @@ export const muteAlertInstanceRoute = (
await rulesClient.muteInstance(renamedQuery);
return res.noContent();
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.test.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_all.test.ts
index 8259d2305b941..f3530786667ff 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.test.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/unmute_all.test.ts
@@ -11,7 +11,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../../lib/license_state.mock';
import { mockHandlerArguments } from './../_mock_handler_arguments';
import { rulesClientMock } from '../../rules_client.mock';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const rulesClient = rulesClientMock.create();
@@ -72,7 +72,7 @@ describe('unmuteAllAlertRoute', () => {
const [, handler] = router.post.mock.calls[0];
- rulesClient.unmuteAll.mockRejectedValue(new AlertTypeDisabledError('Fail', 'license_invalid'));
+ rulesClient.unmuteAll.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
'ok',
diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts
index 40c303e5d7633..a6cd687271cc4 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts
@@ -11,7 +11,7 @@ import type { AlertingRouter } from '../../types';
import { ILicenseState } from '../../lib/license_state';
import { verifyApiAccess } from '../../lib/license_api_access';
import { LEGACY_BASE_ALERT_API_PATH } from '../../../common';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const paramSchema = schema.object({
@@ -42,7 +42,7 @@ export const unmuteAllAlertRoute = (
await rulesClient.unmuteAll({ id });
return res.noContent();
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.test.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.test.ts
index bbe61d715a525..fa109fa09f250 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.test.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.test.ts
@@ -11,7 +11,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../../lib/license_state.mock';
import { mockHandlerArguments } from './../_mock_handler_arguments';
import { rulesClientMock } from '../../rules_client.mock';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const rulesClient = rulesClientMock.create();
@@ -77,7 +77,7 @@ describe('unmuteAlertInstanceRoute', () => {
const [, handler] = router.post.mock.calls[0];
rulesClient.unmuteInstance.mockRejectedValue(
- new AlertTypeDisabledError('Fail', 'license_invalid')
+ new RuleTypeDisabledError('Fail', 'license_invalid')
);
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts
index 1c65af9961adc..d4684bda7f0fa 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts
@@ -11,7 +11,7 @@ import type { AlertingRouter } from '../../types';
import { ILicenseState } from '../../lib/license_state';
import { verifyApiAccess } from '../../lib/license_api_access';
import { LEGACY_BASE_ALERT_API_PATH } from '../../../common';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const paramSchema = schema.object({
@@ -43,7 +43,7 @@ export const unmuteAlertInstanceRoute = (
await rulesClient.unmuteInstance({ alertId, alertInstanceId });
return res.noContent();
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/legacy/update.test.ts b/x-pack/plugins/alerting/server/routes/legacy/update.test.ts
index 799672c3cf432..5396e267fa525 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/update.test.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/update.test.ts
@@ -12,8 +12,8 @@ import { licenseStateMock } from '../../lib/license_state.mock';
import { verifyApiAccess } from '../../lib/license_api_access';
import { mockHandlerArguments } from './../_mock_handler_arguments';
import { rulesClientMock } from '../../rules_client.mock';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
-import { AlertNotifyWhenType } from '../../../common';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
+import { RuleNotifyWhenType } from '../../../common';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const rulesClient = rulesClientMock.create();
@@ -50,7 +50,7 @@ describe('updateAlertRoute', () => {
},
},
],
- notifyWhen: 'onActionGroupChange' as AlertNotifyWhenType,
+ notifyWhen: 'onActionGroupChange' as RuleNotifyWhenType,
};
it('updates an alert with proper parameters', async () => {
@@ -229,7 +229,7 @@ describe('updateAlertRoute', () => {
const [, handler] = router.put.mock.calls[0];
- rulesClient.update.mockRejectedValue(new AlertTypeDisabledError('Fail', 'license_invalid'));
+ rulesClient.update.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
'ok',
diff --git a/x-pack/plugins/alerting/server/routes/legacy/update.ts b/x-pack/plugins/alerting/server/routes/legacy/update.ts
index d6e6a2b3c4ae8..b740be04829e8 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/update.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/update.ts
@@ -12,10 +12,10 @@ import { ILicenseState } from '../../lib/license_state';
import { verifyApiAccess } from '../../lib/license_api_access';
import { validateDurationSchema } from '../../lib';
import { handleDisabledApiKeysError } from './../lib/error_handler';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
import {
- AlertNotifyWhenType,
+ RuleNotifyWhenType,
LEGACY_BASE_ALERT_API_PATH,
validateNotifyWhenType,
} from '../../../common';
@@ -77,14 +77,14 @@ export const updateAlertRoute = (
schedule,
tags,
throttle,
- notifyWhen: notifyWhen as AlertNotifyWhenType,
+ notifyWhen: notifyWhen as RuleNotifyWhenType,
},
});
return res.ok({
body: alertRes,
});
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.test.ts b/x-pack/plugins/alerting/server/routes/legacy/update_api_key.test.ts
index 7c48f5fff357d..5ae3ec2f5387f 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.test.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/update_api_key.test.ts
@@ -11,7 +11,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../../lib/license_state.mock';
import { mockHandlerArguments } from './../_mock_handler_arguments';
import { rulesClientMock } from '../../rules_client.mock';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const rulesClient = rulesClientMock.create();
@@ -73,7 +73,7 @@ describe('updateApiKeyRoute', () => {
const [, handler] = router.post.mock.calls[0];
rulesClient.updateApiKey.mockRejectedValue(
- new AlertTypeDisabledError('Fail', 'license_invalid')
+ new RuleTypeDisabledError('Fail', 'license_invalid')
);
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
diff --git a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts b/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts
index a45767851c5c1..ab5ff254fca86 100644
--- a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts
+++ b/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts
@@ -12,7 +12,7 @@ import { ILicenseState } from '../../lib/license_state';
import { verifyApiAccess } from '../../lib/license_api_access';
import { LEGACY_BASE_ALERT_API_PATH } from '../../../common';
import { handleDisabledApiKeysError } from './../lib/error_handler';
-import { AlertTypeDisabledError } from '../../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled';
import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage';
const paramSchema = schema.object({
@@ -44,7 +44,7 @@ export const updateApiKeyRoute = (
await rulesClient.updateApiKey({ id });
return res.noContent();
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/mute_alert.test.ts b/x-pack/plugins/alerting/server/routes/mute_alert.test.ts
index 284a89ea8a677..0fc28412abc6f 100644
--- a/x-pack/plugins/alerting/server/routes/mute_alert.test.ts
+++ b/x-pack/plugins/alerting/server/routes/mute_alert.test.ts
@@ -10,7 +10,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../lib/license_state.mock';
import { mockHandlerArguments } from './_mock_handler_arguments';
import { rulesClientMock } from '../rules_client.mock';
-import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled';
const rulesClient = rulesClientMock.create();
jest.mock('../lib/license_api_access.ts', () => ({
@@ -71,7 +71,7 @@ describe('muteAlertRoute', () => {
const [, handler] = router.post.mock.calls[0];
rulesClient.muteInstance.mockRejectedValue(
- new AlertTypeDisabledError('Fail', 'license_invalid')
+ new RuleTypeDisabledError('Fail', 'license_invalid')
);
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
diff --git a/x-pack/plugins/alerting/server/routes/mute_alert.ts b/x-pack/plugins/alerting/server/routes/mute_alert.ts
index 301d04f362313..67e6f3b4002d7 100644
--- a/x-pack/plugins/alerting/server/routes/mute_alert.ts
+++ b/x-pack/plugins/alerting/server/routes/mute_alert.ts
@@ -7,7 +7,7 @@
import { IRouter } from 'kibana/server';
import { schema } from '@kbn/config-schema';
-import { ILicenseState, AlertTypeDisabledError } from '../lib';
+import { ILicenseState, RuleTypeDisabledError } from '../lib';
import { MuteOptions } from '../rules_client';
import { RewriteRequestCase, verifyAccessAndContext } from './lib';
import { AlertingRequestHandlerContext, BASE_ALERTING_API_PATH } from '../types';
@@ -44,7 +44,7 @@ export const muteAlertRoute = (
await rulesClient.muteInstance(params);
return res.noContent();
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/mute_all_rule.test.ts b/x-pack/plugins/alerting/server/routes/mute_all_rule.test.ts
index 56e46db082514..277add6ec1647 100644
--- a/x-pack/plugins/alerting/server/routes/mute_all_rule.test.ts
+++ b/x-pack/plugins/alerting/server/routes/mute_all_rule.test.ts
@@ -10,7 +10,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../lib/license_state.mock';
import { mockHandlerArguments } from './_mock_handler_arguments';
import { rulesClientMock } from '../rules_client.mock';
-import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled';
const rulesClient = rulesClientMock.create();
jest.mock('../lib/license_api_access.ts', () => ({
@@ -66,7 +66,7 @@ describe('muteAllRuleRoute', () => {
const [, handler] = router.post.mock.calls[0];
- rulesClient.muteAll.mockRejectedValue(new AlertTypeDisabledError('Fail', 'license_invalid'));
+ rulesClient.muteAll.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
'ok',
diff --git a/x-pack/plugins/alerting/server/routes/mute_all_rule.ts b/x-pack/plugins/alerting/server/routes/mute_all_rule.ts
index f6d3870ef6744..ad3c93f415ea2 100644
--- a/x-pack/plugins/alerting/server/routes/mute_all_rule.ts
+++ b/x-pack/plugins/alerting/server/routes/mute_all_rule.ts
@@ -7,7 +7,7 @@
import { IRouter } from 'kibana/server';
import { schema } from '@kbn/config-schema';
-import { ILicenseState, AlertTypeDisabledError } from '../lib';
+import { ILicenseState, RuleTypeDisabledError } from '../lib';
import { verifyAccessAndContext } from './lib';
import { AlertingRequestHandlerContext, BASE_ALERTING_API_PATH } from '../types';
@@ -34,7 +34,7 @@ export const muteAllRuleRoute = (
await rulesClient.muteAll({ id });
return res.noContent();
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/resolve_rule.ts b/x-pack/plugins/alerting/server/routes/resolve_rule.ts
index a31cf5059b99f..e6cacb8231b5f 100644
--- a/x-pack/plugins/alerting/server/routes/resolve_rule.ts
+++ b/x-pack/plugins/alerting/server/routes/resolve_rule.ts
@@ -11,7 +11,7 @@ import { IRouter } from 'kibana/server';
import { ILicenseState } from '../lib';
import { verifyAccessAndContext, RewriteResponseCase } from './lib';
import {
- AlertTypeParams,
+ RuleTypeParams,
AlertingRequestHandlerContext,
INTERNAL_BASE_ALERTING_API_PATH,
ResolvedSanitizedRule,
@@ -21,7 +21,7 @@ const paramSchema = schema.object({
id: schema.string(),
});
-const rewriteBodyRes: RewriteResponseCase> = ({
+const rewriteBodyRes: RewriteResponseCase> = ({
alertTypeId,
createdBy,
updatedBy,
diff --git a/x-pack/plugins/alerting/server/routes/snooze_rule.test.ts b/x-pack/plugins/alerting/server/routes/snooze_rule.test.ts
index dbcce10cc8e3e..f7e83301385ad 100644
--- a/x-pack/plugins/alerting/server/routes/snooze_rule.test.ts
+++ b/x-pack/plugins/alerting/server/routes/snooze_rule.test.ts
@@ -10,7 +10,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../lib/license_state.mock';
import { mockHandlerArguments } from './_mock_handler_arguments';
import { rulesClientMock } from '../rules_client.mock';
-import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled';
const rulesClient = rulesClientMock.create();
jest.mock('../lib/license_api_access.ts', () => ({
@@ -113,7 +113,7 @@ describe('snoozeAlertRoute', () => {
const [, handler] = router.post.mock.calls[0];
- rulesClient.snooze.mockRejectedValue(new AlertTypeDisabledError('Fail', 'license_invalid'));
+ rulesClient.snooze.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
'ok',
diff --git a/x-pack/plugins/alerting/server/routes/unmute_alert.test.ts b/x-pack/plugins/alerting/server/routes/unmute_alert.test.ts
index 09c0033542dbb..bfc281cb16b2f 100644
--- a/x-pack/plugins/alerting/server/routes/unmute_alert.test.ts
+++ b/x-pack/plugins/alerting/server/routes/unmute_alert.test.ts
@@ -10,7 +10,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../lib/license_state.mock';
import { mockHandlerArguments } from './_mock_handler_arguments';
import { rulesClientMock } from '../rules_client.mock';
-import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled';
const rulesClient = rulesClientMock.create();
jest.mock('../lib/license_api_access.ts', () => ({
@@ -71,7 +71,7 @@ describe('unmuteAlertRoute', () => {
const [, handler] = router.post.mock.calls[0];
rulesClient.unmuteInstance.mockRejectedValue(
- new AlertTypeDisabledError('Fail', 'license_invalid')
+ new RuleTypeDisabledError('Fail', 'license_invalid')
);
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
diff --git a/x-pack/plugins/alerting/server/routes/unmute_alert.ts b/x-pack/plugins/alerting/server/routes/unmute_alert.ts
index 58c3f59b836b1..0269f53fa8827 100644
--- a/x-pack/plugins/alerting/server/routes/unmute_alert.ts
+++ b/x-pack/plugins/alerting/server/routes/unmute_alert.ts
@@ -7,7 +7,7 @@
import { IRouter } from 'kibana/server';
import { schema } from '@kbn/config-schema';
-import { ILicenseState, AlertTypeDisabledError } from '../lib';
+import { ILicenseState, RuleTypeDisabledError } from '../lib';
import { MuteOptions } from '../rules_client';
import { RewriteRequestCase, verifyAccessAndContext } from './lib';
import { AlertingRequestHandlerContext, BASE_ALERTING_API_PATH } from '../types';
@@ -44,7 +44,7 @@ export const unmuteAlertRoute = (
await rulesClient.unmuteInstance(params);
return res.noContent();
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/unmute_all_rule.test.ts b/x-pack/plugins/alerting/server/routes/unmute_all_rule.test.ts
index 0f031c2d8cc80..ff97819506276 100644
--- a/x-pack/plugins/alerting/server/routes/unmute_all_rule.test.ts
+++ b/x-pack/plugins/alerting/server/routes/unmute_all_rule.test.ts
@@ -10,7 +10,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../lib/license_state.mock';
import { mockHandlerArguments } from './_mock_handler_arguments';
import { rulesClientMock } from '../rules_client.mock';
-import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled';
const rulesClient = rulesClientMock.create();
jest.mock('../lib/license_api_access.ts', () => ({
@@ -66,7 +66,7 @@ describe('unmuteAllRuleRoute', () => {
const [, handler] = router.post.mock.calls[0];
- rulesClient.unmuteAll.mockRejectedValue(new AlertTypeDisabledError('Fail', 'license_invalid'));
+ rulesClient.unmuteAll.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
'ok',
diff --git a/x-pack/plugins/alerting/server/routes/unmute_all_rule.ts b/x-pack/plugins/alerting/server/routes/unmute_all_rule.ts
index a0b562404b0b1..05ae9be2ba6e5 100644
--- a/x-pack/plugins/alerting/server/routes/unmute_all_rule.ts
+++ b/x-pack/plugins/alerting/server/routes/unmute_all_rule.ts
@@ -7,7 +7,7 @@
import { IRouter } from 'kibana/server';
import { schema } from '@kbn/config-schema';
-import { ILicenseState, AlertTypeDisabledError } from '../lib';
+import { ILicenseState, RuleTypeDisabledError } from '../lib';
import { verifyAccessAndContext } from './lib';
import { AlertingRequestHandlerContext, BASE_ALERTING_API_PATH } from '../types';
@@ -34,7 +34,7 @@ export const unmuteAllRuleRoute = (
await rulesClient.unmuteAll({ id });
return res.noContent();
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/unsnooze_rule.test.ts b/x-pack/plugins/alerting/server/routes/unsnooze_rule.test.ts
index a0fbf9776240a..260e4b4150043 100644
--- a/x-pack/plugins/alerting/server/routes/unsnooze_rule.test.ts
+++ b/x-pack/plugins/alerting/server/routes/unsnooze_rule.test.ts
@@ -10,7 +10,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../lib/license_state.mock';
import { mockHandlerArguments } from './_mock_handler_arguments';
import { rulesClientMock } from '../rules_client.mock';
-import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled';
const rulesClient = rulesClientMock.create();
jest.mock('../lib/license_api_access.ts', () => ({
@@ -66,7 +66,7 @@ describe('unsnoozeAlertRoute', () => {
const [, handler] = router.post.mock.calls[0];
- rulesClient.unsnooze.mockRejectedValue(new AlertTypeDisabledError('Fail', 'license_invalid'));
+ rulesClient.unsnooze.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
'ok',
diff --git a/x-pack/plugins/alerting/server/routes/update_rule.test.ts b/x-pack/plugins/alerting/server/routes/update_rule.test.ts
index 46f23641f70d9..f39ad53c8786d 100644
--- a/x-pack/plugins/alerting/server/routes/update_rule.test.ts
+++ b/x-pack/plugins/alerting/server/routes/update_rule.test.ts
@@ -13,10 +13,10 @@ import { verifyApiAccess } from '../lib/license_api_access';
import { mockHandlerArguments } from './_mock_handler_arguments';
import { UpdateOptions } from '../rules_client';
import { rulesClientMock } from '../rules_client.mock';
-import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled';
-import { AlertNotifyWhenType } from '../../common';
+import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled';
+import { RuleNotifyWhenType } from '../../common';
import { AsApiContract } from './lib';
-import { PartialAlert } from '../types';
+import { PartialRule } from '../types';
const rulesClient = rulesClientMock.create();
jest.mock('../lib/license_api_access.ts', () => ({
@@ -50,7 +50,7 @@ describe('updateRuleRoute', () => {
},
},
],
- notifyWhen: 'onActionGroupChange' as AlertNotifyWhenType,
+ notifyWhen: 'onActionGroupChange' as RuleNotifyWhenType,
};
const updateRequest: AsApiContract['data']> = {
@@ -65,7 +65,7 @@ describe('updateRuleRoute', () => {
],
};
- const updateResult: AsApiContract> = {
+ const updateResult: AsApiContract> = {
...updateRequest,
id: mockedAlert.id,
updated_at: mockedAlert.updatedAt,
@@ -201,7 +201,7 @@ describe('updateRuleRoute', () => {
const [, handler] = router.put.mock.calls[0];
- rulesClient.update.mockRejectedValue(new AlertTypeDisabledError('Fail', 'license_invalid'));
+ rulesClient.update.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid'));
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
'ok',
diff --git a/x-pack/plugins/alerting/server/routes/update_rule.ts b/x-pack/plugins/alerting/server/routes/update_rule.ts
index 007d24bb8251b..5c416e50b4ff2 100644
--- a/x-pack/plugins/alerting/server/routes/update_rule.ts
+++ b/x-pack/plugins/alerting/server/routes/update_rule.ts
@@ -7,8 +7,8 @@
import { schema } from '@kbn/config-schema';
import { IRouter } from 'kibana/server';
-import { ILicenseState, AlertTypeDisabledError, validateDurationSchema } from '../lib';
-import { AlertNotifyWhenType } from '../../common';
+import { ILicenseState, RuleTypeDisabledError, validateDurationSchema } from '../lib';
+import { RuleNotifyWhenType } from '../../common';
import { UpdateOptions } from '../rules_client';
import {
verifyAccessAndContext,
@@ -17,11 +17,11 @@ import {
handleDisabledApiKeysError,
} from './lib';
import {
- AlertTypeParams,
+ RuleTypeParams,
AlertingRequestHandlerContext,
BASE_ALERTING_API_PATH,
validateNotifyWhenType,
- PartialAlert,
+ PartialRule,
} from '../types';
const paramSchema = schema.object({
@@ -47,7 +47,7 @@ const bodySchema = schema.object({
notify_when: schema.string({ validate: validateNotifyWhenType }),
});
-const rewriteBodyReq: RewriteRequestCase> = (result) => {
+const rewriteBodyReq: RewriteRequestCase> = (result) => {
const { notify_when: notifyWhen, ...rest } = result.data;
return {
...result,
@@ -57,7 +57,7 @@ const rewriteBodyReq: RewriteRequestCase> = (resu
},
};
};
-const rewriteBodyRes: RewriteResponseCase> = ({
+const rewriteBodyRes: RewriteResponseCase> = ({
actions,
alertTypeId,
scheduledTaskId,
@@ -128,7 +128,7 @@ export const updateRuleRoute = (
id,
data: {
...rule,
- notify_when: rule.notify_when as AlertNotifyWhenType,
+ notify_when: rule.notify_when as RuleNotifyWhenType,
},
})
);
@@ -136,7 +136,7 @@ export const updateRuleRoute = (
body: rewriteBodyRes(alertRes),
});
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/routes/update_rule_api_key.test.ts b/x-pack/plugins/alerting/server/routes/update_rule_api_key.test.ts
index b4fb7602bf034..2622c260d7938 100644
--- a/x-pack/plugins/alerting/server/routes/update_rule_api_key.test.ts
+++ b/x-pack/plugins/alerting/server/routes/update_rule_api_key.test.ts
@@ -10,7 +10,7 @@ import { httpServiceMock } from 'src/core/server/mocks';
import { licenseStateMock } from '../lib/license_state.mock';
import { mockHandlerArguments } from './_mock_handler_arguments';
import { rulesClientMock } from '../rules_client.mock';
-import { AlertTypeDisabledError } from '../lib/errors/alert_type_disabled';
+import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled';
const rulesClient = rulesClientMock.create();
jest.mock('../lib/license_api_access.ts', () => ({
@@ -67,7 +67,7 @@ describe('updateRuleApiKeyRoute', () => {
const [, handler] = router.post.mock.calls[0];
rulesClient.updateApiKey.mockRejectedValue(
- new AlertTypeDisabledError('Fail', 'license_invalid')
+ new RuleTypeDisabledError('Fail', 'license_invalid')
);
const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [
diff --git a/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts b/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts
index 11d76f3992efd..a6644e455a9be 100644
--- a/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts
+++ b/x-pack/plugins/alerting/server/routes/update_rule_api_key.ts
@@ -7,7 +7,7 @@
import { IRouter } from 'kibana/server';
import { schema } from '@kbn/config-schema';
-import { ILicenseState, AlertTypeDisabledError } from '../lib';
+import { ILicenseState, RuleTypeDisabledError } from '../lib';
import { verifyAccessAndContext } from './lib';
import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../types';
@@ -34,7 +34,7 @@ export const updateRuleApiKeyRoute = (
await rulesClient.updateApiKey({ id });
return res.noContent();
} catch (e) {
- if (e instanceof AlertTypeDisabledError) {
+ if (e instanceof RuleTypeDisabledError) {
return e.sendResponse(res);
}
throw e;
diff --git a/x-pack/plugins/alerting/server/rule_type_registry.ts b/x-pack/plugins/alerting/server/rule_type_registry.ts
index 35e9e312e9a1a..bc548b8ae2286 100644
--- a/x-pack/plugins/alerting/server/rule_type_registry.ts
+++ b/x-pack/plugins/alerting/server/rule_type_registry.ts
@@ -16,8 +16,8 @@ import { RunContext, TaskManagerSetupContract } from '../../task_manager/server'
import { TaskRunnerFactory } from './task_runner';
import {
RuleType,
- AlertTypeParams,
- AlertTypeState,
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
} from './types';
@@ -84,9 +84,9 @@ const ruleTypeIdSchema = schema.string({
});
export type NormalizedRuleType<
- Params extends AlertTypeParams,
- ExtractedParams extends AlertTypeParams,
- State extends AlertTypeState,
+ Params extends RuleTypeParams,
+ ExtractedParams extends RuleTypeParams,
+ State extends RuleTypeState,
InstanceState extends AlertInstanceState,
InstanceContext extends AlertInstanceContext,
ActionGroupIds extends string,
@@ -121,9 +121,9 @@ export type NormalizedRuleType<
>;
export type UntypedNormalizedRuleType = NormalizedRuleType<
- AlertTypeParams,
- AlertTypeParams,
- AlertTypeState,
+ RuleTypeParams,
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string,
@@ -167,9 +167,9 @@ export class RuleTypeRegistry {
}
public register<
- Params extends AlertTypeParams,
- ExtractedParams extends AlertTypeParams,
- State extends AlertTypeState,
+ Params extends RuleTypeParams,
+ ExtractedParams extends RuleTypeParams,
+ State extends RuleTypeState,
InstanceState extends AlertInstanceState,
InstanceContext extends AlertInstanceContext,
ActionGroupIds extends string,
@@ -287,9 +287,9 @@ export class RuleTypeRegistry {
}
public get<
- Params extends AlertTypeParams = AlertTypeParams,
- ExtractedParams extends AlertTypeParams = AlertTypeParams,
- State extends AlertTypeState = AlertTypeState,
+ Params extends RuleTypeParams = RuleTypeParams,
+ ExtractedParams extends RuleTypeParams = RuleTypeParams,
+ State extends RuleTypeState = RuleTypeState,
InstanceState extends AlertInstanceState = AlertInstanceState,
InstanceContext extends AlertInstanceContext = AlertInstanceContext,
ActionGroupIds extends string = string,
@@ -382,9 +382,9 @@ function normalizedActionVariables(actionVariables: RuleType['actionVariables'])
}
function augmentActionGroupsWithReserved<
- Params extends AlertTypeParams,
- ExtractedParams extends AlertTypeParams,
- State extends AlertTypeState,
+ Params extends RuleTypeParams,
+ ExtractedParams extends RuleTypeParams,
+ State extends RuleTypeState,
InstanceState extends AlertInstanceState,
InstanceContext extends AlertInstanceContext,
ActionGroupIds extends string,
diff --git a/x-pack/plugins/alerting/server/rules_client/lib/mapped_params_utils.ts b/x-pack/plugins/alerting/server/rules_client/lib/mapped_params_utils.ts
index e9624d4604c46..26385cfac3f78 100644
--- a/x-pack/plugins/alerting/server/rules_client/lib/mapped_params_utils.ts
+++ b/x-pack/plugins/alerting/server/rules_client/lib/mapped_params_utils.ts
@@ -6,7 +6,7 @@
*/
import { snakeCase } from 'lodash';
-import { AlertTypeParams, MappedParams, MappedParamsProperties } from '../../types';
+import { RuleTypeParams, MappedParams, MappedParamsProperties } from '../../types';
import { SavedObjectAttribute } from '../../../../../../src/core/server';
import {
iterateFilterKureyNode,
@@ -32,7 +32,7 @@ const SEVERITY_MAP: Record = {
* The function will match params present in MAPPED_PARAMS_PROPERTIES and
* return an empty object if nothing is matched.
*/
-export const getMappedParams = (params: AlertTypeParams) => {
+export const getMappedParams = (params: RuleTypeParams) => {
return Object.entries(params).reduce((result, [key, value]) => {
const snakeCaseKey = snakeCase(key);
diff --git a/x-pack/plugins/alerting/server/rules_client/rules_client.ts b/x-pack/plugins/alerting/server/rules_client/rules_client.ts
index 901d7102f40c6..ac53486d279fd 100644
--- a/x-pack/plugins/alerting/server/rules_client/rules_client.ts
+++ b/x-pack/plugins/alerting/server/rules_client/rules_client.ts
@@ -22,25 +22,25 @@ import {
} from '../../../../../src/core/server';
import { ActionsClient, ActionsAuthorization } from '../../../actions/server';
import {
- Alert as Rule,
- PartialAlert as PartialRule,
+ Rule,
+ PartialRule,
RawRule,
RuleTypeRegistry,
- AlertAction as RuleAction,
+ RuleAction,
IntervalSchedule,
- SanitizedAlert as SanitizedRule,
+ SanitizedRule,
RuleTaskState,
AlertSummary,
- AlertExecutionStatusValues as RuleExecutionStatusValues,
- AlertNotifyWhenType as RuleNotifyWhenType,
- AlertTypeParams as RuleTypeParams,
+ RuleExecutionStatusValues,
+ RuleNotifyWhenType,
+ RuleTypeParams,
ResolvedSanitizedRule,
- AlertWithLegacyId as RuleWithLegacyId,
+ RuleWithLegacyId,
SanitizedRuleWithLegacyId,
- PartialAlertWithLegacyId as PartialRuleWithLegacyId,
+ PartialRuleWithLegacyId,
RawAlertInstance as RawAlert,
} from '../types';
-import { validateRuleTypeParams, ruleExecutionStatusFromRaw, getAlertNotifyWhenType } from '../lib';
+import { validateRuleTypeParams, ruleExecutionStatusFromRaw, getRuleNotifyWhenType } from '../lib';
import {
GrantAPIKeyResult as SecurityPluginGrantAPIKeyResult,
InvalidateAPIKeyResult as SecurityPluginInvalidateAPIKeyResult,
@@ -89,13 +89,10 @@ import {
formatExecutionLogResult,
getExecutionLogAggregation,
} from '../lib/get_execution_log_aggregation';
-import { IExecutionLogResult } from '../../common';
+import { IExecutionLogWithErrorsResult } from '../../common';
import { validateSnoozeDate } from '../lib/validate_snooze_date';
import { RuleMutedError } from '../lib/errors/rule_muted';
-import {
- formatExecutionErrorsResult,
- IExecutionErrorsResult,
-} from '../lib/format_execution_log_errors';
+import { formatExecutionErrorsResult } from '../lib/format_execution_log_errors';
export interface RegistryAlertTypeWithAuth extends RegistryRuleType {
authorizedConsumers: string[];
@@ -263,7 +260,6 @@ export interface GetExecutionLogByIdParams {
sort: estypes.Sort;
}
-export type IExecutionLogWithErrorsResult = IExecutionLogResult & IExecutionErrorsResult;
interface ScheduleRuleOptions {
id: string;
consumer: string;
@@ -406,7 +402,7 @@ export class RulesClient {
const createTime = Date.now();
const legacyId = Semver.lt(this.kibanaVersion, '8.0.0') ? id : null;
- const notifyWhen = getAlertNotifyWhenType(data.notifyWhen, data.throttle);
+ const notifyWhen = getRuleNotifyWhenType(data.notifyWhen, data.throttle);
const rawRule: RawRule = {
...data,
@@ -1204,7 +1200,7 @@ export class RulesClient {
}
const apiKeyAttributes = this.apiKeyAsAlertAttributes(createdAPIKey, username);
- const notifyWhen = getAlertNotifyWhenType(data.notifyWhen, data.throttle);
+ const notifyWhen = getRuleNotifyWhenType(data.notifyWhen, data.throttle);
let updatedObject: SavedObject;
const createAttributes = this.updateMeta({
diff --git a/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts
index 8a16bcb2d2fd7..df5f9252a98a0 100644
--- a/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts
+++ b/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts
@@ -96,185 +96,189 @@ const BaseRuleSavedObject: SavedObject = {
const aggregateResults = {
aggregations: {
- executionUuid: {
+ excludeExecuteStart: {
meta: {},
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [
- {
- key: '6705da7d-2635-499d-a6a8-1aee1ae1eac9',
- doc_count: 27,
- timeoutMessage: {
- meta: {},
- doc_count: 0,
- },
- alertCounts: {
- meta: {},
- buckets: {
- activeAlerts: {
- doc_count: 5,
+ doc_count: 875,
+ executionUuid: {
+ meta: {},
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
+ {
+ key: '6705da7d-2635-499d-a6a8-1aee1ae1eac9',
+ doc_count: 27,
+ timeoutMessage: {
+ meta: {},
+ doc_count: 0,
+ },
+ alertCounts: {
+ meta: {},
+ buckets: {
+ activeAlerts: {
+ doc_count: 5,
+ },
+ newAlerts: {
+ doc_count: 5,
+ },
+ recoveredAlerts: {
+ doc_count: 0,
+ },
},
- newAlerts: {
- doc_count: 5,
+ },
+ ruleExecution: {
+ meta: {},
+ doc_count: 1,
+ numTriggeredActions: {
+ value: 5.0,
},
- recoveredAlerts: {
- doc_count: 0,
+ numScheduledActions: {
+ value: 5.0,
},
- },
- },
- ruleExecution: {
- meta: {},
- doc_count: 1,
- numTriggeredActions: {
- value: 5.0,
- },
- numScheduledActions: {
- value: 5.0,
- },
- outcomeAndMessage: {
- hits: {
- total: {
- value: 1,
- relation: 'eq',
- },
- max_score: 1.0,
- hits: [
- {
- _index: '.kibana-event-log-8.2.0-000001',
- _id: 'S4wIZX8B8TGQpG7XQZns',
- _score: 1.0,
- _source: {
- event: {
- outcome: 'success',
+ outcomeAndMessage: {
+ hits: {
+ total: {
+ value: 1,
+ relation: 'eq',
+ },
+ max_score: 1.0,
+ hits: [
+ {
+ _index: '.kibana-event-log-8.2.0-000001',
+ _id: 'S4wIZX8B8TGQpG7XQZns',
+ _score: 1.0,
+ _source: {
+ event: {
+ outcome: 'success',
+ },
+ message:
+ "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
},
- message:
- "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
},
+ ],
+ },
+ },
+ scheduleDelay: {
+ value: 3.126e9,
+ },
+ totalSearchDuration: {
+ value: 0.0,
+ },
+ esSearchDuration: {
+ value: 0.0,
+ },
+ executionDuration: {
+ value: 1.056e9,
+ },
+ executeStartTime: {
+ value: 1.646667512617e12,
+ value_as_string: '2022-03-07T15:38:32.617Z',
+ },
+ },
+ actionExecution: {
+ meta: {},
+ doc_count: 5,
+ actionOutcomes: {
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
+ {
+ key: 'success',
+ doc_count: 5,
},
],
},
},
- scheduleDelay: {
- value: 3.126e9,
- },
- totalSearchDuration: {
- value: 0.0,
- },
- esSearchDuration: {
- value: 0.0,
- },
- executionDuration: {
- value: 1.056e9,
- },
- executeStartTime: {
- value: 1.646667512617e12,
- value_as_string: '2022-03-07T15:38:32.617Z',
- },
},
- actionExecution: {
- meta: {},
- doc_count: 5,
- actionOutcomes: {
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [
- {
- key: 'success',
+ {
+ key: '41b2755e-765a-4044-9745-b03875d5e79a',
+ doc_count: 32,
+ timeoutMessage: {
+ meta: {},
+ doc_count: 0,
+ },
+ alertCounts: {
+ meta: {},
+ buckets: {
+ activeAlerts: {
+ doc_count: 5,
+ },
+ newAlerts: {
+ doc_count: 5,
+ },
+ recoveredAlerts: {
doc_count: 5,
},
- ],
+ },
},
- },
- },
- {
- key: '41b2755e-765a-4044-9745-b03875d5e79a',
- doc_count: 32,
- timeoutMessage: {
- meta: {},
- doc_count: 0,
- },
- alertCounts: {
- meta: {},
- buckets: {
- activeAlerts: {
- doc_count: 5,
+ ruleExecution: {
+ meta: {},
+ doc_count: 1,
+ numTriggeredActions: {
+ value: 5.0,
+ },
+ numScheduledActions: {
+ value: 5.0,
+ },
+ outcomeAndMessage: {
+ hits: {
+ total: {
+ value: 1,
+ relation: 'eq',
+ },
+ max_score: 1.0,
+ hits: [
+ {
+ _index: '.kibana-event-log-8.2.0-000001',
+ _id: 'a4wIZX8B8TGQpG7Xwpnz',
+ _score: 1.0,
+ _source: {
+ event: {
+ outcome: 'success',
+ },
+ message:
+ "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
+ },
+ },
+ ],
+ },
},
- newAlerts: {
- doc_count: 5,
+ scheduleDelay: {
+ value: 3.345e9,
},
- recoveredAlerts: {
- doc_count: 5,
+ totalSearchDuration: {
+ value: 0.0,
+ },
+ esSearchDuration: {
+ value: 0.0,
+ },
+ executionDuration: {
+ value: 1.165e9,
+ },
+ executeStartTime: {
+ value: 1.646667545604e12,
+ value_as_string: '2022-03-07T15:39:05.604Z',
},
},
- },
- ruleExecution: {
- meta: {},
- doc_count: 1,
- numTriggeredActions: {
- value: 5.0,
- },
- numScheduledActions: {
- value: 5.0,
- },
- outcomeAndMessage: {
- hits: {
- total: {
- value: 1,
- relation: 'eq',
- },
- max_score: 1.0,
- hits: [
+ actionExecution: {
+ meta: {},
+ doc_count: 5,
+ actionOutcomes: {
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
{
- _index: '.kibana-event-log-8.2.0-000001',
- _id: 'a4wIZX8B8TGQpG7Xwpnz',
- _score: 1.0,
- _source: {
- event: {
- outcome: 'success',
- },
- message:
- "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'",
- },
+ key: 'success',
+ doc_count: 5,
},
],
},
},
- scheduleDelay: {
- value: 3.345e9,
- },
- totalSearchDuration: {
- value: 0.0,
- },
- esSearchDuration: {
- value: 0.0,
- },
- executionDuration: {
- value: 1.165e9,
- },
- executeStartTime: {
- value: 1.646667545604e12,
- value_as_string: '2022-03-07T15:39:05.604Z',
- },
- },
- actionExecution: {
- meta: {},
- doc_count: 5,
- actionOutcomes: {
- doc_count_error_upper_bound: 0,
- sum_other_doc_count: 0,
- buckets: [
- {
- key: 'success',
- doc_count: 5,
- },
- ],
- },
},
- },
- ],
- },
- executionUuidCardinality: {
- value: 374,
+ ],
+ },
+ executionUuidCardinality: {
+ value: 374,
+ },
},
},
};
diff --git a/x-pack/plugins/alerting/server/saved_objects/geo_containment/migrations.ts b/x-pack/plugins/alerting/server/saved_objects/geo_containment/migrations.ts
index 50e6979d6ee72..ffed0e0b5efbc 100644
--- a/x-pack/plugins/alerting/server/saved_objects/geo_containment/migrations.ts
+++ b/x-pack/plugins/alerting/server/saved_objects/geo_containment/migrations.ts
@@ -10,14 +10,14 @@ import {
SavedObjectReference,
SavedObjectUnsanitizedDoc,
} from 'kibana/server';
-import { AlertTypeParams } from '../../index';
+import { RuleTypeParams } from '../../index';
import { Query } from '../../../../../../src/plugins/data/common/query';
import { RawRule } from '../../types';
// These definitions are dupes of the SO-types in stack_alerts/geo_containment
// There are not exported to avoid deep imports from stack_alerts plugins into here
const GEO_CONTAINMENT_ID = '.geo-containment';
-interface GeoContainmentParams extends AlertTypeParams {
+interface GeoContainmentParams extends RuleTypeParams {
index: string;
indexId: string;
geoField: string;
diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations.ts b/x-pack/plugins/alerting/server/saved_objects/migrations.ts
index 0e3dc072366c2..91e03eb4da6c2 100644
--- a/x-pack/plugins/alerting/server/saved_objects/migrations.ts
+++ b/x-pack/plugins/alerting/server/saved_objects/migrations.ts
@@ -17,7 +17,7 @@ import {
SavedObjectAttribute,
SavedObjectReference,
} from '../../../../../src/core/server';
-import { RawRule, RawAlertAction, RawRuleExecutionStatus } from '../types';
+import { RawRule, RawRuleAction, RawRuleExecutionStatus } from '../types';
import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server';
import type { IsMigrationNeededPredicate } from '../../../encrypted_saved_objects/server';
import { extractRefsFromGeoContainmentAlert } from './geo_containment/migrations';
@@ -353,7 +353,7 @@ function restructureConnectorsThatSupportIncident(
},
},
},
- ] as RawAlertAction[];
+ ] as RawRuleAction[];
} else if (action.actionTypeId === '.jira') {
const { title, comments, description, issueType, priority, labels, parent, summary } =
action.params.subActionParams as {
@@ -385,7 +385,7 @@ function restructureConnectorsThatSupportIncident(
},
},
},
- ] as RawAlertAction[];
+ ] as RawRuleAction[];
} else if (action.actionTypeId === '.resilient') {
const { title, comments, description, incidentTypes, severityCode, name } = action.params
.subActionParams as {
@@ -413,12 +413,12 @@ function restructureConnectorsThatSupportIncident(
},
},
},
- ] as RawAlertAction[];
+ ] as RawRuleAction[];
}
}
return [...acc, action];
- }, [] as RawAlertAction[]);
+ }, [] as RawRuleAction[]);
return {
...doc,
@@ -855,13 +855,13 @@ function addMappedParams(
function getCorrespondingAction(
actions: SavedObjectAttribute,
connectorRef: string
-): RawAlertAction | null {
+): RawRuleAction | null {
if (!Array.isArray(actions)) {
return null;
} else {
return actions.find(
- (action) => (action as RawAlertAction)?.actionRef === connectorRef
- ) as RawAlertAction;
+ (action) => (action as RawRuleAction)?.actionRef === connectorRef
+ ) as RawRuleAction;
}
}
diff --git a/x-pack/plugins/alerting/server/task_runner/alert_task_instance.test.ts b/x-pack/plugins/alerting/server/task_runner/alert_task_instance.test.ts
index ef48a701d0315..f5183e9e19dcc 100644
--- a/x-pack/plugins/alerting/server/task_runner/alert_task_instance.test.ts
+++ b/x-pack/plugins/alerting/server/task_runner/alert_task_instance.test.ts
@@ -8,9 +8,9 @@
import { ConcreteTaskInstance, TaskStatus } from '../../../task_manager/server';
import { AlertTaskInstance, taskInstanceToAlertTaskInstance } from './alert_task_instance';
import uuid from 'uuid';
-import { SanitizedAlert } from '../types';
+import { SanitizedRule } from '../types';
-const alert: SanitizedAlert<{
+const alert: SanitizedRule<{
bar: boolean;
}> = {
id: 'alert-123',
diff --git a/x-pack/plugins/alerting/server/task_runner/alert_task_instance.ts b/x-pack/plugins/alerting/server/task_runner/alert_task_instance.ts
index a6bb6a68ceae8..fd61b37a277de 100644
--- a/x-pack/plugins/alerting/server/task_runner/alert_task_instance.ts
+++ b/x-pack/plugins/alerting/server/task_runner/alert_task_instance.ts
@@ -10,12 +10,12 @@ import { pipe } from 'fp-ts/lib/pipeable';
import { fold } from 'fp-ts/lib/Either';
import { ConcreteTaskInstance } from '../../../task_manager/server';
import {
- SanitizedAlert,
+ SanitizedRule,
RuleTaskState,
ruleParamsSchema,
ruleStateSchema,
RuleTaskParams,
- AlertTypeParams,
+ RuleTypeParams,
} from '../../common';
export interface AlertTaskInstance extends ConcreteTaskInstance {
@@ -26,9 +26,9 @@ export interface AlertTaskInstance extends ConcreteTaskInstance {
const enumerateErrorFields = (e: t.Errors) =>
`${e.map(({ context }) => context.map(({ key }) => key).join('.'))}`;
-export function taskInstanceToAlertTaskInstance(
+export function taskInstanceToAlertTaskInstance(
taskInstance: ConcreteTaskInstance,
- alert?: SanitizedAlert
+ alert?: SanitizedRule
): AlertTaskInstance {
return {
...taskInstance,
diff --git a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts
index 8b97bf9266e9a..af0220ccba987 100644
--- a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts
+++ b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts
@@ -18,21 +18,16 @@ import { KibanaRequest } from 'kibana/server';
import { asSavedObjectExecutionSource } from '../../../actions/server';
import { InjectActionParamsOpts } from './inject_action_params';
import { NormalizedRuleType } from '../rule_type_registry';
-import {
- AlertInstanceContext,
- AlertInstanceState,
- AlertTypeParams,
- AlertTypeState,
-} from '../types';
+import { AlertInstanceContext, AlertInstanceState, RuleTypeParams, RuleTypeState } from '../types';
jest.mock('./inject_action_params', () => ({
injectActionParams: jest.fn(),
}));
const ruleType: NormalizedRuleType<
- AlertTypeParams,
- AlertTypeParams,
- AlertTypeState,
+ RuleTypeParams,
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
'default' | 'other-group',
@@ -66,9 +61,9 @@ const mockActionsPlugin = actionsMock.createStart();
const mockEventLogger = eventLoggerMock.create();
const createExecutionHandlerParams: jest.Mocked<
CreateExecutionHandlerOptions<
- AlertTypeParams,
- AlertTypeParams,
- AlertTypeState,
+ RuleTypeParams,
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
'default' | 'other-group',
diff --git a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts
index 56e1a25cb0655..7752817f17c85 100644
--- a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts
+++ b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts
@@ -9,12 +9,7 @@ import { asSavedObjectExecutionSource } from '../../../actions/server';
import { SAVED_OBJECT_REL_PRIMARY } from '../../../event_log/server';
import { EVENT_LOG_ACTIONS } from '../plugin';
import { injectActionParams } from './inject_action_params';
-import {
- AlertInstanceContext,
- AlertInstanceState,
- AlertTypeParams,
- AlertTypeState,
-} from '../types';
+import { AlertInstanceContext, AlertInstanceState, RuleTypeParams, RuleTypeState } from '../types';
import { UntypedNormalizedRuleType } from '../rule_type_registry';
import { isEphemeralTaskRejectedDueToCapacityError } from '../../../task_manager/server';
@@ -26,9 +21,9 @@ export type ExecutionHandler = (
) => Promise;
export function createExecutionHandler<
- Params extends AlertTypeParams,
- ExtractedParams extends AlertTypeParams,
- State extends AlertTypeState,
+ Params extends RuleTypeParams,
+ ExtractedParams extends RuleTypeParams,
+ State extends RuleTypeState,
InstanceState extends AlertInstanceState,
InstanceContext extends AlertInstanceContext,
ActionGroupIds extends string,
diff --git a/x-pack/plugins/alerting/server/task_runner/fixtures.ts b/x-pack/plugins/alerting/server/task_runner/fixtures.ts
index 1c8e1776a523f..613f3ed9e1645 100644
--- a/x-pack/plugins/alerting/server/task_runner/fixtures.ts
+++ b/x-pack/plugins/alerting/server/task_runner/fixtures.ts
@@ -7,9 +7,9 @@
import { isNil } from 'lodash';
import {
- Alert,
- AlertExecutionStatusWarningReasons,
- AlertTypeParams,
+ Rule,
+ RuleExecutionStatusWarningReasons,
+ RuleTypeParams,
RecoveredActionGroup,
} from '../../common';
import { getDefaultRuleMonitoring } from './task_runner';
@@ -121,7 +121,7 @@ export const mockRunNowResponse = {
export const mockDate = new Date('2019-02-12T21:01:22.479Z');
-export const mockedRuleTypeSavedObject: Alert = {
+export const mockedRuleTypeSavedObject: Rule = {
id: '1',
consumer: 'bar',
createdAt: mockDate,
@@ -335,7 +335,7 @@ const generateMessage = ({
}
if (
status === 'warning' &&
- reason === AlertExecutionStatusWarningReasons.MAX_EXECUTABLE_ACTIONS
+ reason === RuleExecutionStatusWarningReasons.MAX_EXECUTABLE_ACTIONS
) {
return `The maximum number of actions for this rule type was reached; excess actions were not triggered.`;
}
diff --git a/x-pack/plugins/alerting/server/task_runner/inject_action_params.ts b/x-pack/plugins/alerting/server/task_runner/inject_action_params.ts
index 11ac3f92d1071..f2a41038e257e 100644
--- a/x-pack/plugins/alerting/server/task_runner/inject_action_params.ts
+++ b/x-pack/plugins/alerting/server/task_runner/inject_action_params.ts
@@ -6,13 +6,13 @@
*/
import { i18n } from '@kbn/i18n';
-import { AlertActionParams } from '../types';
+import { RuleActionParams } from '../types';
export interface InjectActionParamsOpts {
ruleId: string;
spaceId: string | undefined;
actionTypeId: string;
- actionParams: AlertActionParams;
+ actionParams: RuleActionParams;
}
export function injectActionParams({
diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts
index c261b4ddbba25..21109b60e012d 100644
--- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts
+++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts
@@ -9,12 +9,12 @@ import sinon from 'sinon';
import { schema } from '@kbn/config-schema';
import { usageCountersServiceMock } from 'src/plugins/usage_collection/server/usage_counters/usage_counters_service.mock';
import {
- AlertExecutorOptions,
- AlertTypeParams,
- AlertTypeState,
+ RuleExecutorOptions,
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
- AlertExecutionStatusWarningReasons,
+ RuleExecutionStatusWarningReasons,
} from '../types';
import {
ConcreteTaskInstance,
@@ -96,7 +96,7 @@ describe('Task Runner', () => {
afterAll(() => fakeTimer.restore());
const encryptedSavedObjectsClient = encryptedSavedObjectsMock.createClient();
- const services = alertsMock.createAlertServices();
+ const services = alertsMock.createRuleExecutorServices();
const actionsClient = actionsClientMock.create();
const rulesClient = rulesClientMock.create();
const ruleTypeRegistry = ruleTypeRegistryMock.create();
@@ -282,9 +282,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -386,9 +386,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -499,9 +499,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -550,9 +550,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -607,9 +607,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -667,9 +667,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -707,9 +707,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -797,9 +797,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -865,9 +865,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -940,9 +940,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -1057,9 +1057,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -1210,9 +1210,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -1294,9 +1294,9 @@ describe('Task Runner', () => {
ruleTypeWithCustomRecovery.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -1356,9 +1356,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -1567,9 +1567,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -1806,9 +1806,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -1957,9 +1957,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -2065,9 +2065,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -2169,9 +2169,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -2349,9 +2349,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -2578,9 +2578,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -2608,9 +2608,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -2652,7 +2652,7 @@ describe('Task Runner', () => {
};
const warning = {
- reason: AlertExecutionStatusWarningReasons.MAX_EXECUTABLE_ACTIONS,
+ reason: RuleExecutionStatusWarningReasons.MAX_EXECUTABLE_ACTIONS,
message: translations.taskRunner.warning.maxExecutableActions,
};
@@ -2662,9 +2662,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -2820,7 +2820,7 @@ describe('Task Runner', () => {
status: 'warning',
numberOfTriggeredActions: ruleTypeWithConfig.config.execution.actions.max,
numberOfScheduledActions: mockActions.length,
- reason: AlertExecutionStatusWarningReasons.MAX_EXECUTABLE_ACTIONS,
+ reason: RuleExecutionStatusWarningReasons.MAX_EXECUTABLE_ACTIONS,
task: true,
consumer: 'bar',
})
@@ -2852,9 +2852,9 @@ describe('Task Runner', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts
index 0e69131711067..36c8bddb1ff82 100644
--- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts
+++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts
@@ -14,7 +14,7 @@ import { KibanaRequest, Logger } from '../../../../../src/core/server';
import { TaskRunnerContext } from './task_runner_factory';
import { ConcreteTaskInstance, throwUnrecoverableError } from '../../../task_manager/server';
import { createExecutionHandler, ExecutionHandler } from './create_execution_handler';
-import { Alert as CreatedAlert, createAlertFactory } from '../alert';
+import { Alert, createAlertFactory } from '../alert';
import {
createWrappedScopedClusterClientFactory,
ElasticsearchError,
@@ -26,9 +26,9 @@ import {
validateRuleTypeParams,
} from '../lib';
import {
- Alert,
- AlertExecutionStatus,
- AlertExecutionStatusErrorReasons,
+ Rule,
+ RuleExecutionStatus,
+ RuleExecutionStatusErrorReasons,
IntervalSchedule,
RawAlertInstance,
RawRule,
@@ -39,7 +39,7 @@ import {
RuleMonitoringHistory,
RuleTaskState,
RuleTypeRegistry,
- SanitizedAlert,
+ SanitizedRule,
} from '../types';
import { asErr, asOk, map, promiseResult, resolveErr, Resultable } from '../lib/result_type';
import { getExecutionDurationPercentiles, getExecutionSuccessRatio } from '../lib/monitoring';
@@ -51,8 +51,8 @@ import { partiallyUpdateAlert } from '../saved_objects';
import {
AlertInstanceContext,
AlertInstanceState,
- AlertTypeParams,
- AlertTypeState,
+ RuleTypeParams,
+ RuleTypeState,
MONITORING_HISTORY_LIMIT,
parseDuration,
WithoutReservedActionGroups,
@@ -91,9 +91,9 @@ export const getDefaultRuleMonitoring = (): RuleMonitoring => ({
});
export class TaskRunner<
- Params extends AlertTypeParams,
- ExtractedParams extends AlertTypeParams,
- State extends AlertTypeState,
+ Params extends RuleTypeParams,
+ ExtractedParams extends RuleTypeParams,
+ State extends RuleTypeState,
InstanceState extends AlertInstanceState,
InstanceContext extends AlertInstanceContext,
ActionGroupIds extends string,
@@ -201,7 +201,7 @@ export class TaskRunner<
spaceId: string,
apiKey: RawRule['apiKey'],
kibanaBaseUrl: string | undefined,
- actions: Alert['actions'],
+ actions: Rule['actions'],
ruleParams: Params,
request: KibanaRequest
) {
@@ -252,7 +252,7 @@ export class TaskRunner<
}
}
- private isRuleSnoozed(rule: SanitizedAlert): boolean {
+ private isRuleSnoozed(rule: SanitizedRule): boolean {
if (rule.muteAll) {
return true;
}
@@ -288,7 +288,7 @@ export class TaskRunner<
private async executeAlert(
alertId: string,
- alert: CreatedAlert,
+ alert: Alert,
executionHandler: ExecutionHandler,
alertExecutionStore: AlertExecutionStore
) {
@@ -312,7 +312,7 @@ export class TaskRunner<
private async executeAlerts(
fakeRequest: KibanaRequest,
- rule: SanitizedAlert,
+ rule: SanitizedRule,
params: Params,
executionHandler: ExecutionHandler,
spaceId: string,
@@ -343,10 +343,10 @@ export class TaskRunner<
const alerts = mapValues<
Record,
- CreatedAlert
+ Alert
>(
alertRawInstances,
- (rawAlert, alertId) => new CreatedAlert(alertId, rawAlert)
+ (rawAlert, alertId) => new Alert(alertId, rawAlert)
);
const originalAlerts = cloneDeep(alerts);
@@ -440,7 +440,7 @@ export class TaskRunner<
event.event = event.event || {};
event.event.outcome = 'failure';
- throw new ErrorWithReason(AlertExecutionStatusErrorReasons.Execute, err);
+ throw new ErrorWithReason(RuleExecutionStatusErrorReasons.Execute, err);
}
event.message = `rule executed: ${ruleLabel}`;
@@ -456,7 +456,7 @@ export class TaskRunner<
// Cleanup alerts that are no longer scheduling actions to avoid over populating the alertInstances object
const alertsWithScheduledActions = pickBy(
alerts,
- (alert: CreatedAlert) => alert.hasScheduledActions()
+ (alert: Alert) => alert.hasScheduledActions()
);
const recoveredAlerts = getRecoveredAlerts(alerts, originalAlertIds);
@@ -502,7 +502,7 @@ export class TaskRunner<
const mutedAlertIdsSet = new Set(mutedInstanceIds);
const alertsWithExecutableActions = Object.entries(alertsWithScheduledActions).filter(
- ([alertName, alert]: [string, CreatedAlert]) => {
+ ([alertName, alert]: [string, Alert]) => {
const throttled = alert.isThrottled(throttle);
const muted = mutedAlertIdsSet.has(alertName);
let shouldExecuteAction = true;
@@ -530,7 +530,7 @@ export class TaskRunner<
await Promise.all(
alertsWithExecutableActions.map(
- ([alertId, alert]: [string, CreatedAlert]) =>
+ ([alertId, alert]: [string, Alert]) =>
this.executeAlert(alertId, alert, executionHandler, alertExecutionStore)
)
);
@@ -570,7 +570,7 @@ export class TaskRunner<
alertExecutionStore,
alertTypeState: updatedRuleTypeState || undefined,
alertInstances: mapValues<
- Record>,
+ Record>,
RawAlertInstance
>(alertsWithScheduledActions, (alert) => alert.toRaw()),
};
@@ -579,7 +579,7 @@ export class TaskRunner<
private async validateAndExecuteRule(
fakeRequest: KibanaRequest,
apiKey: RawRule['apiKey'],
- rule: SanitizedAlert,
+ rule: SanitizedRule,
event: Event
) {
const {
@@ -617,14 +617,14 @@ export class TaskRunner<
enabled = decryptedAttributes.enabled;
consumer = decryptedAttributes.consumer;
} catch (err) {
- throw new ErrorWithReason(AlertExecutionStatusErrorReasons.Decrypt, err);
+ throw new ErrorWithReason(RuleExecutionStatusErrorReasons.Decrypt, err);
}
this.ruleConsumer = consumer;
if (!enabled) {
throw new ErrorWithReason(
- AlertExecutionStatusErrorReasons.Disabled,
+ RuleExecutionStatusErrorReasons.Disabled,
new Error(`Rule failed to execute because rule ran after it was disabled.`)
);
}
@@ -634,7 +634,7 @@ export class TaskRunner<
// Get rules client with space level permissions
const rulesClient = this.context.getRulesClientWithRequest(fakeRequest);
- let rule: SanitizedAlert;
+ let rule: SanitizedRule;
// Ensure API key is still valid and user has access
try {
@@ -651,7 +651,7 @@ export class TaskRunner<
});
}
} catch (err) {
- throw new ErrorWithReason(AlertExecutionStatusErrorReasons.Read, err);
+ throw new ErrorWithReason(RuleExecutionStatusErrorReasons.Read, err);
}
this.ruleName = rule.name;
@@ -659,7 +659,7 @@ export class TaskRunner<
try {
this.ruleTypeRegistry.ensureRuleTypeEnabled(rule.alertTypeId);
} catch (err) {
- throw new ErrorWithReason(AlertExecutionStatusErrorReasons.License, err);
+ throw new ErrorWithReason(RuleExecutionStatusErrorReasons.License, err);
}
if (rule.monitoring) {
@@ -760,7 +760,7 @@ export class TaskRunner<
return getDefaultRuleMonitoring();
}) ?? getDefaultRuleMonitoring();
- const executionStatus = map(
+ const executionStatus = map(
state,
(ruleExecutionState) => executionStatusFromState(ruleExecutionState),
(err: ElasticsearchError) => executionStatusFromError(err)
@@ -992,11 +992,11 @@ export class TaskRunner<
this.inMemoryMetrics.increment(IN_MEMORY_METRICS.RULE_TIMEOUTS);
// Update the rule saved object with execution status
- const executionStatus: AlertExecutionStatus = {
+ const executionStatus: RuleExecutionStatus = {
lastExecutionDate: new Date(),
status: 'error',
error: {
- reason: AlertExecutionStatusErrorReasons.Timeout,
+ reason: RuleExecutionStatusErrorReasons.Timeout,
message: `${this.ruleType.id}:${ruleId}: execution cancelled due to timeout - exceeded rule type timeout of ${this.ruleType.ruleTaskTimeout}`,
},
};
diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts
index 68c005cc4b765..1e24ac986f015 100644
--- a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts
+++ b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts
@@ -8,9 +8,9 @@
import sinon from 'sinon';
import { usageCountersServiceMock } from 'src/plugins/usage_collection/server/usage_counters/usage_counters_service.mock';
import {
- AlertExecutorOptions,
- AlertTypeParams,
- AlertTypeState,
+ RuleExecutorOptions,
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
} from '../types';
@@ -32,7 +32,7 @@ import { actionsMock, actionsClientMock } from '../../../actions/server/mocks';
import { alertsMock, rulesClientMock } from '../mocks';
import { eventLoggerMock } from '../../../event_log/server/event_logger.mock';
import { IEventLogger } from '../../../event_log/server';
-import { Alert, RecoveredActionGroup } from '../../common';
+import { Rule, RecoveredActionGroup } from '../../common';
import { UntypedNormalizedRuleType } from '../rule_type_registry';
import { ruleTypeRegistryMock } from '../rule_type_registry.mock';
import { dataPluginMock } from '../../../../../src/plugins/data/server/mocks';
@@ -98,7 +98,7 @@ describe('Task Runner Cancel', () => {
afterAll(() => fakeTimer.restore());
const encryptedSavedObjectsClient = encryptedSavedObjectsMock.createClient();
- const services = alertsMock.createAlertServices();
+ const services = alertsMock.createRuleExecutorServices();
const actionsClient = actionsClientMock.create();
const rulesClient = rulesClientMock.create();
const ruleTypeRegistry = ruleTypeRegistryMock.create();
@@ -138,7 +138,7 @@ describe('Task Runner Cancel', () => {
const mockDate = new Date('2019-02-12T21:01:22.479Z');
- const mockedRuleSavedObject: Alert = {
+ const mockedRuleSavedObject: Rule = {
id: '1',
consumer: 'bar',
createdAt: mockDate,
@@ -402,9 +402,9 @@ describe('Task Runner Cancel', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -441,9 +441,9 @@ describe('Task Runner Cancel', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
@@ -476,9 +476,9 @@ describe('Task Runner Cancel', () => {
ruleType.executor.mockImplementation(
async ({
services: executorServices,
- }: AlertExecutorOptions<
- AlertTypeParams,
- AlertTypeState,
+ }: RuleExecutorOptions<
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
string
diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_factory.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_factory.ts
index 0ceced10e799b..2cba16152e198 100644
--- a/x-pack/plugins/alerting/server/task_runner/task_runner_factory.ts
+++ b/x-pack/plugins/alerting/server/task_runner/task_runner_factory.ts
@@ -21,10 +21,10 @@ import { RunContext } from '../../../task_manager/server';
import { EncryptedSavedObjectsClient } from '../../../encrypted_saved_objects/server';
import { PluginStartContract as ActionsPluginStartContract } from '../../../actions/server';
import {
- AlertTypeParams,
+ RuleTypeParams,
RuleTypeRegistry,
SpaceIdToNamespaceFunction,
- AlertTypeState,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext,
} from '../types';
@@ -70,9 +70,9 @@ export class TaskRunnerFactory {
}
public create<
- Params extends AlertTypeParams,
- ExtractedParams extends AlertTypeParams,
- State extends AlertTypeState,
+ Params extends RuleTypeParams,
+ ExtractedParams extends RuleTypeParams,
+ State extends RuleTypeState,
InstanceState extends AlertInstanceState,
InstanceContext extends AlertInstanceContext,
ActionGroupIds extends string,
diff --git a/x-pack/plugins/alerting/server/task_runner/transform_action_params.ts b/x-pack/plugins/alerting/server/task_runner/transform_action_params.ts
index 3f9fe9e9c59e0..387bdc00125f0 100644
--- a/x-pack/plugins/alerting/server/task_runner/transform_action_params.ts
+++ b/x-pack/plugins/alerting/server/task_runner/transform_action_params.ts
@@ -6,10 +6,10 @@
*/
import {
- AlertActionParams,
+ RuleActionParams,
AlertInstanceState,
AlertInstanceContext,
- AlertTypeParams,
+ RuleTypeParams,
} from '../types';
import { PluginStartContract as ActionsPluginStartContract } from '../../../actions/server';
@@ -26,8 +26,8 @@ interface TransformActionParamsOptions {
alertActionGroup: string;
alertActionGroupName: string;
alertActionSubgroup?: string;
- actionParams: AlertActionParams;
- alertParams: AlertTypeParams;
+ actionParams: RuleActionParams;
+ alertParams: RuleTypeParams;
state: AlertInstanceState;
kibanaBaseUrl?: string;
context: AlertInstanceContext;
@@ -51,7 +51,7 @@ export function transformActionParams({
state,
kibanaBaseUrl,
alertParams,
-}: TransformActionParamsOptions): AlertActionParams {
+}: TransformActionParamsOptions): RuleActionParams {
// when the list of variables we pass in here changes,
// the UI will need to be updated as well; see:
// x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.ts
diff --git a/x-pack/plugins/alerting/server/task_runner/types.ts b/x-pack/plugins/alerting/server/task_runner/types.ts
index d8483139a92b9..d5ad11f246c49 100644
--- a/x-pack/plugins/alerting/server/task_runner/types.ts
+++ b/x-pack/plugins/alerting/server/task_runner/types.ts
@@ -9,19 +9,19 @@ import { Dictionary } from 'lodash';
import { KibanaRequest, Logger } from 'kibana/server';
import {
ActionGroup,
- AlertAction,
+ RuleAction,
AlertInstanceContext,
AlertInstanceState,
- AlertTypeParams,
- AlertTypeState,
+ RuleTypeParams,
+ RuleTypeState,
IntervalSchedule,
RuleExecutionState,
RuleMonitoring,
RuleTaskState,
- SanitizedAlert,
+ SanitizedRule,
} from '../../common';
import { ConcreteTaskInstance } from '../../../task_manager/server';
-import { Alert as CreatedAlert } from '../alert';
+import { Alert } from '../alert';
import { IEventLogger } from '../../../event_log/server';
import { NormalizedRuleType } from '../rule_type_registry';
import { ExecutionHandler } from './create_execution_handler';
@@ -48,9 +48,9 @@ export interface TrackAlertDurationsParams<
InstanceState extends AlertInstanceState,
InstanceContext extends AlertInstanceContext
> {
- originalAlerts: Dictionary>;
- currentAlerts: Dictionary>;
- recoveredAlerts: Dictionary>;
+ originalAlerts: Dictionary>;
+ currentAlerts: Dictionary>;
+ recoveredAlerts: Dictionary>;
}
export interface GenerateNewAndRecoveredAlertEventsParams<
@@ -59,16 +59,16 @@ export interface GenerateNewAndRecoveredAlertEventsParams<
> {
eventLogger: IEventLogger;
executionId: string;
- originalAlerts: Dictionary>;
- currentAlerts: Dictionary>;
- recoveredAlerts: Dictionary>;
+ originalAlerts: Dictionary>;
+ currentAlerts: Dictionary>;
+ recoveredAlerts: Dictionary>;
ruleId: string;
ruleLabel: string;
namespace: string | undefined;
ruleType: NormalizedRuleType<
- AlertTypeParams,
- AlertTypeParams,
- AlertTypeState,
+ RuleTypeParams,
+ RuleTypeParams,
+ RuleTypeState,
{
[x: string]: unknown;
},
@@ -78,7 +78,7 @@ export interface GenerateNewAndRecoveredAlertEventsParams<
string,
string
>;
- rule: SanitizedAlert;
+ rule: SanitizedRule;
spaceId: string;
}
@@ -89,7 +89,7 @@ export interface ScheduleActionsForRecoveredAlertsParams<
> {
logger: Logger;
recoveryActionGroup: ActionGroup;
- recoveredAlerts: Dictionary>;
+ recoveredAlerts: Dictionary>;
executionHandler: ExecutionHandler;
mutedAlertIdsSet: Set;
ruleLabel: string;
@@ -103,8 +103,8 @@ export interface LogActiveAndRecoveredAlertsParams<
RecoveryActionGroupId extends string
> {
logger: Logger;
- activeAlerts: Dictionary>;
- recoveredAlerts: Dictionary>;
+ activeAlerts: Dictionary>;
+ recoveredAlerts: Dictionary>;
ruleLabel: string;
canSetRecoveryContext: boolean;
}
@@ -112,9 +112,9 @@ export interface LogActiveAndRecoveredAlertsParams<
// / ExecutionHandler
export interface CreateExecutionHandlerOptions<
- Params extends AlertTypeParams,
- ExtractedParams extends AlertTypeParams,
- State extends AlertTypeState,
+ Params extends RuleTypeParams,
+ ExtractedParams extends RuleTypeParams,
+ State extends RuleTypeState,
InstanceState extends AlertInstanceState,
InstanceContext extends AlertInstanceContext,
ActionGroupIds extends string,
@@ -126,7 +126,7 @@ export interface CreateExecutionHandlerOptions<
executionId: string;
tags?: string[];
actionsPlugin: ActionsPluginStartContract;
- actions: AlertAction[];
+ actions: RuleAction[];
spaceId: string;
apiKey: RawRule['apiKey'];
kibanaBaseUrl: string | undefined;
@@ -142,7 +142,7 @@ export interface CreateExecutionHandlerOptions<
logger: Logger;
eventLogger: IEventLogger;
request: KibanaRequest;
- ruleParams: AlertTypeParams;
+ ruleParams: RuleTypeParams;
supportsEphemeralTasks: boolean;
maxEphemeralActionsPerRule: number;
}
diff --git a/x-pack/plugins/alerting/server/types.ts b/x-pack/plugins/alerting/server/types.ts
index 10d191d9b43e4..cfd03f4edf184 100644
--- a/x-pack/plugins/alerting/server/types.ts
+++ b/x-pack/plugins/alerting/server/types.ts
@@ -23,23 +23,23 @@ import {
SavedObjectsClientContract,
} from '../../../../src/core/server';
import {
- Alert,
- AlertActionParams,
+ Rule,
+ RuleTypeParams,
+ RuleTypeState,
+ RuleActionParams,
+ RuleExecutionStatuses,
+ RuleExecutionStatusErrorReasons,
+ RuleExecutionStatusWarningReasons,
+ RuleNotifyWhenType,
ActionGroup,
- AlertTypeParams,
- AlertTypeState,
AlertInstanceContext,
AlertInstanceState,
- AlertExecutionStatuses,
- AlertExecutionStatusErrorReasons,
AlertsHealth,
- AlertNotifyWhenType,
WithoutReservedActionGroups,
ActionVariable,
SanitizedRuleConfig,
RuleMonitoring,
MappedParams,
- AlertExecutionStatusWarningReasons,
} from '../common';
import { LicenseType } from '../../licensing/server';
import { ISearchStartSearchSource } from '../../../../src/plugins/data/common';
@@ -69,7 +69,7 @@ export interface AlertingRequestHandlerContext extends RequestHandlerContext {
*/
export type AlertingRouter = IRouter;
-export interface AlertServices<
+export interface RuleExecutorServices<
InstanceState extends AlertInstanceState = AlertInstanceState,
InstanceContext extends AlertInstanceContext = AlertInstanceContext,
ActionGroupIds extends string = never
@@ -86,9 +86,9 @@ export interface AlertServices<
shouldStopExecution: () => boolean;
}
-export interface AlertExecutorOptions<
- Params extends AlertTypeParams = never,
- State extends AlertTypeState = never,
+export interface RuleExecutorOptions<
+ Params extends RuleTypeParams = never,
+ State extends RuleTypeState = never,
InstanceState extends AlertInstanceState = never,
InstanceContext extends AlertInstanceContext = never,
ActionGroupIds extends string = never
@@ -97,7 +97,7 @@ export interface AlertExecutorOptions<
executionId: string;
startedAt: Date;
previousStartedAt: Date | null;
- services: AlertServices;
+ services: RuleExecutorServices;
params: Params;
state: State;
rule: SanitizedRuleConfig;
@@ -109,29 +109,29 @@ export interface AlertExecutorOptions<
updatedBy: string | null;
}
-export interface RuleParamsAndRefs {
+export interface RuleParamsAndRefs {
references: SavedObjectReference[];
params: Params;
}
export type ExecutorType<
- Params extends AlertTypeParams = never,
- State extends AlertTypeState = never,
+ Params extends RuleTypeParams = never,
+ State extends RuleTypeState = never,
InstanceState extends AlertInstanceState = never,
InstanceContext extends AlertInstanceContext = never,
ActionGroupIds extends string = never
> = (
- options: AlertExecutorOptions
+ options: RuleExecutorOptions
) => Promise;
-export interface AlertTypeParamsValidator {
+export interface RuleTypeParamsValidator {
validate: (object: unknown) => Params;
}
export interface RuleType<
- Params extends AlertTypeParams = never,
- ExtractedParams extends AlertTypeParams = never,
- State extends AlertTypeState = never,
+ Params extends RuleTypeParams = never,
+ ExtractedParams extends RuleTypeParams = never,
+ State extends RuleTypeState = never,
InstanceState extends AlertInstanceState = never,
InstanceContext extends AlertInstanceContext = never,
ActionGroupIds extends string = never,
@@ -140,7 +140,7 @@ export interface RuleType<
id: string;
name: string;
validate?: {
- params?: AlertTypeParamsValidator;
+ params?: RuleTypeParamsValidator;
};
actionGroups: Array>;
defaultActionGroupId: ActionGroup['id'];
@@ -175,57 +175,57 @@ export interface RuleType<
config?: RuleTypeConfig;
}
export type UntypedRuleType = RuleType<
- AlertTypeParams,
- AlertTypeState,
+ RuleTypeParams,
+ RuleTypeState,
AlertInstanceState,
AlertInstanceContext
>;
-export interface RawAlertAction extends SavedObjectAttributes {
+export interface RawRuleAction extends SavedObjectAttributes {
group: string;
actionRef: string;
actionTypeId: string;
- params: AlertActionParams;
+ params: RuleActionParams;
}
-export interface AlertMeta extends SavedObjectAttributes {
+export interface RuleMeta extends SavedObjectAttributes {
versionApiKeyLastmodified?: string;
}
// note that the `error` property is "null-able", as we're doing a partial
-// update on the alert when we update this data, but need to ensure we
+// update on the rule when we update this data, but need to ensure we
// delete any previous error if the current status has no error
export interface RawRuleExecutionStatus extends SavedObjectAttributes {
- status: AlertExecutionStatuses;
+ status: RuleExecutionStatuses;
lastExecutionDate: string;
lastDuration?: number;
error: null | {
- reason: AlertExecutionStatusErrorReasons;
+ reason: RuleExecutionStatusErrorReasons;
message: string;
};
warning: null | {
- reason: AlertExecutionStatusWarningReasons;
+ reason: RuleExecutionStatusWarningReasons;
message: string;
};
}
-export type PartialAlert = Pick, 'id'> &
- Partial, 'id'>>;
+export type PartialRule = Pick, 'id'> &
+ Partial, 'id'>>;
-export interface AlertWithLegacyId extends Alert {
+export interface RuleWithLegacyId extends Rule {
legacyId: string | null;
}
-export type SanitizedRuleWithLegacyId = Omit<
- AlertWithLegacyId,
+export type SanitizedRuleWithLegacyId = Omit<
+ RuleWithLegacyId,
'apiKey'
>;
-export type PartialAlertWithLegacyId = Pick<
- AlertWithLegacyId,
+export type PartialRuleWithLegacyId = Pick<
+ RuleWithLegacyId,
'id'
> &
- Partial, 'id'>>;
+ Partial, 'id'>>;
export interface RawRule extends SavedObjectAttributes {
enabled: boolean;
@@ -235,7 +235,7 @@ export interface RawRule extends SavedObjectAttributes {
consumer: string;
legacyId: string | null;
schedule: SavedObjectAttributes;
- actions: RawAlertAction[];
+ actions: RawRuleAction[];
params: SavedObjectAttributes;
mapped_params?: MappedParams;
scheduledTaskId?: string | null;
@@ -246,28 +246,15 @@ export interface RawRule extends SavedObjectAttributes {
apiKey: string | null;
apiKeyOwner: string | null;
throttle: string | null;
- notifyWhen: AlertNotifyWhenType | null;
+ notifyWhen: RuleNotifyWhenType | null;
muteAll: boolean;
mutedInstanceIds: string[];
- meta?: AlertMeta;
+ meta?: RuleMeta;
executionStatus: RawRuleExecutionStatus;
monitoring?: RuleMonitoring;
snoozeEndTime?: string | null; // Remove ? when this parameter is made available in the public API
}
-export type AlertInfoParams = Pick<
- RawRule,
- | 'params'
- | 'throttle'
- | 'notifyWhen'
- | 'muteAll'
- | 'mutedInstanceIds'
- | 'name'
- | 'tags'
- | 'createdBy'
- | 'updatedBy'
->;
-
export interface AlertingPlugin {
setup: PluginSetupContract;
start: PluginStartContract;
diff --git a/x-pack/plugins/alerting/server/usage/alerting_telemetry.test.ts b/x-pack/plugins/alerting/server/usage/alerting_telemetry.test.ts
index 3bb64ad00a194..61383656e67d5 100644
--- a/x-pack/plugins/alerting/server/usage/alerting_telemetry.test.ts
+++ b/x-pack/plugins/alerting/server/usage/alerting_telemetry.test.ts
@@ -15,6 +15,7 @@ import {
getExecutionsPerDayCount,
getExecutionTimeoutsPerDayCount,
getFailedAndUnrecognizedTasksPerDay,
+ parsePercentileAggsByRuleType,
} from './alerting_telemetry';
describe('alerting telemetry', () => {
@@ -181,6 +182,41 @@ Object {
avgTotalSearchDuration: {
value: 30.642857142857142,
},
+ percentileScheduledActions: {
+ values: {
+ '50.0': 4.0,
+ '90.0': 26.0,
+ '99.0': 26.0,
+ },
+ },
+ aggsByType: {
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
+ {
+ key: '.index-threshold',
+ doc_count: 149,
+ percentileScheduledActions: {
+ values: {
+ '50.0': 4.0,
+ '90.0': 26.0,
+ '99.0': 26.0,
+ },
+ },
+ },
+ {
+ key: 'logs.alert.document.count',
+ doc_count: 1,
+ percentileScheduledActions: {
+ values: {
+ '50.0': 10.0,
+ '90.0': 10.0,
+ '99.0': 10.0,
+ },
+ },
+ },
+ ],
+ },
},
hits: {
hits: [],
@@ -228,6 +264,25 @@ Object {
},
countTotal: 4,
countTotalFailures: 4,
+ scheduledActionsPercentiles: {
+ p50: 4,
+ p90: 26,
+ p99: 26,
+ },
+ scheduledActionsPercentilesByType: {
+ p50: {
+ '__index-threshold': 4,
+ logs__alert__document__count: 10,
+ },
+ p90: {
+ '__index-threshold': 26,
+ logs__alert__document__count: 10,
+ },
+ p99: {
+ '__index-threshold': 26,
+ logs__alert__document__count: 10,
+ },
+ },
});
});
@@ -316,4 +371,150 @@ Object {
countTotal: 5,
});
});
+
+ test('parsePercentileAggsByRuleType', () => {
+ const aggsByType = {
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
+ {
+ key: '.index-threshold',
+ doc_count: 149,
+ percentileScheduledActions: {
+ values: {
+ '50.0': 4.0,
+ '90.0': 26.0,
+ '99.0': 26.0,
+ },
+ },
+ },
+ {
+ key: 'logs.alert.document.count',
+ doc_count: 1,
+ percentileScheduledActions: {
+ values: {
+ '50.0': 10.0,
+ '90.0': 10.0,
+ '99.0': 10.0,
+ },
+ },
+ },
+ {
+ key: 'document.test.',
+ doc_count: 1,
+ percentileScheduledActions: {
+ values: {
+ '50.0': null,
+ '90.0': null,
+ '99.0': null,
+ },
+ },
+ },
+ ],
+ };
+ expect(
+ parsePercentileAggsByRuleType(aggsByType.buckets, 'percentileScheduledActions.values')
+ ).toEqual({
+ p50: {
+ '__index-threshold': 4,
+ document__test__: 0,
+ logs__alert__document__count: 10,
+ },
+ p90: {
+ '__index-threshold': 26,
+ document__test__: 0,
+ logs__alert__document__count: 10,
+ },
+ p99: {
+ '__index-threshold': 26,
+ document__test__: 0,
+ logs__alert__document__count: 10,
+ },
+ });
+ });
+
+ test('parsePercentileAggsByRuleType handles unknown path', () => {
+ const aggsByType = {
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
+ {
+ key: '.index-threshold',
+ doc_count: 149,
+ percentileScheduledActions: {
+ values: {
+ '50.0': 4.0,
+ '90.0': 26.0,
+ '99.0': 26.0,
+ },
+ },
+ },
+ {
+ key: 'logs.alert.document.count',
+ doc_count: 1,
+ percentileScheduledActions: {
+ values: {
+ '50.0': 10.0,
+ '90.0': 10.0,
+ '99.0': 10.0,
+ },
+ },
+ },
+ ],
+ };
+ expect(parsePercentileAggsByRuleType(aggsByType.buckets, 'foo.values')).toEqual({
+ p50: {},
+ p90: {},
+ p99: {},
+ });
+ });
+
+ test('parsePercentileAggsByRuleType handles unrecognized percentiles', () => {
+ const aggsByType = {
+ doc_count_error_upper_bound: 0,
+ sum_other_doc_count: 0,
+ buckets: [
+ {
+ key: '.index-threshold',
+ doc_count: 149,
+ percentileScheduledActions: {
+ values: {
+ '50.0': 4.0,
+ '75.0': 8.0,
+ '90.0': 26.0,
+ '99.0': 26.0,
+ },
+ },
+ },
+ {
+ key: 'logs.alert.document.count',
+ doc_count: 1,
+ percentileScheduledActions: {
+ values: {
+ '50.0': 10.0,
+ '75.0': 10.0,
+ '90.0': 10.0,
+ '99.0': 10.0,
+ },
+ },
+ },
+ ],
+ };
+ expect(
+ parsePercentileAggsByRuleType(aggsByType.buckets, 'percentileScheduledActions.values')
+ ).toEqual({
+ p50: {
+ '__index-threshold': 4,
+ logs__alert__document__count: 10,
+ },
+ p90: {
+ '__index-threshold': 26,
+ logs__alert__document__count: 10,
+ },
+ p99: {
+ '__index-threshold': 26,
+ logs__alert__document__count: 10,
+ },
+ });
+ });
});
diff --git a/x-pack/plugins/alerting/server/usage/alerting_telemetry.ts b/x-pack/plugins/alerting/server/usage/alerting_telemetry.ts
index 4fbad593d1600..2e360374faa42 100644
--- a/x-pack/plugins/alerting/server/usage/alerting_telemetry.ts
+++ b/x-pack/plugins/alerting/server/usage/alerting_telemetry.ts
@@ -5,8 +5,17 @@
* 2.0.
*/
+import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { ElasticsearchClient } from 'kibana/server';
+import { get, merge } from 'lodash';
import { AlertingUsage } from './types';
+import { NUM_ALERTING_RULE_TYPES } from './alerting_usage_collector';
+
+const percentileFieldNameMapping: Record = {
+ '50.0': 'p50',
+ '90.0': 'p90',
+ '99.0': 'p99',
+};
const ruleTypeMetric = {
scripted_metric: {
@@ -38,6 +47,13 @@ const ruleTypeMetric = {
},
};
+const scheduledActionsPercentilesAgg = {
+ percentiles: {
+ field: 'kibana.alert.rule.execution.metrics.number_of_scheduled_actions',
+ percents: [50, 90, 99],
+ },
+};
+
const ruleTypeExecutionsWithDurationMetric = {
scripted_metric: {
init_script:
@@ -409,6 +425,16 @@ export async function getExecutionsPerDayCount(
avgTotalSearchDuration: {
avg: { field: 'kibana.alert.rule.execution.metrics.total_search_duration_ms' },
},
+ percentileScheduledActions: scheduledActionsPercentilesAgg,
+ aggsByType: {
+ terms: {
+ field: 'rule.category',
+ size: NUM_ALERTING_RULE_TYPES,
+ },
+ aggs: {
+ percentileScheduledActions: scheduledActionsPercentilesAgg,
+ },
+ },
},
},
});
@@ -439,6 +465,14 @@ export async function getExecutionsPerDayCount(
searchResult.aggregations.avgTotalSearchDuration.value
);
+ const aggsScheduledActionsPercentiles =
+ // @ts-expect-error aggegation type is not specified
+ searchResult.aggregations.percentileScheduledActions.values;
+
+ const aggsByTypeBuckets =
+ // @ts-expect-error aggegation type is not specified
+ searchResult.aggregations.aggsByType.buckets;
+
const executionFailuresAggregations = searchResult.aggregations as {
failuresByReason: { value: { reasons: Record> } };
};
@@ -537,6 +571,21 @@ export async function getExecutionsPerDayCount(
}),
{}
),
+ scheduledActionsPercentiles: Object.keys(aggsScheduledActionsPercentiles).reduce(
+ // ES DSL aggregations are returned as `any` by esClient.search
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ (acc: any, curr: string) => ({
+ ...acc,
+ ...(percentileFieldNameMapping[curr]
+ ? { [percentileFieldNameMapping[curr]]: aggsScheduledActionsPercentiles[curr] }
+ : {}),
+ }),
+ {}
+ ),
+ scheduledActionsPercentilesByType: parsePercentileAggsByRuleType(
+ aggsByTypeBuckets,
+ 'percentileScheduledActions.values'
+ ),
};
}
@@ -701,3 +750,30 @@ function replaceDotSymbolsInRuleTypeIds(ruleTypeIdObj: Record) {
{}
);
}
+
+export function parsePercentileAggsByRuleType(
+ aggsByType: estypes.AggregationsStringTermsBucketKeys[],
+ path: string
+) {
+ return (aggsByType ?? []).reduce(
+ (acc, curr) => {
+ const percentiles = get(curr, path, {});
+ return merge(
+ acc,
+ Object.keys(percentiles).reduce((pacc, pcurr) => {
+ return {
+ ...pacc,
+ ...(percentileFieldNameMapping[pcurr]
+ ? {
+ [percentileFieldNameMapping[pcurr]]: {
+ [replaceDotSymbols(curr.key)]: percentiles[pcurr] ?? 0,
+ },
+ }
+ : {}),
+ };
+ }, {})
+ );
+ },
+ { p50: {}, p90: {}, p99: {} }
+ );
+}
diff --git a/x-pack/plugins/alerting/server/usage/alerting_usage_collector.ts b/x-pack/plugins/alerting/server/usage/alerting_usage_collector.ts
index f375e758a8c9b..b0990bab9491d 100644
--- a/x-pack/plugins/alerting/server/usage/alerting_usage_collector.ts
+++ b/x-pack/plugins/alerting/server/usage/alerting_usage_collector.ts
@@ -56,6 +56,8 @@ const byTypeSchema: MakeSchemaFrom['count_by_type'] = {
xpack__ml__anomaly_detection_jobs_health: { type: 'long' }, // eslint-disable-line @typescript-eslint/naming-convention
};
+export const NUM_ALERTING_RULE_TYPES = Object.keys(byTypeSchema).length;
+
const byReasonSchema: MakeSchemaFrom['count_rules_executions_failured_by_reason_per_day'] =
{
// TODO: Find out an automated way to populate the keys or reformat these into an array (and change the Remote Telemetry indexer accordingly)
@@ -66,6 +68,20 @@ const byReasonSchema: MakeSchemaFrom['count_rules_executions_fail
unknown: { type: 'long' },
};
+const byPercentileSchema: MakeSchemaFrom['percentile_num_scheduled_actions_per_day'] =
+ {
+ p50: { type: 'long' },
+ p90: { type: 'long' },
+ p99: { type: 'long' },
+ };
+
+const byPercentileSchemaByType: MakeSchemaFrom['percentile_num_scheduled_actions_by_type_per_day'] =
+ {
+ p50: byTypeSchema,
+ p90: byTypeSchema,
+ p99: byTypeSchema,
+ };
+
const byReasonSchemaByType: MakeSchemaFrom['count_rules_executions_failured_by_reason_by_type_per_day'] =
{
// TODO: Find out an automated way to populate the keys or reformat these into an array (and change the Remote Telemetry indexer accordingly)
@@ -160,6 +176,16 @@ export function createAlertingUsageCollector(
avg_es_search_duration_by_type_per_day: {},
avg_total_search_duration_per_day: 0,
avg_total_search_duration_by_type_per_day: {},
+ percentile_num_scheduled_actions_per_day: {
+ p50: 0,
+ p90: 0,
+ p99: 0,
+ },
+ percentile_num_scheduled_actions_by_type_per_day: {
+ p50: {},
+ p90: {},
+ p99: {},
+ },
};
}
},
@@ -211,6 +237,8 @@ export function createAlertingUsageCollector(
avg_es_search_duration_by_type_per_day: byTypeSchema,
avg_total_search_duration_per_day: { type: 'long' },
avg_total_search_duration_by_type_per_day: byTypeSchema,
+ percentile_num_scheduled_actions_per_day: byPercentileSchema,
+ percentile_num_scheduled_actions_by_type_per_day: byPercentileSchemaByType,
},
});
}
diff --git a/x-pack/plugins/alerting/server/usage/task.ts b/x-pack/plugins/alerting/server/usage/task.ts
index 7aee043653806..0d0d2d802a3fb 100644
--- a/x-pack/plugins/alerting/server/usage/task.ts
+++ b/x-pack/plugins/alerting/server/usage/task.ts
@@ -144,6 +144,10 @@ export function telemetryTaskRunner(
avg_total_search_duration_per_day: dailyExecutionCounts.avgTotalSearchDuration,
avg_total_search_duration_by_type_per_day:
dailyExecutionCounts.avgTotalSearchDurationByType,
+ percentile_num_scheduled_actions_per_day:
+ dailyExecutionCounts.scheduledActionsPercentiles,
+ percentile_num_scheduled_actions_by_type_per_day:
+ dailyExecutionCounts.scheduledActionsPercentilesByType,
},
runAt: getNextMidnight(),
};
diff --git a/x-pack/plugins/alerting/server/usage/types.ts b/x-pack/plugins/alerting/server/usage/types.ts
index a03483bd54007..00bd3b46f91b1 100644
--- a/x-pack/plugins/alerting/server/usage/types.ts
+++ b/x-pack/plugins/alerting/server/usage/types.ts
@@ -25,6 +25,16 @@ export interface AlertingUsage {
string,
Record
>;
+ percentile_num_scheduled_actions_per_day: {
+ p50: number;
+ p90: number;
+ p99: number;
+ };
+ percentile_num_scheduled_actions_by_type_per_day: {
+ p50: Record;
+ p90: Record;
+ p99: Record;
+ };
avg_execution_time_per_day: number;
avg_execution_time_by_type_per_day: Record;
avg_es_search_duration_per_day: number;
diff --git a/x-pack/plugins/apm/server/routes/alerts/alerting_es_client.ts b/x-pack/plugins/apm/server/routes/alerts/alerting_es_client.ts
index 876d02137c3f8..ebab01464de6b 100644
--- a/x-pack/plugins/apm/server/routes/alerts/alerting_es_client.ts
+++ b/x-pack/plugins/apm/server/routes/alerts/alerting_es_client.ts
@@ -9,13 +9,13 @@ import {
ESSearchRequest,
ESSearchResponse,
} from '../../../../../../src/core/types/elasticsearch';
-import { AlertServices } from '../../../../alerting/server';
+import { RuleExecutorServices } from '../../../../alerting/server';
export async function alertingEsClient({
scopedClusterClient,
params,
}: {
- scopedClusterClient: AlertServices<
+ scopedClusterClient: RuleExecutorServices<
never,
never,
never
diff --git a/x-pack/plugins/cases/public/client/ui/get_all_cases_selector_modal.tsx b/x-pack/plugins/cases/public/client/ui/get_all_cases_selector_modal.tsx
index 18821d24e3053..1666557ec2648 100644
--- a/x-pack/plugins/cases/public/client/ui/get_all_cases_selector_modal.tsx
+++ b/x-pack/plugins/cases/public/client/ui/get_all_cases_selector_modal.tsx
@@ -18,19 +18,15 @@ const AllCasesSelectorModalLazy: React.FC = lazy(
export const getAllCasesSelectorModalLazy = ({
owner,
userCanCrud,
- alertData,
hiddenStatuses,
onRowClick,
- updateCase,
onClose,
}: GetAllCasesSelectorModalProps) => (
}>
@@ -42,20 +38,14 @@ export const getAllCasesSelectorModalLazy = ({
* cases provider. to be further refactored https://github.com/elastic/kibana/issues/123183
*/
export const getAllCasesSelectorModalNoProviderLazy = ({
- alertData,
- attachments,
hiddenStatuses,
onRowClick,
- updateCase,
onClose,
}: AllCasesSelectorModalProps) => (
}>
diff --git a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx
index 88aad5fb64408..c8e656b8117eb 100644
--- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx
@@ -17,7 +17,7 @@ import { TestProviders } from '../../common/mock';
import { casesStatus, useGetCasesMockState, mockCase, connectorsMock } from '../../containers/mock';
import { StatusAll } from '../../../common/ui/types';
-import { CaseStatuses, CommentType } from '../../../common/api';
+import { CaseStatuses } from '../../../common/api';
import { SECURITY_SOLUTION_OWNER } from '../../../common/constants';
import { getEmptyTagValue } from '../empty_value';
import { useDeleteCases } from '../../containers/use_delete_cases';
@@ -515,46 +515,6 @@ describe('AllCasesListGeneric', () => {
});
});
- it('should call postComment when a case is selected in isSelectorView=true and has attachments', async () => {
- const postCommentMockedValue = { status: { isLoading: false }, postComment: jest.fn() };
- usePostCommentMock.mockReturnValueOnce(postCommentMockedValue);
- const wrapper = mount(
-
-
-
- );
- wrapper.find('[data-test-subj="cases-table-row-select-1"]').first().simulate('click');
- await waitFor(() => {
- expect(postCommentMockedValue.postComment).toHaveBeenCalledWith({
- caseId: '1',
- data: {
- alertId: 'alert-id-201',
- index: 'index-id-1',
- owner: 'test',
- rule: {
- id: 'rule-id-1',
- name: 'Awesome myrule',
- },
- type: 'alert',
- },
- });
- });
- });
-
it('should call onRowClick with no cases and isSelectorView=true', async () => {
useGetCasesMock.mockReturnValue({
...defaultGetCases,
diff --git a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx
index ffcb7a1abe416..5eac485e24c7b 100644
--- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx
@@ -16,14 +16,8 @@ import {
FilterOptions,
SortFieldCase,
} from '../../../common/ui/types';
-import {
- CaseStatuses,
- CommentRequestAlertType,
- caseStatuses,
- CommentType,
-} from '../../../common/api';
+import { CaseStatuses, caseStatuses } from '../../../common/api';
import { useGetCases } from '../../containers/use_get_cases';
-import { usePostComment } from '../../containers/use_post_comment';
import { useAvailableCasesOwners } from '../app/use_available_owners';
import { useCasesColumns } from './columns';
@@ -33,7 +27,6 @@ import { EuiBasicTableOnChange } from './types';
import { CasesTable } from './table';
import { useConnectors } from '../../containers/configure/use_connectors';
import { useCasesContext } from '../cases_context/use_cases_context';
-import { CaseAttachments } from '../../types';
const ProgressLoader = styled(EuiProgress)`
${({ $isShow }: { $isShow: boolean }) =>
@@ -52,28 +45,14 @@ const getSortField = (field: string): SortFieldCase =>
field === SortFieldCase.closedAt ? SortFieldCase.closedAt : SortFieldCase.createdAt;
export interface AllCasesListProps {
- /**
- * @deprecated Use the attachments prop instead
- */
- alertData?: Omit;
hiddenStatuses?: CaseStatusWithAllStatus[];
isSelectorView?: boolean;
onRowClick?: (theCase?: Case) => void;
- updateCase?: (newCase: Case) => void;
doRefresh?: () => void;
- attachments?: CaseAttachments;
}
export const AllCasesList = React.memo(
- ({
- alertData,
- attachments,
- hiddenStatuses = [],
- isSelectorView = false,
- onRowClick,
- updateCase,
- doRefresh,
- }) => {
+ ({ hiddenStatuses = [], isSelectorView = false, onRowClick, doRefresh }) => {
const { owner, userCanCrud } = useCasesContext();
const hasOwner = !!owner.length;
const availableSolutions = useAvailableCasesOwners();
@@ -97,8 +76,6 @@ export const AllCasesList = React.memo(
setSelectedCases,
} = useGetCases({ initialFilterOptions });
- // Post Comment to Case
- const { postComment, isLoading: isCommentUpdating } = usePostComment();
const { connectors } = useConnectors();
const sorting = useMemo(
@@ -181,19 +158,6 @@ export const AllCasesList = React.memo(
const showActions = userCanCrud && !isSelectorView;
- // TODO remove the deprecated alertData field when cleaning up
- // code https://github.com/elastic/kibana/issues/123183
- // This code is to support the deprecated alertData prop
- const toAttach = useMemo((): CaseAttachments | undefined => {
- if (attachments !== undefined || alertData !== undefined) {
- const _toAttach = attachments ?? [];
- if (alertData !== undefined) {
- _toAttach.push({ ...alertData, type: CommentType.alert });
- }
- return _toAttach;
- }
- }, [alertData, attachments]);
-
const columns = useCasesColumns({
dispatchUpdateCaseProperty,
filterStatus: filterOptions.status,
@@ -204,9 +168,6 @@ export const AllCasesList = React.memo(
userCanCrud,
connectors,
onRowClick,
- attachments: toAttach,
- postComment,
- updateCase,
showSolutionColumn: !hasOwner && availableSolutions.length > 1,
});
@@ -243,7 +204,7 @@ export const AllCasesList = React.memo(
size="xs"
color="accent"
className="essentialAnimation"
- $isShow={(isCasesLoading || isLoading || isCommentUpdating) && !isDataEmpty}
+ $isShow={(isCasesLoading || isLoading) && !isDataEmpty}
/>
(
goToCreateCase={onRowClick}
handleIsLoading={handleIsLoading}
isCasesLoading={isCasesLoading}
- isCommentUpdating={isCommentUpdating}
+ isCommentUpdating={isCasesLoading}
isDataEmpty={isDataEmpty}
isSelectorView={isSelectorView}
onChange={tableOnChangeCallback}
diff --git a/x-pack/plugins/cases/public/components/all_cases/columns.tsx b/x-pack/plugins/cases/public/components/all_cases/columns.tsx
index a05673d3e095a..543e6ef6f4871 100644
--- a/x-pack/plugins/cases/public/components/all_cases/columns.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/columns.tsx
@@ -38,8 +38,6 @@ import { useApplicationCapabilities, useKibana } from '../../common/lib/kibana';
import { StatusContextMenu } from '../case_action_bar/status_context_menu';
import { TruncatedText } from '../truncated_text';
import { getConnectorIcon } from '../utils';
-import { PostComment } from '../../containers/use_post_comment';
-import { CaseAttachments } from '../../types';
import type { CasesOwners } from '../../client/helpers/can_use_cases';
import { useCasesFeatures } from '../cases_context/use_cases_features';
@@ -73,9 +71,6 @@ export interface GetCasesColumn {
userCanCrud: boolean;
connectors?: ActionConnector[];
onRowClick?: (theCase: Case) => void;
- attachments?: CaseAttachments;
- postComment?: (args: PostComment) => Promise;
- updateCase?: (newCase: Case) => void;
showSolutionColumn?: boolean;
}
@@ -89,9 +84,6 @@ export const useCasesColumns = ({
userCanCrud,
connectors = [],
onRowClick,
- attachments,
- postComment,
- updateCase,
showSolutionColumn,
}: GetCasesColumn): CasesColumns[] => {
// Delete case
@@ -141,24 +133,11 @@ export const useCasesColumns = ({
const assignCaseAction = useCallback(
async (theCase: Case) => {
- // TODO currently the API only supports to add a comment at the time
- // once the API is updated we should use bulk post comment #124814
- // this operation is intentionally made in sequence
- if (attachments !== undefined && attachments.length > 0) {
- for (const attachment of attachments) {
- await postComment?.({
- caseId: theCase.id,
- data: attachment,
- });
- }
- updateCase?.(theCase);
- }
-
if (onRowClick) {
onRowClick(theCase);
}
},
- [attachments, onRowClick, postComment, updateCase]
+ [onRowClick]
);
useEffect(() => {
diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.test.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.test.tsx
index ef01ead1cb07d..eba8888f3367a 100644
--- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.test.tsx
@@ -11,7 +11,6 @@ import { mount } from 'enzyme';
import { AllCasesSelectorModal } from '.';
import { TestProviders } from '../../../common/mock';
import { AllCasesList } from '../all_cases_list';
-import { SECURITY_SOLUTION_OWNER } from '../../../../common/constants';
jest.mock('../all_cases_list');
@@ -19,7 +18,6 @@ const onRowClick = jest.fn();
const defaultProps = {
onRowClick,
};
-const updateCase = jest.fn();
describe('AllCasesSelectorModal', () => {
beforeEach(() => {
@@ -50,17 +48,7 @@ describe('AllCasesSelectorModal', () => {
it('pass the correct props to getAllCases method', () => {
const fullProps = {
...defaultProps,
- alertData: {
- rule: {
- id: 'rule-id',
- name: 'rule',
- },
- index: 'index-id',
- alertId: 'alert-id',
- owner: SECURITY_SOLUTION_OWNER,
- },
hiddenStatuses: [],
- updateCase,
};
mount(
@@ -72,10 +60,8 @@ describe('AllCasesSelectorModal', () => {
// @ts-ignore idk what this mock style is but it works ¯\_(ツ)_/¯
expect(AllCasesList.type.mock.calls[0][0]).toEqual(
expect.objectContaining({
- alertData: fullProps.alertData,
hiddenStatuses: fullProps.hiddenStatuses,
isSelectorView: true,
- updateCase,
})
);
});
diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.tsx
index ba553b28a34e0..581ecef47ad88 100644
--- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.tsx
@@ -16,20 +16,13 @@ import {
} from '@elastic/eui';
import styled from 'styled-components';
import { Case, CaseStatusWithAllStatus } from '../../../../common/ui/types';
-import { CommentRequestAlertType } from '../../../../common/api';
import * as i18n from '../../../common/translations';
import { AllCasesList } from '../all_cases_list';
-import { CaseAttachments } from '../../../types';
+
export interface AllCasesSelectorModalProps {
- /**
- * @deprecated Use the attachments prop instead
- */
- alertData?: Omit;
hiddenStatuses?: CaseStatusWithAllStatus[];
onRowClick?: (theCase?: Case) => void;
- updateCase?: (newCase: Case) => void;
onClose?: () => void;
- attachments?: CaseAttachments;
}
const Modal = styled(EuiModal)`
@@ -40,7 +33,7 @@ const Modal = styled(EuiModal)`
`;
export const AllCasesSelectorModal = React.memo(
- ({ alertData, attachments, hiddenStatuses, onRowClick, updateCase, onClose }) => {
+ ({ hiddenStatuses, onRowClick, onClose }) => {
const [isModalOpen, setIsModalOpen] = useState(true);
const closeModal = useCallback(() => {
if (onClose) {
@@ -66,12 +59,9 @@ export const AllCasesSelectorModal = React.memo(
diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx
index b0e316e891744..25360800554b2 100644
--- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx
@@ -5,42 +5,82 @@
* 2.0.
*/
-/* eslint-disable react/display-name */
-
-import { renderHook } from '@testing-library/react-hooks';
+import { waitFor } from '@testing-library/dom';
+import { act, renderHook } from '@testing-library/react-hooks';
+import userEvent from '@testing-library/user-event';
import React from 'react';
-import { CaseStatuses, StatusAll } from '../../../../common';
+import AllCasesSelectorModal from '.';
+import { Case, CaseStatuses, StatusAll } from '../../../../common';
+import { AppMockRenderer, createAppMockRenderer } from '../../../common/mock';
+import { useCasesToast } from '../../../common/use_cases_toast';
+import { alertComment } from '../../../containers/mock';
+import { usePostComment } from '../../../containers/use_post_comment';
+import { SupportedCaseAttachment } from '../../../types';
import { CasesContext } from '../../cases_context';
import { CasesContextStoreActionsList } from '../../cases_context/cases_context_reducer';
import { useCasesAddToExistingCaseModal } from './use_cases_add_to_existing_case_modal';
+
jest.mock('../../../common/use_cases_toast');
+jest.mock('../../../containers/use_post_comment');
+// dummy mock, will call onRowclick when rendering
+jest.mock('./all_cases_selector_modal', () => {
+ return {
+ AllCasesSelectorModal: jest.fn(),
+ };
+});
+
+const useCasesToastMock = useCasesToast as jest.Mock;
+
+const AllCasesSelectorModalMock = AllCasesSelectorModal as unknown as jest.Mock;
+
+// test component to test the hook integration
+const TestComponent: React.FC = () => {
+ const hook = useCasesAddToExistingCaseModal({
+ attachments: [alertComment as SupportedCaseAttachment],
+ });
+
+ const onClick = () => {
+ hook.open();
+ };
+
+ return ;
+};
+
+const usePostCommentMock = usePostComment as jest.Mock;
describe('use cases add to existing case modal hook', () => {
+ usePostCommentMock.mockReturnValue({
+ postComment: jest.fn(),
+ });
+
const dispatch = jest.fn();
- let wrapper: React.FC;
+ let appMockRender: AppMockRenderer;
+ const wrapper: React.FC = ({ children }) => {
+ return (
+
+ {children}
+
+ );
+ };
+
const defaultParams = () => {
return { onRowClick: jest.fn() };
};
beforeEach(() => {
+ appMockRender = createAppMockRenderer();
dispatch.mockReset();
- wrapper = ({ children }) => {
- return (
-
- {children}
-
- );
- };
+ AllCasesSelectorModalMock.mockReset();
});
it('should throw if called outside of a cases context', () => {
@@ -89,4 +129,93 @@ describe('use cases add to existing case modal hook', () => {
})
);
});
+
+ it('should call postComment when a case is selected and show a toast message', async () => {
+ const mockedPostMessage = jest.fn();
+ usePostCommentMock.mockReturnValueOnce({
+ postComment: mockedPostMessage,
+ });
+
+ const mockedToastSuccess = jest.fn();
+ useCasesToastMock.mockReturnValue({
+ showSuccessAttach: mockedToastSuccess,
+ });
+
+ AllCasesSelectorModalMock.mockImplementation(({ onRowClick }) => {
+ onRowClick({ id: 'test' } as Case);
+ return null;
+ });
+
+ const result = appMockRender.render();
+ userEvent.click(result.getByTestId('open-modal'));
+
+ await waitFor(() => {
+ expect(mockedPostMessage).toHaveBeenCalledWith({
+ caseId: 'test',
+ data: alertComment,
+ throwOnError: true,
+ });
+ });
+ expect(mockedToastSuccess).toHaveBeenCalled();
+ });
+
+ it('should not call postComment nor show toast success when a case is not selected', async () => {
+ const mockedPostMessage = jest.fn();
+ usePostCommentMock.mockReturnValueOnce({
+ postComment: mockedPostMessage,
+ });
+
+ const mockedToastSuccess = jest.fn();
+ useCasesToastMock.mockReturnValue({
+ showSuccessAttach: mockedToastSuccess,
+ });
+
+ AllCasesSelectorModalMock.mockImplementation(({ onRowClick }) => {
+ onRowClick();
+ return null;
+ });
+
+ const result = appMockRender.render();
+ userEvent.click(result.getByTestId('open-modal'));
+ // give a small delay for the reducer to run
+
+ act(() => {
+ expect(mockedPostMessage).not.toHaveBeenCalled();
+ expect(mockedToastSuccess).not.toHaveBeenCalled();
+ });
+ });
+
+ it('should not show toast success when a case is selected with attachments and fails to update attachments', async () => {
+ const mockedPostMessage = jest.fn().mockRejectedValue(new Error('Impossible'));
+ usePostCommentMock.mockReturnValueOnce({
+ postComment: mockedPostMessage,
+ });
+
+ const mockedToast = jest.fn();
+ useCasesToastMock.mockReturnValue({
+ showSuccessAttach: mockedToast,
+ });
+
+ // simulate a case selected
+ AllCasesSelectorModalMock.mockImplementation(({ onRowClick }) => {
+ onRowClick({ id: 'test' } as Case);
+ return null;
+ });
+
+ const result = appMockRender.render();
+ userEvent.click(result.getByTestId('open-modal'));
+
+ await waitFor(() => {
+ expect(mockedPostMessage).toHaveBeenCalledWith({
+ caseId: 'test',
+ data: alertComment,
+ throwOnError: true,
+ });
+ });
+
+ act(() => {
+ expect(mockedPostMessage).toHaveBeenCalled();
+ expect(mockedToast).not.toHaveBeenCalled();
+ });
+ });
});
diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx
index 5d30c95227e2b..651b01c2242f3 100644
--- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx
+++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx
@@ -13,10 +13,13 @@ import { Case } from '../../../containers/types';
import { CasesContextStoreActionsList } from '../../cases_context/cases_context_reducer';
import { useCasesContext } from '../../cases_context/use_cases_context';
import { useCasesAddToNewCaseFlyout } from '../../create/flyout/use_cases_add_to_new_case_flyout';
+import { CaseAttachments } from '../../../types';
+import { usePostComment } from '../../../containers/use_post_comment';
type AddToExistingFlyoutProps = AllCasesSelectorModalProps & {
toastTitle?: string;
toastContent?: string;
+ attachments?: CaseAttachments;
};
export const useCasesAddToExistingCaseModal = (props: AddToExistingFlyoutProps) => {
@@ -33,8 +36,10 @@ export const useCasesAddToExistingCaseModal = (props: AddToExistingFlyoutProps)
toastTitle: props.toastTitle,
toastContent: props.toastContent,
});
+
const { dispatch } = useCasesContext();
const casesToasts = useCasesToast();
+ const { postComment } = usePostComment();
const closeModal = useCallback(() => {
dispatch({
@@ -47,45 +52,62 @@ export const useCasesAddToExistingCaseModal = (props: AddToExistingFlyoutProps)
});
}, [dispatch]);
+ const handleOnRowClick = useCallback(
+ async (theCase?: Case) => {
+ // when the case is undefined in the modal
+ // the user clicked "create new case"
+ if (theCase === undefined) {
+ closeModal();
+ createNewCaseFlyout.open();
+ return;
+ }
+
+ try {
+ // add attachments to the case
+ const attachments = props.attachments;
+ if (attachments !== undefined && attachments.length > 0) {
+ for (const attachment of attachments) {
+ await postComment({
+ caseId: theCase.id,
+ data: attachment,
+ throwOnError: true,
+ });
+ }
+ casesToasts.showSuccessAttach({
+ theCase,
+ attachments: props.attachments,
+ title: props.toastTitle,
+ content: props.toastContent,
+ });
+ }
+ } catch (error) {
+ // error toast is handled
+ // inside the postComment method
+ }
+
+ if (props.onRowClick) {
+ props.onRowClick(theCase);
+ }
+ },
+ [casesToasts, closeModal, createNewCaseFlyout, postComment, props]
+ );
+
const openModal = useCallback(() => {
dispatch({
type: CasesContextStoreActionsList.OPEN_ADD_TO_CASE_MODAL,
payload: {
...props,
hiddenStatuses: [CaseStatuses.closed, StatusAll],
- onRowClick: (theCase?: Case) => {
- // when the case is undefined in the modal
- // the user clicked "create new case"
- if (theCase === undefined) {
- closeModal();
- createNewCaseFlyout.open();
- } else {
- casesToasts.showSuccessAttach({
- theCase,
- attachments: props.attachments,
- title: props.toastTitle,
- content: props.toastContent,
- });
- if (props.onRowClick) {
- props.onRowClick(theCase);
- }
- }
- },
+ onRowClick: handleOnRowClick,
onClose: () => {
closeModal();
if (props.onClose) {
return props.onClose();
}
},
- updateCase: async (...args) => {
- closeModal();
- if (props.updateCase) {
- return props.updateCase(...args);
- }
- },
},
});
- }, [casesToasts, closeModal, createNewCaseFlyout, dispatch, props]);
+ }, [closeModal, dispatch, handleOnRowClick, props]);
return {
open: openModal,
close: closeModal,
diff --git a/x-pack/plugins/cases/public/containers/use_post_comment.test.tsx b/x-pack/plugins/cases/public/containers/use_post_comment.test.tsx
index cd76738b70307..a3e6147c98439 100644
--- a/x-pack/plugins/cases/public/containers/use_post_comment.test.tsx
+++ b/x-pack/plugins/cases/public/containers/use_post_comment.test.tsx
@@ -12,11 +12,19 @@ import { SECURITY_SOLUTION_OWNER } from '../../common/constants';
import { usePostComment, UsePostComment } from './use_post_comment';
import { basicCaseId } from './mock';
import * as api from './api';
+import { useToasts } from '../common/lib/kibana';
jest.mock('./api');
jest.mock('../common/lib/kibana');
+const useToastMock = useToasts as jest.Mock;
+
describe('usePostComment', () => {
+ const toastErrorMock = jest.fn();
+ useToastMock.mockReturnValue({
+ addError: toastErrorMock,
+ });
+
const abortCtrl = new AbortController();
const samplePost = {
comment: 'a comment',
@@ -59,6 +67,7 @@ describe('usePostComment', () => {
});
await waitForNextUpdate();
expect(spyOnPostCase).toBeCalledWith(samplePost, basicCaseId, abortCtrl.signal);
+ expect(toastErrorMock).not.toHaveBeenCalled();
});
});
@@ -98,7 +107,7 @@ describe('usePostComment', () => {
});
});
- it('unhappy path', async () => {
+ it('set isError true and shows a toast error when an error occurs', async () => {
const spyOnPostCase = jest.spyOn(api, 'postComment');
spyOnPostCase.mockImplementation(() => {
throw new Error('Something went wrong');
@@ -120,6 +129,33 @@ describe('usePostComment', () => {
isError: true,
postComment: result.current.postComment,
});
+
+ expect(toastErrorMock).toHaveBeenCalledWith(expect.any(Error), {
+ title: 'Error fetching data',
+ });
+ });
+ });
+
+ it('throws an error when invoked with throwOnError true', async () => {
+ const spyOnPostCase = jest.spyOn(api, 'postComment');
+ spyOnPostCase.mockImplementation(() => {
+ throw new Error('This is not possible');
+ });
+
+ await act(async () => {
+ const { result, waitForNextUpdate } = renderHook(() =>
+ usePostComment()
+ );
+ await waitForNextUpdate();
+ async function test() {
+ await result.current.postComment({
+ caseId: basicCaseId,
+ data: samplePost,
+ updateCase: updateCaseCallback,
+ throwOnError: true,
+ });
+ }
+ expect(test()).rejects.toThrowError('This is not possible');
});
});
});
diff --git a/x-pack/plugins/cases/public/containers/use_post_comment.tsx b/x-pack/plugins/cases/public/containers/use_post_comment.tsx
index 67db681166d95..ebfcf607701ba 100644
--- a/x-pack/plugins/cases/public/containers/use_post_comment.tsx
+++ b/x-pack/plugins/cases/public/containers/use_post_comment.tsx
@@ -45,6 +45,7 @@ export interface PostComment {
caseId: string;
data: CommentRequest;
updateCase?: (newCase: Case) => void;
+ throwOnError?: boolean;
}
export interface UsePostComment extends NewCommentState {
postComment: (args: PostComment) => Promise;
@@ -60,7 +61,7 @@ export const usePostComment = (): UsePostComment => {
const abortCtrlRef = useRef(new AbortController());
const postMyComment = useCallback(
- async ({ caseId, data, updateCase }: PostComment) => {
+ async ({ caseId, data, updateCase, throwOnError }: PostComment) => {
try {
isCancelledRef.current = false;
abortCtrlRef.current.abort();
@@ -84,6 +85,9 @@ export const usePostComment = (): UsePostComment => {
);
}
dispatch({ type: 'FETCH_FAILURE' });
+ if (throwOnError) {
+ throw error;
+ }
}
}
},
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts
index 5a894c7b00748..704542bca918f 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts
@@ -18,11 +18,14 @@ import { SecurityPluginStart } from '../../../../../security/public';
import { HttpLogic } from '../http';
import { createHref, CreateHrefOptions } from '../react_router_helpers';
+type RequiredFieldsOnly = {
+ [K in keyof T as T[K] extends Required[K] ? K : never]: T[K];
+};
interface KibanaLogicProps {
config: { host?: string };
// Kibana core
history: History;
- navigateToUrl: ApplicationStart['navigateToUrl'];
+ navigateToUrl: RequiredFieldsOnly