diff --git a/.buildkite/scripts/steps/storybooks/build_and_upload.js b/.buildkite/scripts/steps/storybooks/build_and_upload.js index 328c769d81c66..0af75e72de78a 100644 --- a/.buildkite/scripts/steps/storybooks/build_and_upload.js +++ b/.buildkite/scripts/steps/storybooks/build_and_upload.js @@ -15,6 +15,7 @@ const STORYBOOKS = [ 'apm', 'canvas', 'ci_composite', + 'cloud', 'codeeditor', 'custom_integrations', 'dashboard_enhanced', diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index ca0c4b4e91795..ed580cc9e0baf 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github summary: API docs for the actions plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index a60b799dce6c9..8690fd287cd3b 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github summary: API docs for the advancedSettings plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index a4c78c1249832..9171a8236c5ab 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github summary: API docs for the alerting plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/apm.devdocs.json b/api_docs/apm.devdocs.json index 5059a88c10b7d..f7e8f96b7614c 100644 --- a/api_docs/apm.devdocs.json +++ b/api_docs/apm.devdocs.json @@ -737,7 +737,7 @@ "label": "APIEndpoint", "description": [], "signature": [ - "\"POST /internal/apm/data_view/static\" | \"GET /internal/apm/data_view/dynamic\" | \"GET /internal/apm/environments\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}\" | \"GET /internal/apm/services/{serviceName}/errors/distribution\" | \"POST /internal/apm/latency/overall_distribution\" | \"GET /internal/apm/services/{serviceName}/metrics/charts\" | \"GET /internal/apm/observability_overview\" | \"GET /internal/apm/observability_overview/has_data\" | \"GET /internal/apm/ux/client-metrics\" | \"GET /internal/apm/ux/page-load-distribution\" | \"GET /internal/apm/ux/page-load-distribution/breakdown\" | \"GET /internal/apm/ux/page-view-trends\" | \"GET /internal/apm/ux/services\" | \"GET /internal/apm/ux/visitor-breakdown\" | \"GET /internal/apm/ux/web-core-vitals\" | \"GET /internal/apm/ux/long-task-metrics\" | \"GET /internal/apm/ux/url-search\" | \"GET /internal/apm/ux/js-errors\" | \"GET /api/apm/observability_overview/has_rum_data\" | \"GET /internal/apm/service-map\" | \"GET /internal/apm/service-map/service/{serviceName}\" | \"GET /internal/apm/service-map/backend\" | \"GET /internal/apm/services/{serviceName}/serviceNodes\" | \"GET /internal/apm/services\" | \"GET /internal/apm/services/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/metadata/details\" | \"GET /internal/apm/services/{serviceName}/metadata/icons\" | \"GET /internal/apm/services/{serviceName}/agent\" | \"GET /internal/apm/services/{serviceName}/transaction_types\" | \"GET /internal/apm/services/{serviceName}/node/{serviceNodeName}/metadata\" | \"GET /api/apm/services/{serviceName}/annotation/search\" | \"POST /api/apm/services/{serviceName}/annotation\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}\" | \"GET /internal/apm/services/{serviceName}/throughput\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/dependencies\" | \"GET /internal/apm/services/{serviceName}/dependencies/breakdown\" | \"GET /internal/apm/services/{serviceName}/profiling/timeline\" | \"GET /internal/apm/services/{serviceName}/profiling/statistics\" | \"GET /internal/apm/services/{serviceName}/alerts\" | \"GET /internal/apm/services/{serviceName}/infrastructure\" | \"GET /internal/apm/services/{serviceName}/anomaly_charts\" | \"GET /internal/apm/suggestions\" | \"GET /internal/apm/traces/{traceId}\" | \"GET /internal/apm/traces\" | \"GET /internal/apm/traces/{traceId}/root_transaction\" | \"GET /internal/apm/transactions/{transactionId}\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/latency\" | \"GET /internal/apm/services/{serviceName}/transactions/traces/samples\" | \"GET /internal/apm/services/{serviceName}/transaction/charts/breakdown\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_rate\" | \"GET /internal/apm/alerts/chart_preview/transaction_duration\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_count\" | \"GET /api/apm/settings/agent-configuration\" | \"GET /api/apm/settings/agent-configuration/view\" | \"DELETE /api/apm/settings/agent-configuration\" | \"PUT /api/apm/settings/agent-configuration\" | \"POST /api/apm/settings/agent-configuration/search\" | \"GET /api/apm/settings/agent-configuration/services\" | \"GET /api/apm/settings/agent-configuration/environments\" | \"GET /api/apm/settings/agent-configuration/agent_name\" | \"GET /internal/apm/settings/anomaly-detection/jobs\" | \"POST /internal/apm/settings/anomaly-detection/jobs\" | \"GET /internal/apm/settings/anomaly-detection/environments\" | \"POST /internal/apm/settings/anomaly-detection/update_to_v3\" | \"GET /internal/apm/settings/apm-index-settings\" | \"GET /internal/apm/settings/apm-indices\" | \"POST /internal/apm/settings/apm-indices/save\" | \"GET /internal/apm/settings/custom_links/transaction\" | \"GET /internal/apm/settings/custom_links\" | \"POST /internal/apm/settings/custom_links\" | \"PUT /internal/apm/settings/custom_links/{id}\" | \"DELETE /internal/apm/settings/custom_links/{id}\" | \"GET /api/apm/sourcemaps\" | \"POST /api/apm/sourcemaps\" | \"DELETE /api/apm/sourcemaps/{id}\" | \"GET /internal/apm/fleet/has_data\" | \"GET /internal/apm/fleet/agents\" | \"POST /api/apm/fleet/apm_server_schema\" | \"GET /internal/apm/fleet/apm_server_schema/unsupported\" | \"GET /internal/apm/fleet/migration_check\" | \"POST /internal/apm/fleet/cloud_apm_package_policy\" | \"GET /internal/apm/backends/top_backends\" | \"GET /internal/apm/backends/upstream_services\" | \"GET /internal/apm/backends/metadata\" | \"GET /internal/apm/backends/charts/latency\" | \"GET /internal/apm/backends/charts/throughput\" | \"GET /internal/apm/backends/charts/error_rate\" | \"POST /internal/apm/correlations/p_values\" | \"GET /internal/apm/correlations/field_candidates\" | \"POST /internal/apm/correlations/field_stats\" | \"GET /internal/apm/correlations/field_value_stats\" | \"POST /internal/apm/correlations/field_value_pairs\" | \"POST /internal/apm/correlations/significant_correlations\" | \"GET /internal/apm/fallback_to_transactions\" | \"GET /internal/apm/has_data\" | \"GET /internal/apm/event_metadata/{processorEvent}/{id}\" | \"GET /internal/apm/agent_keys\" | \"GET /internal/apm/agent_keys/privileges\" | \"POST /internal/apm/api_key/invalidate\" | \"POST /api/apm/agent_keys\"" + "\"POST /internal/apm/data_view/static\" | \"GET /internal/apm/data_view/dynamic\" | \"GET /internal/apm/environments\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}\" | \"GET /internal/apm/services/{serviceName}/errors/distribution\" | \"POST /internal/apm/latency/overall_distribution\" | \"GET /internal/apm/services/{serviceName}/metrics/charts\" | \"GET /internal/apm/observability_overview\" | \"GET /internal/apm/observability_overview/has_data\" | \"GET /internal/apm/ux/client-metrics\" | \"GET /internal/apm/ux/page-load-distribution\" | \"GET /internal/apm/ux/page-load-distribution/breakdown\" | \"GET /internal/apm/ux/page-view-trends\" | \"GET /internal/apm/ux/services\" | \"GET /internal/apm/ux/visitor-breakdown\" | \"GET /internal/apm/ux/web-core-vitals\" | \"GET /internal/apm/ux/long-task-metrics\" | \"GET /internal/apm/ux/url-search\" | \"GET /internal/apm/ux/js-errors\" | \"GET /api/apm/observability_overview/has_rum_data\" | \"GET /internal/apm/service-map\" | \"GET /internal/apm/service-map/service/{serviceName}\" | \"GET /internal/apm/service-map/backend\" | \"GET /internal/apm/services/{serviceName}/serviceNodes\" | \"GET /internal/apm/services\" | \"GET /internal/apm/services/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/metadata/details\" | \"GET /internal/apm/services/{serviceName}/metadata/icons\" | \"GET /internal/apm/services/{serviceName}/agent\" | \"GET /internal/apm/services/{serviceName}/transaction_types\" | \"GET /internal/apm/services/{serviceName}/node/{serviceNodeName}/metadata\" | \"GET /api/apm/services/{serviceName}/annotation/search\" | \"POST /api/apm/services/{serviceName}/annotation\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}\" | \"GET /internal/apm/services/{serviceName}/throughput\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/dependencies\" | \"GET /internal/apm/services/{serviceName}/dependencies/breakdown\" | \"GET /internal/apm/services/{serviceName}/profiling/timeline\" | \"GET /internal/apm/services/{serviceName}/profiling/statistics\" | \"GET /internal/apm/services/{serviceName}/alerts\" | \"GET /internal/apm/services/{serviceName}/infrastructure\" | \"GET /internal/apm/services/{serviceName}/anomaly_charts\" | \"GET /internal/apm/suggestions\" | \"GET /internal/apm/traces/{traceId}\" | \"GET /internal/apm/traces\" | \"GET /internal/apm/traces/{traceId}/root_transaction\" | \"GET /internal/apm/transactions/{transactionId}\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/latency\" | \"GET /internal/apm/services/{serviceName}/transactions/traces/samples\" | \"GET /internal/apm/services/{serviceName}/transaction/charts/breakdown\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_rate\" | \"GET /internal/apm/alerts/chart_preview/transaction_duration\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_count\" | \"GET /api/apm/settings/agent-configuration\" | \"GET /api/apm/settings/agent-configuration/view\" | \"DELETE /api/apm/settings/agent-configuration\" | \"PUT /api/apm/settings/agent-configuration\" | \"POST /api/apm/settings/agent-configuration/search\" | \"GET /api/apm/settings/agent-configuration/services\" | \"GET /api/apm/settings/agent-configuration/environments\" | \"GET /api/apm/settings/agent-configuration/agent_name\" | \"GET /internal/apm/settings/anomaly-detection/jobs\" | \"POST /internal/apm/settings/anomaly-detection/jobs\" | \"GET /internal/apm/settings/anomaly-detection/environments\" | \"POST /internal/apm/settings/anomaly-detection/update_to_v3\" | \"GET /internal/apm/settings/apm-index-settings\" | \"GET /internal/apm/settings/apm-indices\" | \"POST /internal/apm/settings/apm-indices/save\" | \"GET /internal/apm/settings/custom_links/transaction\" | \"GET /internal/apm/settings/custom_links\" | \"POST /internal/apm/settings/custom_links\" | \"PUT /internal/apm/settings/custom_links/{id}\" | \"DELETE /internal/apm/settings/custom_links/{id}\" | \"GET /api/apm/sourcemaps\" | \"POST /api/apm/sourcemaps\" | \"DELETE /api/apm/sourcemaps/{id}\" | \"GET /internal/apm/fleet/has_data\" | \"GET /internal/apm/fleet/agents\" | \"POST /api/apm/fleet/apm_server_schema\" | \"GET /internal/apm/fleet/apm_server_schema/unsupported\" | \"GET /internal/apm/fleet/migration_check\" | \"POST /internal/apm/fleet/cloud_apm_package_policy\" | \"GET /internal/apm/backends/top_backends\" | \"GET /internal/apm/backends/upstream_services\" | \"GET /internal/apm/backends/metadata\" | \"GET /internal/apm/backends/charts/latency\" | \"GET /internal/apm/backends/charts/throughput\" | \"GET /internal/apm/backends/charts/error_rate\" | \"POST /internal/apm/correlations/p_values\" | \"GET /internal/apm/correlations/field_candidates\" | \"POST /internal/apm/correlations/field_stats\" | \"GET /internal/apm/correlations/field_value_stats\" | \"POST /internal/apm/correlations/field_value_pairs\" | \"POST /internal/apm/correlations/significant_correlations\" | \"GET /internal/apm/fallback_to_transactions\" | \"GET /internal/apm/has_data\" | \"GET /internal/apm/event_metadata/{processorEvent}/{id}\" | \"GET /internal/apm/agent_keys\" | \"GET /internal/apm/agent_keys/privileges\" | \"POST /internal/apm/api_key/invalidate\" | \"POST /api/apm/agent_keys\"" ], "path": "x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts", "deprecated": false, @@ -2405,6 +2405,132 @@ }, ", { errorRateChartPreview: { x: number; y: number; }[]; }, ", "APMRouteCreateOptions", + ">; \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\": ", + "ServerRoute", + "<\"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\", ", + "TypeC", + "<{ path: ", + "TypeC", + "<{ serviceName: ", + "StringC", + "; }>; query: ", + "IntersectionC", + "<[", + "TypeC", + "<{ transactionType: ", + "StringC", + "; transactionName: ", + "StringC", + "; }>, ", + "IntersectionC", + "<[", + "TypeC", + "<{ environment: ", + "UnionC", + "<[", + "LiteralC", + "<\"ENVIRONMENT_NOT_DEFINED\">, ", + "LiteralC", + "<\"ENVIRONMENT_ALL\">, ", + "BrandC", + "<", + "StringC", + ", ", + "NonEmptyStringBrand", + ">]>; }>, ", + "TypeC", + "<{ kuery: ", + "StringC", + "; }>, ", + "TypeC", + "<{ start: ", + "Type", + "; end: ", + "Type", + "; }>, ", + "PartialC", + "<{ comparisonStart: ", + "Type", + "; comparisonEnd: ", + "Type", + "; }>]>]>; }>, ", + { + "pluginId": "apm", + "scope": "server", + "docId": "kibApmPluginApi", + "section": "def-server.APMRouteHandlerResources", + "text": "APMRouteHandlerResources" + }, + ", { currentPeriod: { transactionColdstartRate: ", + "Coordinate", + "[]; average: number | null; }; previousPeriod: { transactionColdstartRate: { x: number; y: ", + "Maybe", + "; }[]; average: number | null; } | { transactionColdstartRate: { x: number; y: ", + "Maybe", + "; }[]; average: null; }; }, ", + "APMRouteCreateOptions", + ">; \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\": ", + "ServerRoute", + "<\"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\", ", + "TypeC", + "<{ path: ", + "TypeC", + "<{ serviceName: ", + "StringC", + "; }>; query: ", + "IntersectionC", + "<[", + "TypeC", + "<{ transactionType: ", + "StringC", + "; }>, ", + "IntersectionC", + "<[", + "TypeC", + "<{ environment: ", + "UnionC", + "<[", + "LiteralC", + "<\"ENVIRONMENT_NOT_DEFINED\">, ", + "LiteralC", + "<\"ENVIRONMENT_ALL\">, ", + "BrandC", + "<", + "StringC", + ", ", + "NonEmptyStringBrand", + ">]>; }>, ", + "TypeC", + "<{ kuery: ", + "StringC", + "; }>, ", + "TypeC", + "<{ start: ", + "Type", + "; end: ", + "Type", + "; }>, ", + "PartialC", + "<{ comparisonStart: ", + "Type", + "; comparisonEnd: ", + "Type", + "; }>]>]>; }>, ", + { + "pluginId": "apm", + "scope": "server", + "docId": "kibApmPluginApi", + "section": "def-server.APMRouteHandlerResources", + "text": "APMRouteHandlerResources" + }, + ", { currentPeriod: { transactionColdstartRate: ", + "Coordinate", + "[]; average: number | null; }; previousPeriod: { transactionColdstartRate: { x: number; y: ", + "Maybe", + "; }[]; average: number | null; } | { transactionColdstartRate: { x: number; y: ", + "Maybe", + "; }[]; average: null; }; }, ", + "APMRouteCreateOptions", ">; \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\": ", "ServerRoute", "<\"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\", ", diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index b3a77bd237b87..cf2654aee72eb 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github summary: API docs for the apm plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 8b4afe1b8cf6a..302bdbdcf2469 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github summary: API docs for the banners plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/bfetch.devdocs.json b/api_docs/bfetch.devdocs.json index 4f9f7a33ebd3f..418468cf7da1c 100644 --- a/api_docs/bfetch.devdocs.json +++ b/api_docs/bfetch.devdocs.json @@ -86,6 +86,20 @@ } ], "initialIsOpen": false + }, + { + "parentPluginId": "bfetch", + "id": "def-public.DISABLE_BFETCH", + "type": "string", + "tags": [], + "label": "DISABLE_BFETCH", + "description": [], + "signature": [ + "\"bfetch:disable\"" + ], + "path": "src/plugins/bfetch/common/constants.ts", + "deprecated": false, + "initialIsOpen": false } ], "objects": [], @@ -1319,6 +1333,20 @@ ], "enums": [], "misc": [ + { + "parentPluginId": "bfetch", + "id": "def-common.DISABLE_BFETCH", + "type": "string", + "tags": [], + "label": "DISABLE_BFETCH", + "description": [], + "signature": [ + "\"bfetch:disable\"" + ], + "path": "src/plugins/bfetch/common/constants.ts", + "deprecated": false, + "initialIsOpen": false + }, { "parentPluginId": "bfetch", "id": "def-common.DISABLE_BFETCH_COMPRESSION", diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index 00ba4298f1238..ac765b5b3abe4 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github summary: API docs for the bfetch plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,7 +18,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 76 | 1 | 67 | 2 | +| 78 | 1 | 69 | 2 | ## Client diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index bae6975abdd42..a9f2bb6a208cb 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github summary: API docs for the canvas plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index 0c0cbd84cc3fb..b628d2c3e2d40 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github summary: API docs for the cases plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/charts.devdocs.json b/api_docs/charts.devdocs.json index 96c915f5997ed..eac5adfc1c61a 100644 --- a/api_docs/charts.devdocs.json +++ b/api_docs/charts.devdocs.json @@ -285,9 +285,9 @@ }, ", xAccessor: ", "Accessor", - " | ", + " | ", "AccessorFn", - ") => ({ x: selectedRange }: ", + ") => ({ x: selectedRange }: ", "XYBrushEvent", ") => ", { @@ -330,8 +330,9 @@ "description": [], "signature": [ "Accessor", - " | ", - "AccessorFn" + " | ", + "AccessorFn", + "" ], "path": "src/plugins/charts/public/static/utils/transform_click_event.ts", "deprecated": false, @@ -361,19 +362,19 @@ }, ", xAccessor: ", "Accessor", - " | ", + " | ", "AccessorFn", - ", splitSeriesAccessorFnMap?: Map, splitSeriesAccessorFnMap?: Map | undefined, splitChartAccessor?: ", + "> | undefined, splitChartAccessor?: ", "Accessor", - " | ", + " | ", "AccessorFn", - " | undefined, negate?: boolean) => (points: [", + " | undefined, negate?: boolean) => (points: [", "GeometryValue", ", ", "XYChartSeriesIdentifier", - "][]) => ", + "][]) => ", { "pluginId": "charts", "scope": "public", @@ -414,8 +415,9 @@ "description": [], "signature": [ "Accessor", - " | ", - "AccessorFn" + " | ", + "AccessorFn", + "" ], "path": "src/plugins/charts/public/static/utils/transform_click_event.ts", "deprecated": false, @@ -433,7 +435,7 @@ "signature": [ "Map | undefined" + "> | undefined" ], "path": "src/plugins/charts/public/static/utils/transform_click_event.ts", "deprecated": false, @@ -448,9 +450,9 @@ "description": [], "signature": [ "Accessor", - " | ", + " | ", "AccessorFn", - " | undefined" + " | undefined" ], "path": "src/plugins/charts/public/static/utils/transform_click_event.ts", "deprecated": false, @@ -494,13 +496,13 @@ }, ") => ({ splitAccessors, ...rest }: ", "XYChartSeriesIdentifier", - ", splitSeriesAccessorFnMap?: Map, splitSeriesAccessorFnMap?: Map | undefined, splitChartAccessor?: ", + "> | undefined, splitChartAccessor?: ", "Accessor", - " | ", + " | ", "AccessorFn", - " | undefined, negate?: boolean) => ", + " | undefined, negate?: boolean) => ", { "pluginId": "charts", "scope": "public", @@ -680,7 +682,7 @@ "signature": [ "(xInterval?: number | undefined, domainStart?: number | undefined, domainEnd?: number | undefined, formatter?: ((v: any) => string) | undefined, renderValue?: boolean) => (headerData: ", "TooltipValue", - ") => string | JSX.Element" + ") => string | JSX.Element" ], "path": "src/plugins/charts/public/static/components/endzones.tsx", "deprecated": false, diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index c14a971309e1c..234cf7139c57a 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github summary: API docs for the charts plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/cloud.devdocs.json b/api_docs/cloud.devdocs.json index 6c6dbf6f48003..946bfa90c7245 100644 --- a/api_docs/cloud.devdocs.json +++ b/api_docs/cloud.devdocs.json @@ -2,7 +2,26 @@ "id": "cloud", "client": { "classes": [], - "functions": [], + "functions": [ + { + "parentPluginId": "cloud", + "id": "def-public.Chat", + "type": "Function", + "tags": [], + "label": "Chat", + "description": [ + "\nA lazily-loaded component that will display a trigger that will allow the user to chat with a\nhuman operator when the service is enabled; otherwise, it renders nothing." + ], + "signature": [ + "() => JSX.Element" + ], + "path": "x-pack/plugins/cloud/public/components/index.tsx", + "deprecated": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + } + ], "interfaces": [ { "parentPluginId": "cloud", @@ -11,7 +30,7 @@ "tags": [], "label": "CloudConfigType", "description": [], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false, "children": [ { @@ -24,7 +43,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false }, { @@ -37,7 +56,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false }, { @@ -50,7 +69,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false }, { @@ -63,7 +82,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false }, { @@ -76,7 +95,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false }, { @@ -89,7 +108,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false }, { @@ -102,8 +121,80 @@ "signature": [ "{ enabled: boolean; org_id?: string | undefined; }" ], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false + }, + { + "parentPluginId": "cloud", + "id": "def-public.CloudConfigType.chat", + "type": "Object", + "tags": [], + "label": "chat", + "description": [ + "Configuration to enable live chat in Cloud-enabled instances of Kibana." + ], + "signature": [ + "{ enabled: boolean; chatURL: string; }" + ], + "path": "x-pack/plugins/cloud/public/plugin.tsx", + "deprecated": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "cloud", + "id": "def-public.CloudStart", + "type": "Interface", + "tags": [], + "label": "CloudStart", + "description": [], + "path": "x-pack/plugins/cloud/public/plugin.tsx", + "deprecated": false, + "children": [ + { + "parentPluginId": "cloud", + "id": "def-public.CloudStart.CloudContextProvider", + "type": "Function", + "tags": [], + "label": "CloudContextProvider", + "description": [ + "\nA React component that provides a pre-wired `React.Context` which connects components to Cloud services." + ], + "signature": [ + "React.FunctionComponent<{}>" + ], + "path": "x-pack/plugins/cloud/public/plugin.tsx", + "deprecated": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "cloud", + "id": "def-public.CloudStart.CloudContextProvider.$1", + "type": "CompoundType", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "P & { children?: React.ReactNode; }" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false + }, + { + "parentPluginId": "cloud", + "id": "def-public.CloudStart.CloudContextProvider.$2", + "type": "Any", + "tags": [], + "label": "context", + "description": [], + "signature": [ + "any" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false + } + ] } ], "initialIsOpen": false @@ -119,7 +210,7 @@ "tags": [], "label": "CloudSetup", "description": [], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false, "children": [ { @@ -132,7 +223,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false }, { @@ -145,7 +236,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false }, { @@ -158,7 +249,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false }, { @@ -171,7 +262,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false }, { @@ -184,7 +275,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false }, { @@ -197,7 +288,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false }, { @@ -210,7 +301,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false }, { @@ -220,7 +311,7 @@ "tags": [], "label": "isCloudEnabled", "description": [], - "path": "x-pack/plugins/cloud/public/plugin.ts", + "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false } ], diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index 6c483ae1dd390..85ce8e619da05 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github summary: API docs for the cloud plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,13 +18,16 @@ Contact [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) for que | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 22 | 0 | 22 | 0 | +| 28 | 0 | 23 | 0 | ## Client ### Setup +### Functions + + ### Interfaces diff --git a/api_docs/console.mdx b/api_docs/console.mdx index d7301cbcf6258..f072b0c10def1 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github summary: API docs for the console plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index f8539c484752f..f95d2dc96d247 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github summary: API docs for the controls plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/core.devdocs.json b/api_docs/core.devdocs.json index 57243eaf987dd..c8f9a3a1953af 100644 --- a/api_docs/core.devdocs.json +++ b/api_docs/core.devdocs.json @@ -1671,7 +1671,7 @@ "label": "links", "description": [], "signature": [ - "{ readonly settings: string; readonly elasticStackGetStarted: string; readonly upgrade: { readonly upgradingElasticStack: string; }; readonly apm: { readonly kibanaSettings: string; readonly supportedServiceMaps: string; readonly customLinks: string; readonly droppedTransactionSpans: string; readonly upgrading: string; readonly metaData: string; }; readonly canvas: { readonly guide: string; }; readonly cloud: { readonly indexManagement: string; }; readonly console: { readonly guide: string; }; readonly dashboard: { readonly guide: string; readonly drilldowns: string; readonly drilldownsTriggerPicker: string; readonly urlDrilldownTemplateSyntax: string; readonly urlDrilldownVariables: string; }; readonly discover: Record; readonly filebeat: { readonly base: string; readonly installation: string; readonly configuration: string; readonly elasticsearchOutput: string; readonly elasticsearchModule: string; readonly startup: string; readonly exportedFields: string; readonly suricataModule: string; readonly zeekModule: string; }; readonly auditbeat: { readonly base: string; readonly auditdModule: string; readonly systemModule: string; }; readonly metricbeat: { readonly base: string; readonly configure: string; readonly httpEndpoint: string; readonly install: string; readonly start: string; }; readonly appSearch: { readonly apiRef: string; readonly apiClients: string; readonly apiKeys: string; readonly authentication: string; readonly crawlRules: string; readonly curations: string; readonly duplicateDocuments: string; readonly entryPoints: string; readonly guide: string; readonly indexingDocuments: string; readonly indexingDocumentsSchema: string; readonly logSettings: string; readonly metaEngines: string; readonly precisionTuning: string; readonly relevanceTuning: string; readonly resultSettings: string; readonly searchUI: string; readonly security: string; readonly synonyms: string; readonly webCrawler: string; readonly webCrawlerEventLogs: string; }; readonly enterpriseSearch: { readonly configuration: string; readonly licenseManagement: string; readonly mailService: string; readonly usersAccess: string; }; readonly workplaceSearch: { readonly apiKeys: string; readonly box: string; readonly confluenceCloud: string; readonly confluenceServer: string; readonly customSources: string; readonly customSourcePermissions: string; readonly documentPermissions: string; readonly dropbox: string; readonly externalIdentities: string; readonly gitHub: string; readonly gettingStarted: string; readonly gmail: string; readonly googleDrive: string; readonly indexingSchedule: string; readonly jiraCloud: string; readonly jiraServer: string; readonly oneDrive: string; readonly permissions: string; readonly salesforce: string; readonly security: string; readonly serviceNow: string; readonly sharePoint: string; readonly slack: string; readonly synch: string; readonly zendesk: string; }; readonly heartbeat: { readonly base: string; }; readonly libbeat: { readonly getStarted: string; }; readonly logstash: { readonly base: string; }; readonly functionbeat: { readonly base: string; }; readonly winlogbeat: { readonly base: string; }; readonly aggs: { readonly composite: string; readonly composite_missing_bucket: string; readonly date_histogram: string; readonly date_range: string; readonly date_format_pattern: string; readonly filter: string; readonly filters: string; readonly geohash_grid: string; readonly histogram: string; readonly ip_range: string; readonly range: string; readonly significant_terms: string; readonly terms: string; readonly terms_doc_count_error: string; readonly rare_terms: string; readonly avg: string; readonly avg_bucket: string; readonly max_bucket: string; readonly min_bucket: string; readonly sum_bucket: string; readonly cardinality: string; readonly count: string; readonly cumulative_sum: string; readonly derivative: string; readonly geo_bounds: string; readonly geo_centroid: string; readonly max: string; readonly median: string; readonly min: string; readonly moving_avg: string; readonly percentile_ranks: string; readonly serial_diff: string; readonly std_dev: string; readonly sum: string; readonly top_hits: string; }; readonly runtimeFields: { readonly overview: string; readonly mapping: string; }; readonly scriptedFields: { readonly scriptFields: string; readonly scriptAggs: string; readonly painless: string; readonly painlessApi: string; readonly painlessLangSpec: string; readonly painlessSyntax: string; readonly painlessWalkthrough: string; readonly luceneExpressions: string; }; readonly search: { readonly sessions: string; readonly sessionLimits: string; }; readonly indexPatterns: { readonly introduction: string; readonly fieldFormattersNumber: string; readonly fieldFormattersString: string; readonly runtimeFields: string; }; readonly addData: string; readonly kibana: { readonly guide: string; readonly autocompleteSuggestions: string; }; readonly upgradeAssistant: { readonly overview: string; readonly batchReindex: string; readonly remoteReindex: string; }; readonly rollupJobs: string; readonly elasticsearch: Record; readonly siem: { readonly privileges: string; readonly guide: string; readonly gettingStarted: string; readonly ml: string; readonly ruleChangeLog: string; readonly detectionsReq: string; readonly networkMap: string; readonly troubleshootGaps: string; }; readonly securitySolution: { readonly trustedApps: string; readonly eventFilters: string; }; readonly query: { readonly eql: string; readonly kueryQuerySyntax: string; readonly luceneQuery: string; readonly luceneQuerySyntax: string; readonly percolate: string; readonly queryDsl: string; }; readonly date: { readonly dateMath: string; readonly dateMathIndexNames: string; }; readonly management: Record; readonly ml: Record; readonly transforms: Record; readonly visualize: Record; readonly apis: Readonly<{ bulkIndexAlias: string; byteSizeUnits: string; createAutoFollowPattern: string; createFollower: string; createIndex: string; createSnapshotLifecyclePolicy: string; createRoleMapping: string; createRoleMappingTemplates: string; createRollupJobsRequest: string; createApiKey: string; createPipeline: string; createTransformRequest: string; cronExpressions: string; executeWatchActionModes: string; indexExists: string; multiSearch: string; openIndex: string; putComponentTemplate: string; painlessExecute: string; painlessExecuteAPIContexts: string; putComponentTemplateMetadata: string; putSnapshotLifecyclePolicy: string; putIndexTemplateV1: string; putWatch: string; searchPreference: string; simulatePipeline: string; timeUnits: string; unfreezeIndex: string; updateTransform: string; }>; readonly observability: Readonly<{ guide: string; infrastructureThreshold: string; logsThreshold: string; metricsThreshold: string; monitorStatus: string; monitorUptime: string; tlsCertificate: string; uptimeDurationAnomaly: string; }>; readonly alerting: Record; readonly maps: Readonly<{ guide: string; importGeospatialPrivileges: string; gdalTutorial: string; }>; readonly monitoring: Record; readonly security: Readonly<{ apiKeyServiceSettings: string; clusterPrivileges: string; elasticsearchSettings: string; elasticsearchEnableSecurity: string; elasticsearchEnableApiKeys: string; indicesPrivileges: string; kibanaTLS: string; kibanaPrivileges: string; mappingRoles: string; mappingRolesFieldRules: string; runAsPrivilege: string; }>; readonly spaces: Readonly<{ kibanaLegacyUrlAliases: string; kibanaDisableLegacyUrlAliasesApi: string; }>; readonly watcher: Record; readonly ccs: Record; readonly plugins: { azureRepo: string; gcsRepo: string; hdfsRepo: string; s3Repo: string; snapshotRestoreRepos: string; mapperSize: string; }; readonly snapshotRestore: Record; readonly ingest: Record; readonly fleet: Readonly<{ beatsAgentComparison: string; guide: string; fleetServer: string; fleetServerAddFleetServer: string; settings: string; settingsFleetServerHostSettings: string; settingsFleetServerProxySettings: string; troubleshooting: string; elasticAgent: string; datastreams: string; datastreamsNamingScheme: string; installElasticAgent: string; installElasticAgentStandalone: string; upgradeElasticAgent: string; upgradeElasticAgent712lower: string; learnMoreBlog: string; apiKeysLearnMore: string; onPremRegistry: string; }>; readonly ecs: { readonly guide: string; }; readonly clients: { readonly guide: string; readonly goOverview: string; readonly javaIndex: string; readonly jsIntro: string; readonly netGuide: string; readonly perlGuide: string; readonly phpGuide: string; readonly pythonGuide: string; readonly rubyOverview: string; readonly rustGuide: string; }; readonly endpoints: { readonly troubleshooting: string; }; }" + "{ readonly settings: string; readonly elasticStackGetStarted: string; readonly upgrade: { readonly upgradingElasticStack: string; }; readonly apm: { readonly kibanaSettings: string; readonly supportedServiceMaps: string; readonly customLinks: string; readonly droppedTransactionSpans: string; readonly upgrading: string; readonly metaData: string; }; readonly canvas: { readonly guide: string; }; readonly cloud: { readonly indexManagement: string; }; readonly console: { readonly guide: string; }; readonly dashboard: { readonly guide: string; readonly drilldowns: string; readonly drilldownsTriggerPicker: string; readonly urlDrilldownTemplateSyntax: string; readonly urlDrilldownVariables: string; }; readonly discover: Record; readonly filebeat: { readonly base: string; readonly installation: string; readonly configuration: string; readonly elasticsearchOutput: string; readonly elasticsearchModule: string; readonly startup: string; readonly exportedFields: string; readonly suricataModule: string; readonly zeekModule: string; }; readonly auditbeat: { readonly base: string; readonly auditdModule: string; readonly systemModule: string; }; readonly metricbeat: { readonly base: string; readonly configure: string; readonly httpEndpoint: string; readonly install: string; readonly start: string; }; readonly appSearch: { readonly apiRef: string; readonly apiClients: string; readonly apiKeys: string; readonly authentication: string; readonly crawlRules: string; readonly curations: string; readonly duplicateDocuments: string; readonly entryPoints: string; readonly guide: string; readonly indexingDocuments: string; readonly indexingDocumentsSchema: string; readonly logSettings: string; readonly metaEngines: string; readonly precisionTuning: string; readonly relevanceTuning: string; readonly resultSettings: string; readonly searchUI: string; readonly security: string; readonly synonyms: string; readonly webCrawler: string; readonly webCrawlerEventLogs: string; }; readonly enterpriseSearch: { readonly configuration: string; readonly licenseManagement: string; readonly mailService: string; readonly usersAccess: string; }; readonly workplaceSearch: { readonly apiKeys: string; readonly box: string; readonly confluenceCloud: string; readonly confluenceServer: string; readonly customSources: string; readonly customSourcePermissions: string; readonly documentPermissions: string; readonly dropbox: string; readonly externalIdentities: string; readonly gitHub: string; readonly gettingStarted: string; readonly gmail: string; readonly googleDrive: string; readonly indexingSchedule: string; readonly jiraCloud: string; readonly jiraServer: string; readonly oneDrive: string; readonly permissions: string; readonly salesforce: string; readonly security: string; readonly serviceNow: string; readonly sharePoint: string; readonly slack: string; readonly synch: string; readonly zendesk: string; }; readonly heartbeat: { readonly base: string; }; readonly libbeat: { readonly getStarted: string; }; readonly logstash: { readonly base: string; }; readonly functionbeat: { readonly base: string; }; readonly winlogbeat: { readonly base: string; }; readonly aggs: { readonly composite: string; readonly composite_missing_bucket: string; readonly date_histogram: string; readonly date_range: string; readonly date_format_pattern: string; readonly filter: string; readonly filters: string; readonly geohash_grid: string; readonly histogram: string; readonly ip_range: string; readonly range: string; readonly significant_terms: string; readonly terms: string; readonly terms_doc_count_error: string; readonly rare_terms: string; readonly avg: string; readonly avg_bucket: string; readonly max_bucket: string; readonly min_bucket: string; readonly sum_bucket: string; readonly cardinality: string; readonly count: string; readonly cumulative_sum: string; readonly derivative: string; readonly geo_bounds: string; readonly geo_centroid: string; readonly max: string; readonly median: string; readonly min: string; readonly moving_avg: string; readonly percentile_ranks: string; readonly serial_diff: string; readonly std_dev: string; readonly sum: string; readonly top_hits: string; }; readonly runtimeFields: { readonly overview: string; readonly mapping: string; }; readonly scriptedFields: { readonly scriptFields: string; readonly scriptAggs: string; readonly painless: string; readonly painlessApi: string; readonly painlessLangSpec: string; readonly painlessSyntax: string; readonly painlessWalkthrough: string; readonly luceneExpressions: string; }; readonly search: { readonly sessions: string; readonly sessionLimits: string; }; readonly indexPatterns: { readonly introduction: string; readonly fieldFormattersNumber: string; readonly fieldFormattersString: string; readonly runtimeFields: string; }; readonly addData: string; readonly kibana: { readonly guide: string; readonly autocompleteSuggestions: string; readonly xpackSecurity: string; }; readonly upgradeAssistant: { readonly overview: string; readonly batchReindex: string; readonly remoteReindex: string; }; readonly rollupJobs: string; readonly elasticsearch: Record; readonly siem: { readonly privileges: string; readonly guide: string; readonly gettingStarted: string; readonly ml: string; readonly ruleChangeLog: string; readonly detectionsReq: string; readonly networkMap: string; readonly troubleshootGaps: string; }; readonly securitySolution: { readonly trustedApps: string; readonly eventFilters: string; }; readonly query: { readonly eql: string; readonly kueryQuerySyntax: string; readonly luceneQuery: string; readonly luceneQuerySyntax: string; readonly percolate: string; readonly queryDsl: string; }; readonly date: { readonly dateMath: string; readonly dateMathIndexNames: string; }; readonly management: Record; readonly ml: Record; readonly transforms: Record; readonly visualize: Record; readonly apis: Readonly<{ bulkIndexAlias: string; byteSizeUnits: string; createAutoFollowPattern: string; createFollower: string; createIndex: string; createSnapshotLifecyclePolicy: string; createRoleMapping: string; createRoleMappingTemplates: string; createRollupJobsRequest: string; createApiKey: string; createPipeline: string; createTransformRequest: string; cronExpressions: string; executeWatchActionModes: string; indexExists: string; multiSearch: string; openIndex: string; putComponentTemplate: string; painlessExecute: string; painlessExecuteAPIContexts: string; putComponentTemplateMetadata: string; putSnapshotLifecyclePolicy: string; putIndexTemplateV1: string; putWatch: string; searchPreference: string; simulatePipeline: string; timeUnits: string; unfreezeIndex: string; updateTransform: string; }>; readonly observability: Readonly<{ guide: string; infrastructureThreshold: string; logsThreshold: string; metricsThreshold: string; monitorStatus: string; monitorUptime: string; tlsCertificate: string; uptimeDurationAnomaly: string; }>; readonly alerting: Record; readonly maps: Readonly<{ guide: string; importGeospatialPrivileges: string; gdalTutorial: string; }>; readonly monitoring: Record; readonly security: Readonly<{ apiKeyServiceSettings: string; clusterPrivileges: string; elasticsearchSettings: string; elasticsearchEnableSecurity: string; elasticsearchEnableApiKeys: string; indicesPrivileges: string; kibanaTLS: string; kibanaPrivileges: string; mappingRoles: string; mappingRolesFieldRules: string; runAsPrivilege: string; }>; readonly spaces: Readonly<{ kibanaLegacyUrlAliases: string; kibanaDisableLegacyUrlAliasesApi: string; }>; readonly watcher: Record; readonly ccs: Record; readonly plugins: { azureRepo: string; gcsRepo: string; hdfsRepo: string; s3Repo: string; snapshotRestoreRepos: string; mapperSize: string; }; readonly snapshotRestore: Record; readonly ingest: Record; readonly fleet: Readonly<{ beatsAgentComparison: string; guide: string; fleetServer: string; fleetServerAddFleetServer: string; settings: string; settingsFleetServerHostSettings: string; settingsFleetServerProxySettings: string; troubleshooting: string; elasticAgent: string; datastreams: string; datastreamsNamingScheme: string; installElasticAgent: string; installElasticAgentStandalone: string; upgradeElasticAgent: string; upgradeElasticAgent712lower: string; learnMoreBlog: string; apiKeysLearnMore: string; onPremRegistry: string; }>; readonly ecs: { readonly guide: string; }; readonly clients: { readonly guide: string; readonly goOverview: string; readonly javaIndex: string; readonly jsIntro: string; readonly netGuide: string; readonly perlGuide: string; readonly phpGuide: string; readonly pythonGuide: string; readonly rubyOverview: string; readonly rustGuide: string; }; readonly endpoints: { readonly troubleshooting: string; }; }" ], "path": "src/core/public/doc_links/doc_links_service.ts", "deprecated": false @@ -14756,13 +14756,13 @@ "signature": [ "{ legacy: { globalConfig$: ", "Observable", - " moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; readonly requestTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; readonly pingTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; }>; path: Readonly<{ readonly data: string; }>; savedObjects: Readonly<{ readonly maxImportPayloadBytes: Readonly<{ isGreaterThan: (other: ", + " moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; }>; readonly requestTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; }>; readonly pingTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; }>; }>; path: Readonly<{ readonly data: string; }>; savedObjects: Readonly<{ readonly maxImportPayloadBytes: Readonly<{ isGreaterThan: (other: ", "ByteSizeValue", ") => boolean; isLessThan: (other: ", "ByteSizeValue", ") => boolean; isEqualTo: (other: ", "ByteSizeValue", - ") => boolean; getValueInBytes: () => number; toString: (returnUnit?: ByteSizeValueUnit | undefined) => string; }>; }>; }>>; get: () => Readonly<{ elasticsearch: Readonly<{ readonly shardTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; readonly requestTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; readonly pingTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; }>; path: Readonly<{ readonly data: string; }>; savedObjects: Readonly<{ readonly maxImportPayloadBytes: Readonly<{ isGreaterThan: (other: ", + ") => boolean; getValueInBytes: () => number; toString: (returnUnit?: ByteSizeValueUnit | undefined) => string; }>; }>; }>>; get: () => Readonly<{ elasticsearch: Readonly<{ readonly shardTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; }>; readonly requestTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; }>; readonly pingTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; }>; }>; path: Readonly<{ readonly data: string; }>; savedObjects: Readonly<{ readonly maxImportPayloadBytes: Readonly<{ isGreaterThan: (other: ", "ByteSizeValue", ") => boolean; isLessThan: (other: ", "ByteSizeValue", @@ -18665,7 +18665,7 @@ "label": "SharedGlobalConfig", "description": [], "signature": [ - "{ readonly elasticsearch: Readonly<{ readonly shardTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; readonly requestTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; readonly pingTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; }>; readonly path: Readonly<{ readonly data: string; }>; readonly savedObjects: Readonly<{ readonly maxImportPayloadBytes: Readonly<{ isGreaterThan: (other: ", + "{ readonly elasticsearch: Readonly<{ readonly shardTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; }>; readonly requestTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; }>; readonly pingTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; }>; }>; readonly path: Readonly<{ readonly data: string; }>; readonly savedObjects: Readonly<{ readonly maxImportPayloadBytes: Readonly<{ isGreaterThan: (other: ", "ByteSizeValue", ") => boolean; isLessThan: (other: ", "ByteSizeValue", diff --git a/api_docs/core.mdx b/api_docs/core.mdx index 321438d49b035..96fb591d5e9ec 100644 --- a/api_docs/core.mdx +++ b/api_docs/core.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/core title: "core" image: https://source.unsplash.com/400x175/?github summary: API docs for the core plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/core_application.mdx b/api_docs/core_application.mdx index 56599e1c86938..61b7413a8f42b 100644 --- a/api_docs/core_application.mdx +++ b/api_docs/core_application.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/core-application title: "core.application" image: https://source.unsplash.com/400x175/?github summary: API docs for the core.application plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core.application'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/core_chrome.mdx b/api_docs/core_chrome.mdx index 4ed582a92dd17..df7ba093c62c2 100644 --- a/api_docs/core_chrome.mdx +++ b/api_docs/core_chrome.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/core-chrome title: "core.chrome" image: https://source.unsplash.com/400x175/?github summary: API docs for the core.chrome plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core.chrome'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/core_http.mdx b/api_docs/core_http.mdx index cefc422199b1e..3158e24a5e029 100644 --- a/api_docs/core_http.mdx +++ b/api_docs/core_http.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/core-http title: "core.http" image: https://source.unsplash.com/400x175/?github summary: API docs for the core.http plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core.http'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/core_saved_objects.mdx b/api_docs/core_saved_objects.mdx index d843587611869..5baefc5ef46b1 100644 --- a/api_docs/core_saved_objects.mdx +++ b/api_docs/core_saved_objects.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/core-savedObjects title: "core.savedObjects" image: https://source.unsplash.com/400x175/?github summary: API docs for the core.savedObjects plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core.savedObjects'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 0016a07fe626d..9051e146ac464 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github summary: API docs for the customIntegrations plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index 87877a1bcfc61..0452af3f41587 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github summary: API docs for the dashboard plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index f570c458d2033..f5b4263686c41 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github summary: API docs for the dashboardEnhanced plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/data.devdocs.json b/api_docs/data.devdocs.json index ef0e1dcb9c7a1..81d0a204d9d04 100644 --- a/api_docs/data.devdocs.json +++ b/api_docs/data.devdocs.json @@ -621,28 +621,7 @@ "path": "src/plugins/data/common/search/aggs/agg_config.ts", "deprecated": true, "removeBy": "8.1", - "references": [ - { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/vis.ts" - }, - { - "plugin": "visDefaultEditor", - "path": "src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts" - }, - { - "plugin": "visDefaultEditor", - "path": "src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts" - }, - { - "plugin": "visDefaultEditor", - "path": "src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts" - }, - { - "plugin": "visDefaultEditor", - "path": "src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx" - } - ], + "references": [], "children": [], "returnComment": [] }, @@ -2944,14 +2923,6 @@ "plugin": "apm", "path": "x-pack/plugins/apm/public/components/app/rum_dashboard/local_ui_filters/selected_filters.tsx" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/common/types/index.ts" @@ -3016,14 +2987,6 @@ "plugin": "dataVisualizer", "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/utils/saved_search_utils.test.ts" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts" - }, { "plugin": "maps", "path": "x-pack/plugins/maps/target/types/public/classes/fields/agg/percentile_agg_field.d.ts" @@ -5202,14 +5165,6 @@ "plugin": "maps", "path": "x-pack/plugins/maps/server/data_indexing/create_doc_source.ts" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" @@ -9590,30 +9545,6 @@ "plugin": "dataViews", "path": "src/plugins/data_views/common/data_views/data_view.ts" }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" - }, { "plugin": "monitoring", "path": "x-pack/plugins/monitoring/public/alerts/components/param_details_form/use_derived_index_pattern.tsx" @@ -12370,14 +12301,6 @@ "plugin": "dashboard", "path": "src/plugins/dashboard/public/url_generator.ts" }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/maps/anomaly_source_field.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/maps/anomaly_source_field.ts" - }, { "plugin": "dashboardEnhanced", "path": "x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx" @@ -18588,14 +18511,6 @@ "plugin": "security", "path": "x-pack/plugins/security/public/management/roles/roles_management_app.tsx" }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" - }, { "plugin": "discover", "path": "src/plugins/discover/public/build_services.ts" @@ -18608,10 +18523,6 @@ "plugin": "discover", "path": "src/plugins/discover/public/application/main/discover_main_route.tsx" }, - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/discover_main_route.tsx" - }, { "plugin": "discover", "path": "src/plugins/discover/public/plugin.tsx" @@ -18702,7 +18613,7 @@ }, { "plugin": "infra", - "path": "x-pack/plugins/infra/public/components/log_stream/log_stream.tsx" + "path": "x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx" }, { "plugin": "infra", @@ -18710,11 +18621,11 @@ }, { "plugin": "infra", - "path": "x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts" + "path": "x-pack/plugins/infra/public/components/log_stream/log_stream.tsx" }, { "plugin": "infra", - "path": "x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx" + "path": "x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts" }, { "plugin": "infra", @@ -18728,14 +18639,6 @@ "plugin": "infra", "path": "x-pack/plugins/infra/public/pages/logs/page_providers.tsx" }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" - }, { "plugin": "graph", "path": "x-pack/plugins/graph/public/plugin.ts" @@ -21227,14 +21130,6 @@ "plugin": "apm", "path": "x-pack/plugins/apm/public/components/app/rum_dashboard/local_ui_filters/selected_filters.tsx" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/common/types/index.ts" @@ -21299,14 +21194,6 @@ "plugin": "dataVisualizer", "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/utils/saved_search_utils.test.ts" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts" - }, { "plugin": "maps", "path": "x-pack/plugins/maps/target/types/public/classes/fields/agg/percentile_agg_field.d.ts" @@ -23793,14 +23680,6 @@ "plugin": "maps", "path": "x-pack/plugins/maps/server/data_indexing/create_doc_source.ts" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" @@ -23958,14 +23837,6 @@ "plugin": "maps", "path": "x-pack/plugins/maps/server/data_indexing/create_doc_source.ts" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" @@ -24572,30 +24443,6 @@ "plugin": "dataViews", "path": "src/plugins/data_views/common/data_views/data_view.ts" }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" - }, { "plugin": "monitoring", "path": "x-pack/plugins/monitoring/public/alerts/components/param_details_form/use_derived_index_pattern.tsx" @@ -25448,14 +25295,6 @@ "plugin": "dashboard", "path": "src/plugins/dashboard/public/url_generator.ts" }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/maps/anomaly_source_field.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/maps/anomaly_source_field.ts" - }, { "plugin": "dashboardEnhanced", "path": "x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx" @@ -29531,10 +29370,6 @@ "plugin": "dataViews", "path": "src/plugins/data_views/common/data_views/data_views.ts" }, - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/discover_main_route.tsx" - }, { "plugin": "visualizations", "path": "src/plugins/visualizations/public/plugin.ts" @@ -31007,14 +30842,6 @@ "plugin": "apm", "path": "x-pack/plugins/apm/public/components/app/rum_dashboard/local_ui_filters/selected_filters.tsx" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/common/types/index.ts" @@ -31079,14 +30906,6 @@ "plugin": "dataVisualizer", "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/utils/saved_search_utils.test.ts" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts" - }, { "plugin": "maps", "path": "x-pack/plugins/maps/target/types/public/classes/fields/agg/percentile_agg_field.d.ts" @@ -33265,14 +33084,6 @@ "plugin": "maps", "path": "x-pack/plugins/maps/server/data_indexing/create_doc_source.ts" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" @@ -35257,20 +35068,7 @@ "path": "src/plugins/data/common/es_query/index.ts", "deprecated": true, "removeBy": "8.1", - "references": [ - { - "plugin": "visualizations", - "path": "src/plugins/visualizations/common/locator.ts" - }, - { - "plugin": "visualizations", - "path": "src/plugins/visualizations/common/locator.ts" - }, - { - "plugin": "visualizations", - "path": "src/plugins/visualizations/common/locator.ts" - } - ], + "references": [], "returnComment": [], "children": [ { @@ -37376,30 +37174,6 @@ "plugin": "dataViews", "path": "src/plugins/data_views/common/data_views/data_view.ts" }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" - }, { "plugin": "monitoring", "path": "x-pack/plugins/monitoring/public/alerts/components/param_details_form/use_derived_index_pattern.tsx" @@ -40139,14 +39913,6 @@ "plugin": "dashboard", "path": "src/plugins/dashboard/public/url_generator.ts" }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/maps/anomaly_source_field.ts" - }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/maps/anomaly_source_field.ts" - }, { "plugin": "dashboardEnhanced", "path": "x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx" diff --git a/api_docs/data.mdx b/api_docs/data.mdx index e650df9b484a8..5ad82aeb15901 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github summary: API docs for the data plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,7 +18,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3364 | 39 | 2767 | 26 | +| 3368 | 39 | 2771 | 26 | ## Client diff --git a/api_docs/data_autocomplete.mdx b/api_docs/data_autocomplete.mdx index f548e7dc7209d..9ad02e0de09ed 100644 --- a/api_docs/data_autocomplete.mdx +++ b/api_docs/data_autocomplete.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/data-autocomplete title: "data.autocomplete" image: https://source.unsplash.com/400x175/?github summary: API docs for the data.autocomplete plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.autocomplete'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,7 +18,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3364 | 39 | 2767 | 26 | +| 3368 | 39 | 2771 | 26 | ## Client diff --git a/api_docs/data_enhanced.mdx b/api_docs/data_enhanced.mdx index 327b8ee8b1dda..804e780be87c3 100644 --- a/api_docs/data_enhanced.mdx +++ b/api_docs/data_enhanced.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataEnhanced title: "dataEnhanced" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataEnhanced plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataEnhanced'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index 4089aa809e3b2..2dbefcbd0612e 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github summary: API docs for the data.query plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,7 +18,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3364 | 39 | 2767 | 26 | +| 3368 | 39 | 2771 | 26 | ## Client diff --git a/api_docs/data_search.devdocs.json b/api_docs/data_search.devdocs.json index d20980b9ea85d..241a628fdd922 100644 --- a/api_docs/data_search.devdocs.json +++ b/api_docs/data_search.devdocs.json @@ -3,6 +3,104 @@ "client": { "classes": [], "functions": [ + { + "parentPluginId": "data", + "id": "def-public.handleResponse", + "type": "Function", + "tags": [], + "label": "handleResponse", + "description": [], + "signature": [ + "(request: ", + "SearchRequest", + ", response: ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.IKibanaSearchResponse", + "text": "IKibanaSearchResponse" + }, + ", theme: ", + { + "pluginId": "core", + "scope": "public", + "docId": "kibCorePluginApi", + "section": "def-public.ThemeServiceStart", + "text": "ThemeServiceStart" + }, + ") => ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.IKibanaSearchResponse", + "text": "IKibanaSearchResponse" + }, + "" + ], + "path": "src/plugins/data/public/search/fetch/handle_response.tsx", + "deprecated": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-public.handleResponse.$1", + "type": "Object", + "tags": [], + "label": "request", + "description": [], + "signature": [ + "SearchRequest" + ], + "path": "src/plugins/data/public/search/fetch/handle_response.tsx", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-public.handleResponse.$2", + "type": "Object", + "tags": [], + "label": "response", + "description": [], + "signature": [ + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.IKibanaSearchResponse", + "text": "IKibanaSearchResponse" + }, + "" + ], + "path": "src/plugins/data/public/search/fetch/handle_response.tsx", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-public.handleResponse.$3", + "type": "Object", + "tags": [], + "label": "theme", + "description": [], + "signature": [ + { + "pluginId": "core", + "scope": "public", + "docId": "kibCorePluginApi", + "section": "def-public.ThemeServiceStart", + "text": "ThemeServiceStart" + } + ], + "path": "src/plugins/data/public/search/fetch/handle_response.tsx", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "data", "id": "def-public.isEsError", @@ -3222,28 +3320,7 @@ "path": "src/plugins/data/common/search/aggs/agg_config.ts", "deprecated": true, "removeBy": "8.1", - "references": [ - { - "plugin": "visualizations", - "path": "src/plugins/visualizations/public/vis.ts" - }, - { - "plugin": "visDefaultEditor", - "path": "src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts" - }, - { - "plugin": "visDefaultEditor", - "path": "src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts" - }, - { - "plugin": "visDefaultEditor", - "path": "src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts" - }, - { - "plugin": "visDefaultEditor", - "path": "src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx" - } - ], + "references": [], "children": [], "returnComment": [] }, diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index 2ef8e0569b7dc..3532f05ab635d 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github summary: API docs for the data.search plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,7 +18,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3364 | 39 | 2767 | 26 | +| 3368 | 39 | 2771 | 26 | ## Client diff --git a/api_docs/data_ui.mdx b/api_docs/data_ui.mdx index 208632d9231a2..ab63f0cd60b36 100644 --- a/api_docs/data_ui.mdx +++ b/api_docs/data_ui.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/data-ui title: "data.ui" image: https://source.unsplash.com/400x175/?github summary: API docs for the data.ui plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.ui'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,7 +18,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3364 | 39 | 2767 | 26 | +| 3368 | 39 | 2771 | 26 | ## Client diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 4c5ab246646c4..c1f8afb3e3c3b 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataViewEditor plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 5d9476dbf6c00..c7fe66ad85520 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataViewFieldEditor plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index c108e886a9544..99b866ff9954a 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataViewManagement plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/data_views.devdocs.json b/api_docs/data_views.devdocs.json index ac618b8e72899..3d06d95d4d169 100644 --- a/api_docs/data_views.devdocs.json +++ b/api_docs/data_views.devdocs.json @@ -2365,10 +2365,6 @@ "path": "src/plugins/data_views/common/data_views/data_views.ts", "deprecated": true, "references": [ - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/discover_main_route.tsx" - }, { "plugin": "visualizations", "path": "src/plugins/visualizations/public/plugin.ts" @@ -3924,14 +3920,6 @@ "plugin": "apm", "path": "x-pack/plugins/apm/public/components/app/rum_dashboard/local_ui_filters/selected_filters.tsx" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/common/types/index.ts" @@ -3996,14 +3984,6 @@ "plugin": "dataVisualizer", "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/utils/saved_search_utils.test.ts" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts" - }, { "plugin": "maps", "path": "x-pack/plugins/maps/target/types/public/classes/fields/agg/percentile_agg_field.d.ts" @@ -6498,14 +6478,6 @@ "plugin": "maps", "path": "x-pack/plugins/maps/server/data_indexing/create_doc_source.ts" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" @@ -10906,10 +10878,6 @@ "plugin": "data", "path": "src/plugins/data/server/search/search_service.ts" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/server/routes/field_stats.ts" @@ -13437,10 +13405,6 @@ "path": "src/plugins/data_views/common/data_views/data_views.ts", "deprecated": true, "references": [ - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/discover_main_route.tsx" - }, { "plugin": "visualizations", "path": "src/plugins/visualizations/public/plugin.ts" @@ -15049,14 +15013,6 @@ "plugin": "apm", "path": "x-pack/plugins/apm/public/components/app/rum_dashboard/local_ui_filters/selected_filters.tsx" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/common/types/index.ts" @@ -15121,14 +15077,6 @@ "plugin": "dataVisualizer", "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/utils/saved_search_utils.test.ts" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts" - }, { "plugin": "maps", "path": "x-pack/plugins/maps/target/types/public/classes/fields/agg/percentile_agg_field.d.ts" @@ -17623,14 +17571,6 @@ "plugin": "maps", "path": "x-pack/plugins/maps/server/data_indexing/create_doc_source.ts" }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, - { - "plugin": "lens", - "path": "x-pack/plugins/lens/server/routes/existing_fields.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" @@ -19205,6 +19145,10 @@ "plugin": "data", "path": "src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_editor_utils.ts" }, + { + "plugin": "data", + "path": "src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_editor_utils.ts" + }, { "plugin": "data", "path": "src/plugins/data/public/query/filter_manager/lib/generate_filters.ts" @@ -19313,30 +19257,6 @@ "plugin": "data", "path": "src/plugins/data/public/ui/filter_bar/filter_editor/index.tsx" }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" - }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" - }, { "plugin": "monitoring", "path": "x-pack/plugins/monitoring/public/alerts/components/param_details_form/use_derived_index_pattern.tsx" @@ -19500,6 +19420,30 @@ { "plugin": "data", "path": "src/plugins/data/public/query/filter_manager/lib/mappers/map_exists.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_operators.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_operators.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_operators.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_operators.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/public/ui/filter_bar/filter_editor/value_input_type.tsx" + }, + { + "plugin": "data", + "path": "src/plugins/data/public/ui/filter_bar/filter_editor/value_input_type.tsx" } ], "children": [ diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index fcbe3589df7f2..ed6084dbf9995 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataViews plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 2da419a8b561f..aaa635baf44da 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataVisualizer plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 1aab530e2ebe4..3037d083e3fcd 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -3,7 +3,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API summary: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2021-07-27 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. --- @@ -14,15 +14,15 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Deprecated API | Referencing plugin(s) | Remove By | | ---------------|-----------|-----------| | | securitySolution | - | -| | home, savedObjects, security, fleet, discover, visualizations, dashboard, lens, observability, maps, fileUpload, dataVisualizer, infra, graph, monitoring, securitySolution, stackAlerts, transform, uptime, inputControlVis, kibanaOverview, savedObjectsManagement, visTypeTimelion, visTypeTimeseries, visTypeVega, dataViewManagement | - | +| | home, savedObjects, security, discover, visualizations, dashboard, lens, observability, maps, fileUpload, dataVisualizer, infra, graph, monitoring, securitySolution, stackAlerts, transform, uptime, inputControlVis, kibanaOverview, savedObjectsManagement, visTypeTimelion, visTypeTimeseries, visTypeVega, dataViewManagement | - | | | apm, security, securitySolution | - | | | apm, security, securitySolution | - | -| | encryptedSavedObjects, actions, ml, dataEnhanced, logstash, securitySolution | - | +| | encryptedSavedObjects, actions, cloud, ml, dataEnhanced, logstash, securitySolution | - | | | visualizations, dashboard, lens, maps, ml, securitySolution, security | - | | | securitySolution | - | -| | dataViews, visTypeTimeseries, maps, lens, data | - | +| | dataViews, visTypeTimeseries, maps, data | - | | | dataViews, observability, savedObjects, security, dashboard, lens, maps, graph, stackAlerts, transform, inputControlVis, savedObjectsManagement, visTypeTimelion, data | - | -| | dataViews, upgradeAssistant, dashboard, visualizations, discover, visTypeTimeseries, observability, maps, dataVisualizer, apm, lens, transform, savedObjects, dataViewFieldEditor, graph, stackAlerts, uptime, dataViewEditor, inputControlVis, savedObjectsManagement, visDefaultEditor, visTypeVega, data | - | +| | dataViews, upgradeAssistant, dashboard, visualizations, discover, visTypeTimeseries, observability, maps, dataVisualizer, apm, transform, lens, savedObjects, dataViewFieldEditor, graph, stackAlerts, uptime, dataViewEditor, inputControlVis, savedObjectsManagement, visDefaultEditor, visTypeVega, data | - | | | dataViews, maps, dataVisualizer, lens, dataViewEditor, inputControlVis, visDefaultEditor, visTypeTimeseries, discover, data | - | | | dataViews, monitoring, stackAlerts, transform | - | | | dataViews, transform, canvas, discover | - | @@ -39,17 +39,17 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | dataViews, visualizations, dashboard, data | - | | | dataViews, maps, dataVisualizer, lens, dataViewEditor, inputControlVis, visDefaultEditor, visTypeTimeseries, discover, data | - | | | dataViews, data | - | -| | dataViews, visTypeTimeseries, maps, lens, data | - | -| | dataViews, discover, visualizations, dashboard, lens | - | -| | dataViews, upgradeAssistant, dashboard, visualizations, discover, visTypeTimeseries, observability, maps, dataVisualizer, apm, lens, transform, savedObjects, dataViewFieldEditor, graph, stackAlerts, uptime, dataViewEditor, inputControlVis, savedObjectsManagement, visDefaultEditor, visTypeVega, data | - | +| | dataViews, visTypeTimeseries, maps, data | - | +| | dataViews, visualizations, dashboard, lens | - | +| | dataViews, upgradeAssistant, dashboard, visualizations, discover, visTypeTimeseries, observability, maps, dataVisualizer, apm, transform, lens, savedObjects, dataViewFieldEditor, graph, stackAlerts, uptime, dataViewEditor, inputControlVis, savedObjectsManagement, visDefaultEditor, visTypeVega, data | - | | | dataViews, maps | - | | | dataViewManagement, dataViews | - | | | visTypeTimeseries, graph, dataViewManagement, dataViews | - | | | dataViews, dataViewManagement | - | | | dataViews, transform, canvas, discover | - | | | dataViews, maps, dataVisualizer, lens, dataViewEditor, inputControlVis, visDefaultEditor, visTypeTimeseries, discover | - | -| | dataViews, upgradeAssistant, dashboard, visualizations, discover, visTypeTimeseries, observability, maps, dataVisualizer, apm, lens, transform, savedObjects, dataViewFieldEditor, graph, stackAlerts, uptime, dataViewEditor, inputControlVis, savedObjectsManagement, visDefaultEditor, visTypeVega | - | -| | dataViews, visTypeTimeseries, maps, lens | - | +| | dataViews, upgradeAssistant, dashboard, visualizations, discover, visTypeTimeseries, observability, maps, dataVisualizer, apm, transform, lens, savedObjects, dataViewFieldEditor, graph, stackAlerts, uptime, dataViewEditor, inputControlVis, savedObjectsManagement, visDefaultEditor, visTypeVega | - | +| | dataViews, visTypeTimeseries, maps | - | | | dataViews, maps | - | | | dataViewManagement, dataViews | - | | | visTypeTimeseries, graph, dataViewManagement, dataViews | - | @@ -60,9 +60,6 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | data, lens, visTypeTimeseries, infra, maps, visTypeTimelion | - | | | maps | - | | | visualizations, dashboard, maps, graph | - | -| | discover, visualizations, dashboard, lens | - | -| | savedObjectsTaggingOss, visualizations, dashboard, lens | - | -| | lens, dashboard | - | | | observability, osquery | - | | | security | - | | | security | - | @@ -72,10 +69,13 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | security, licenseManagement, ml, fleet, apm, crossClusterReplication, logstash, painlessLab, searchprofiler, watcher | - | | | spaces, security, actions, alerting, ml, fleet, remoteClusters, graph, indexLifecycleManagement, mapsEms, painlessLab, rollup, searchprofiler, snapshotRestore, transform, upgradeAssistant | - | | | management, fleet, security, kibanaOverview | - | +| | visualizations, dashboard, lens | - | | | embeddable, presentationUtil, discover, dashboard, graph | - | | | dashboard | - | +| | savedObjectsTaggingOss, visualizations, dashboard, lens | - | | | dashboard | - | | | screenshotting, dashboard | - | +| | lens, dashboard | - | | | spaces, savedObjectsManagement | - | | | spaces, savedObjectsManagement | - | | | ml, infra, ingestPipelines, upgradeAssistant | - | @@ -89,7 +89,6 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | visTypeVega | - | | | monitoring, visTypeVega | - | | | monitoring, kibanaUsageCollection | - | -| | fleet | - | | | canvas, visTypeXy | - | | | canvas | - | | | canvas | - | @@ -104,26 +103,24 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | reporting | - | | | dataViewManagement | - | | | dataViewManagement | - | +| | fleet | - | | | actions, ml, enterpriseSearch, savedObjectsTagging | - | -| | ml | - | | | actions | - | | | screenshotting | - | +| | ml | - | | | mapsEms | - | | | console | - | -| | dataViews, fleet, monitoring, stackAlerts | 8.1 | -| | dataViews, fleet, monitoring, stackAlerts, data | 8.1 | -| | dataViews, fleet, monitoring, stackAlerts | 8.1 | +| | dataViews, monitoring, stackAlerts | 8.1 | +| | dataViews, monitoring, stackAlerts, data | 8.1 | +| | dataViews, monitoring, stackAlerts | 8.1 | | | discover, maps, inputControlVis | 8.1 | | | discover, dashboard, maps, dashboardEnhanced, discoverEnhanced | 8.1 | -| | discover, dashboard, ml, dashboardEnhanced, discoverEnhanced, urlDrilldown, inputControlVis, maps | 8.1 | -| | discover, dashboard, ml, dashboardEnhanced, discoverEnhanced, urlDrilldown, inputControlVis, maps | 8.1 | +| | discover, dashboard, dashboardEnhanced, discoverEnhanced, urlDrilldown, inputControlVis, maps | 8.1 | +| | discover, dashboard, dashboardEnhanced, discoverEnhanced, urlDrilldown, inputControlVis, maps | 8.1 | | | discover, maps, inputControlVis | 8.1 | -| | discover, dashboard, ml, dashboardEnhanced, discoverEnhanced, urlDrilldown, inputControlVis, maps | 8.1 | +| | discover, dashboard, dashboardEnhanced, discoverEnhanced, urlDrilldown, inputControlVis, maps | 8.1 | | | apm, graph, monitoring, stackAlerts | 8.1 | | | stackAlerts | 8.1 | -| | visualizations, visDefaultEditor | 8.1 | -| | visualizations | 8.1 | -| | visualizations, visDefaultEditor | 8.1 | | | dataViewFieldEditor | 8.1 | | | dataViewFieldEditor | 8.1 | | | dataViewFieldEditor | 8.1 | @@ -145,6 +142,7 @@ Safe to remove. | ---------------|------------| | | dashboard | | | dashboard | +| | data | | | data | | | data | | | data | @@ -181,6 +179,7 @@ Safe to remove. | | data | | | data | | | data | +| | data | | | data | | | data | | | data | @@ -205,6 +204,7 @@ Safe to remove. | | data | | | data | | | data | +| | data | | | data | | | data | | | data | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 16d5e67ab1cde..21a2e9f0bd4a8 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -3,7 +3,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin summary: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2021-05-02 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. --- @@ -81,7 +81,8 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud/public/plugin.ts#:~:text=environment) | - | +| | [plugin.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud/public/plugin.tsx#:~:text=environment) | - | +| | [chat.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud/server/routes/chat.ts#:~:text=authc) | - | @@ -152,7 +153,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/index.ts#:~:text=IndexPatternsService), [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/server/index.ts#:~:text=IndexPatternsService), [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/server/index.ts#:~:text=IndexPatternsService), [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/server/index.ts#:~:text=IndexPatternsService), [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/index.ts#:~:text=IndexPatternsService) | - | | | [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/index.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/search_source/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/search_source/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/types.ts#:~:text=IndexPattern), [search_source.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/search_source/search_source.ts#:~:text=IndexPattern), [search_source.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/search_source/search_source.ts#:~:text=IndexPattern), [search_source.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/search_source/search_source.ts#:~:text=IndexPattern), [tabify_docs.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/tabify/tabify_docs.ts#:~:text=IndexPattern), [tabify_docs.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/tabify/tabify_docs.ts#:~:text=IndexPattern)+ 94 more | - | | | [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/index.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE) | - | -| | [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/index.ts#:~:text=IFieldType), [date_histogram.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/aggs/buckets/date_histogram.ts#:~:text=IFieldType), [date_histogram.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/aggs/buckets/date_histogram.ts#:~:text=IFieldType), [filter_editor_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_editor_utils.ts#:~:text=IFieldType), [filter_editor_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_editor_utils.ts#:~:text=IFieldType), [filter_editor_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_editor_utils.ts#:~:text=IFieldType), [generate_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts#:~:text=IFieldType), [generate_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts#:~:text=IFieldType), [generate_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts#:~:text=IFieldType), [generate_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts#:~:text=IFieldType)+ 36 more | 8.1 | +| | [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/index.ts#:~:text=IFieldType), [date_histogram.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/aggs/buckets/date_histogram.ts#:~:text=IFieldType), [date_histogram.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/aggs/buckets/date_histogram.ts#:~:text=IFieldType), [filter_editor_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_editor_utils.ts#:~:text=IFieldType), [filter_editor_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_editor_utils.ts#:~:text=IFieldType), [filter_editor_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_editor_utils.ts#:~:text=IFieldType), [filter_editor_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/ui/filter_bar/filter_editor/lib/filter_editor_utils.ts#:~:text=IFieldType), [generate_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts#:~:text=IFieldType), [generate_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts#:~:text=IFieldType), [generate_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/query/filter_manager/lib/generate_filters.ts#:~:text=IFieldType)+ 43 more | 8.1 | | | [field.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/aggs/param_types/field.ts#:~:text=IndexPatternField), [field.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/aggs/param_types/field.ts#:~:text=IndexPatternField), [field.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/aggs/param_types/field.ts#:~:text=IndexPatternField), [field.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/aggs/param_types/field.ts#:~:text=IndexPatternField), [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/index.ts#:~:text=IndexPatternField), [kibana_context_type.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/expressions/kibana_context_type.ts#:~:text=IndexPatternField), [kibana_context_type.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/expressions/kibana_context_type.ts#:~:text=IndexPatternField), [search_source.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/search_source/search_source.ts#:~:text=IndexPatternField), [search_source.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/search_source/search_source.ts#:~:text=IndexPatternField), [search_source.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/search_source/search_source.ts#:~:text=IndexPatternField)+ 16 more | - | | | [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/index.ts#:~:text=IIndexPattern), [get_time.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/query/timefilter/get_time.ts#:~:text=IIndexPattern), [get_time.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/query/timefilter/get_time.ts#:~:text=IIndexPattern), [get_time.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/query/timefilter/get_time.ts#:~:text=IIndexPattern), [get_time.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/query/timefilter/get_time.ts#:~:text=IIndexPattern), [normalize_sort_request.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/search_source/normalize_sort_request.ts#:~:text=IIndexPattern), [normalize_sort_request.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/search_source/normalize_sort_request.ts#:~:text=IIndexPattern), [normalize_sort_request.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/search_source/normalize_sort_request.ts#:~:text=IIndexPattern), [search_source.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/search_source/search_source.ts#:~:text=IIndexPattern), [search_source.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/search/search_source/search_source.ts#:~:text=IIndexPattern)+ 64 more | - | | | [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/common/index.ts#:~:text=IndexPatternAttributes), [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/public/index.ts#:~:text=IndexPatternAttributes), [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data/server/index.ts#:~:text=IndexPatternAttributes) | - | @@ -294,13 +295,12 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/layout/types.ts#:~:text=IndexPatternAttributes), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/layout/types.ts#:~:text=IndexPatternAttributes), [discover_main_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_app.tsx#:~:text=IndexPatternAttributes), [discover_main_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_app.tsx#:~:text=IndexPatternAttributes), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_route.tsx#:~:text=IndexPatternAttributes), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_route.tsx#:~:text=IndexPatternAttributes), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_route.tsx#:~:text=IndexPatternAttributes) | - | | | [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx#:~:text=create), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx#:~:text=create) | - | | | [anchor.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/context/services/anchor.ts#:~:text=fetch), [fetch_hits_in_interval.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/context/utils/fetch_hits_in_interval.ts#:~:text=fetch) | 8.1 | -| | [build_services.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/build_services.ts#:~:text=indexPatterns), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_route.tsx#:~:text=indexPatterns), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_route.tsx#:~:text=indexPatterns), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_route.tsx#:~:text=indexPatterns), [plugin.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/plugin.tsx#:~:text=indexPatterns) | - | +| | [build_services.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/build_services.ts#:~:text=indexPatterns), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_route.tsx#:~:text=indexPatterns), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_route.tsx#:~:text=indexPatterns), [plugin.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/plugin.tsx#:~:text=indexPatterns) | - | | | [histogram.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/chart/histogram.tsx#:~:text=fieldFormats) | - | | | [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=esFilters), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=esFilters), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=esFilters), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=esFilters), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=esFilters), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=esFilters), [use_navigation_props.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/utils/use_navigation_props.tsx#:~:text=esFilters), [use_navigation_props.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/utils/use_navigation_props.tsx#:~:text=esFilters), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=esFilters), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=esFilters)+ 17 more | 8.1 | | | [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter)+ 24 more | 8.1 | | | [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/layout/types.ts#:~:text=IndexPatternAttributes), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/layout/types.ts#:~:text=IndexPatternAttributes), [discover_main_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_app.tsx#:~:text=IndexPatternAttributes), [discover_main_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_app.tsx#:~:text=IndexPatternAttributes), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_route.tsx#:~:text=IndexPatternAttributes), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_route.tsx#:~:text=IndexPatternAttributes), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_route.tsx#:~:text=IndexPatternAttributes), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/layout/types.ts#:~:text=IndexPatternAttributes), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/layout/types.ts#:~:text=IndexPatternAttributes), [discover_main_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_app.tsx#:~:text=IndexPatternAttributes)+ 4 more | - | | | [discover_field_visualize_inner.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/sidebar/discover_field_visualize_inner.tsx#:~:text=IndexPatternField), [discover_field_visualize_inner.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/sidebar/discover_field_visualize_inner.tsx#:~:text=IndexPatternField), [fields.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/sidebar/__stories__/fields.ts#:~:text=IndexPatternField), [fields.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/sidebar/__stories__/fields.ts#:~:text=IndexPatternField), [discover_field_visualize_inner.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/sidebar/discover_field_visualize_inner.tsx#:~:text=IndexPatternField), [discover_field_visualize_inner.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/sidebar/discover_field_visualize_inner.tsx#:~:text=IndexPatternField), [fields.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/sidebar/__stories__/fields.ts#:~:text=IndexPatternField), [fields.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/sidebar/__stories__/fields.ts#:~:text=IndexPatternField) | - | -| | [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_route.tsx#:~:text=ensureDefaultDataView), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_route.tsx#:~:text=ensureDefaultDataView) | - | | | [use_discover_state.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/main/utils/use_discover_state.d.ts#:~:text=IndexPattern), [use_discover_state.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/main/utils/use_discover_state.d.ts#:~:text=IndexPattern) | - | | | [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter)+ 24 more | 8.1 | | | [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx#:~:text=create), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx#:~:text=create) | - | @@ -309,7 +309,6 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [discover_field_visualize_inner.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/sidebar/discover_field_visualize_inner.tsx#:~:text=IndexPatternField), [discover_field_visualize_inner.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/sidebar/discover_field_visualize_inner.tsx#:~:text=IndexPatternField), [fields.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/sidebar/__stories__/fields.ts#:~:text=IndexPatternField), [fields.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/sidebar/__stories__/fields.ts#:~:text=IndexPatternField) | - | | | [use_discover_state.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/main/utils/use_discover_state.d.ts#:~:text=IndexPattern) | - | | | [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter)+ 24 more | 8.1 | -| | [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/discover_main_route.tsx#:~:text=ensureDefaultDataView) | - | | | [on_save_search.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx#:~:text=SavedObjectSaveModal), [on_save_search.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx#:~:text=SavedObjectSaveModal) | - | | | [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx#:~:text=executeTriggerActions), [search_embeddable_factory.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/embeddable/search_embeddable_factory.ts#:~:text=executeTriggerActions), [plugin.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/plugin.tsx#:~:text=executeTriggerActions), [search_embeddable_factory.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/embeddable/search_embeddable_factory.d.ts#:~:text=executeTriggerActions) | - | | | [ui_settings.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/server/ui_settings.ts#:~:text=metric), [ui_settings.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/server/ui_settings.ts#:~:text=metric), [ui_settings.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/server/ui_settings.ts#:~:text=metric) | - | @@ -375,11 +374,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=IFieldType), [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=IFieldType), [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=IFieldType), [query_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=IFieldType), [query_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=IFieldType), [query_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=IFieldType) | 8.1 | -| | [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=indexPatterns), [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=indexPatterns), [query_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=indexPatterns), [query_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=indexPatterns) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/data_stream/list_page/index.tsx#:~:text=fieldFormats) | - | -| | [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=IFieldType), [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=IFieldType), [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=IFieldType), [query_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=IFieldType), [query_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=IFieldType), [query_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=IFieldType), [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=IFieldType), [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=IFieldType), [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=IFieldType), [query_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=IFieldType)+ 2 more | 8.1 | -| | [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=IFieldType), [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=IFieldType), [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=IFieldType), [query_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=IFieldType), [query_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=IFieldType), [query_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=IFieldType) | 8.1 | | | [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/plugin.ts#:~:text=license%24) | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/server/plugin.ts#:~:text=license%24) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/integrations/index.tsx#:~:text=appBasePath), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/public/applications/fleet/index.tsx#:~:text=appBasePath), [index.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/target/types/public/applications/fleet/index.d.ts#:~:text=appBasePath), [index.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/fleet/target/types/public/applications/integrations/index.d.ts#:~:text=appBasePath) | - | @@ -427,7 +422,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [log_stream.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx#:~:text=indexPatterns), [log_stream.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx#:~:text=indexPatterns), [logs_overview_fetchers.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts#:~:text=indexPatterns), [editor.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx#:~:text=indexPatterns), [redirect_to_node_logs.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.tsx#:~:text=indexPatterns), [use_kibana_index_patterns.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/hooks/use_kibana_index_patterns.ts#:~:text=indexPatterns), [page_providers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/pages/logs/page_providers.tsx#:~:text=indexPatterns), [logs_overview_fetches.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/utils/logs_overview_fetches.test.ts#:~:text=indexPatterns) | - | +| | [editor.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx#:~:text=indexPatterns), [log_stream.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx#:~:text=indexPatterns), [log_stream.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx#:~:text=indexPatterns), [logs_overview_fetchers.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts#:~:text=indexPatterns), [redirect_to_node_logs.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.tsx#:~:text=indexPatterns), [use_kibana_index_patterns.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/hooks/use_kibana_index_patterns.ts#:~:text=indexPatterns), [page_providers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/pages/logs/page_providers.tsx#:~:text=indexPatterns), [logs_overview_fetches.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/utils/logs_overview_fetches.test.ts#:~:text=indexPatterns) | - | | | [kibana_framework_adapter.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts#:~:text=indexPatternsServiceFactory), [log_entries_search_strategy.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.ts#:~:text=indexPatternsServiceFactory), [log_entry_search_strategy.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.ts#:~:text=indexPatternsServiceFactory) | - | | | [module_list_card.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/components/logging/log_analysis_setup/setup_flyout/module_list_card.tsx#:~:text=getUrl) | - | | | [module_list_card.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/infra/public/components/logging/log_analysis_setup/setup_flyout/module_list_card.tsx#:~:text=getUrl) | - | @@ -485,22 +480,19 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService) | - | | | [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPatternsContract), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPatternsContract), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPatternsContract), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPatternsContract), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPatternsContract), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPatternsContract), [embeddable_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts#:~:text=IndexPatternsContract), [embeddable_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts#:~:text=IndexPatternsContract), [loader.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts#:~:text=IndexPatternsContract), [loader.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts#:~:text=IndexPatternsContract)+ 22 more | - | -| | [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPattern), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts#:~:text=IndexPattern), [existing_fields.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts#:~:text=IndexPattern), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPattern), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPattern)+ 36 more | - | +| | [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPattern), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPattern), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPattern), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPattern), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPattern), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPattern)+ 28 more | - | | | [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField)+ 8 more | - | | | [datapanel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx#:~:text=indexPatterns), [datapanel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx#:~:text=indexPatterns), [datapanel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx#:~:text=indexPatterns), [datapanel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx#:~:text=indexPatterns), [indexpattern.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx#:~:text=indexPatterns), [lens_top_nav.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx#:~:text=indexPatterns), [lens_top_nav.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx#:~:text=indexPatterns), [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/plugin.ts#:~:text=indexPatterns), [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/plugin.ts#:~:text=indexPatterns) | - | | | [ranges.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx#:~:text=fieldFormats), [droppable.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/droppable.test.ts#:~:text=fieldFormats) | - | | | [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPatternsContract), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPatternsContract), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPatternsContract), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPatternsContract), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPatternsContract), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPatternsContract), [embeddable_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts#:~:text=IndexPatternsContract), [embeddable_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts#:~:text=IndexPatternsContract), [loader.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts#:~:text=IndexPatternsContract), [loader.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts#:~:text=IndexPatternsContract)+ 22 more | - | | | [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField)+ 8 more | - | -| | [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService) | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/plugin.ts#:~:text=ensureDefaultDataView), [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/plugin.ts#:~:text=ensureDefaultDataView) | - | -| | [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPattern), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts#:~:text=IndexPattern), [existing_fields.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts#:~:text=IndexPattern), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPattern), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPattern)+ 36 more | - | +| | [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPattern), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPattern), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPattern), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPattern), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPattern), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPattern)+ 28 more | - | | | [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField) | - | -| | [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPattern), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts#:~:text=IndexPattern), [existing_fields.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts#:~:text=IndexPattern), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPattern), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPattern)+ 13 more | - | -| | [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService) | - | +| | [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPattern), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPattern), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPattern), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPattern), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPattern), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPattern)+ 9 more | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/plugin.ts#:~:text=ensureDefaultDataView) | - | -| | [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=indexPatternsServiceFactory), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=indexPatternsServiceFactory) | - | +| | [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=indexPatternsServiceFactory) | - | | | [display_duplicate_title_confirm_modal.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/persistence/saved_objects_utils/display_duplicate_title_confirm_modal.ts#:~:text=SavedObject), [display_duplicate_title_confirm_modal.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/persistence/saved_objects_utils/display_duplicate_title_confirm_modal.ts#:~:text=SavedObject), [check_for_duplicate_title.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/persistence/saved_objects_utils/check_for_duplicate_title.ts#:~:text=SavedObject), [check_for_duplicate_title.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/persistence/saved_objects_utils/check_for_duplicate_title.ts#:~:text=SavedObject), [check_for_duplicate_title.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/public/persistence/saved_objects_utils/check_for_duplicate_title.d.ts#:~:text=SavedObject), [check_for_duplicate_title.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/public/persistence/saved_objects_utils/check_for_duplicate_title.d.ts#:~:text=SavedObject), [display_duplicate_title_confirm_modal.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/public/persistence/saved_objects_utils/display_duplicate_title_confirm_modal.d.ts#:~:text=SavedObject), [display_duplicate_title_confirm_modal.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/public/persistence/saved_objects_utils/display_duplicate_title_confirm_modal.d.ts#:~:text=SavedObject) | - | | | [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/app_plugin/types.ts#:~:text=onAppLeave), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/app_plugin/types.ts#:~:text=onAppLeave), [mounter.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/app_plugin/mounter.tsx#:~:text=onAppLeave) | - | | | [saved_object_migrations.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/migrations/saved_object_migrations.ts#:~:text=warning), [saved_object_migrations.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/migrations/saved_object_migrations.ts#:~:text=warning) | - | @@ -576,11 +568,8 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [anomaly_source_field.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/maps/anomaly_source_field.ts#:~:text=Filter), [anomaly_source_field.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/maps/anomaly_source_field.ts#:~:text=Filter) | 8.1 | -| | [anomaly_source_field.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/maps/anomaly_source_field.ts#:~:text=Filter), [anomaly_source_field.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/maps/anomaly_source_field.ts#:~:text=Filter) | 8.1 | -| | [anomaly_source_field.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/maps/anomaly_source_field.ts#:~:text=Filter), [anomaly_source_field.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/maps/anomaly_source_field.ts#:~:text=Filter) | 8.1 | -| | [use_create_url.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts#:~:text=getUrl), [use_create_url.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts#:~:text=getUrl), [side_nav.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/components/ml_page/side_nav.tsx#:~:text=getUrl), [actions.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/actions.tsx#:~:text=getUrl), [actions.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/actions.tsx#:~:text=getUrl), [anomaly_detection_empty_state.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/jobs/jobs_list/components/anomaly_detection_empty_state/anomaly_detection_empty_state.tsx#:~:text=getUrl), [use_view_action.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/use_view_action.tsx#:~:text=getUrl), [use_map_action.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_map/use_map_action.tsx#:~:text=getUrl), [actions.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/overview/components/analytics_panel/actions.tsx#:~:text=getUrl), [models_list.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx#:~:text=getUrl)+ 18 more | - | -| | [use_create_url.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts#:~:text=getUrl), [use_create_url.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts#:~:text=getUrl), [side_nav.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/components/ml_page/side_nav.tsx#:~:text=getUrl), [actions.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/actions.tsx#:~:text=getUrl), [actions.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/actions.tsx#:~:text=getUrl), [anomaly_detection_empty_state.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/jobs/jobs_list/components/anomaly_detection_empty_state/anomaly_detection_empty_state.tsx#:~:text=getUrl), [use_view_action.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/use_view_action.tsx#:~:text=getUrl), [use_map_action.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_map/use_map_action.tsx#:~:text=getUrl), [actions.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/overview/components/analytics_panel/actions.tsx#:~:text=getUrl), [models_list.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx#:~:text=getUrl)+ 18 more | - | +| | [use_create_url.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts#:~:text=getUrl), [use_create_url.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts#:~:text=getUrl), [side_nav.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/components/ml_page/side_nav.tsx#:~:text=getUrl), [actions.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/actions.tsx#:~:text=getUrl), [actions.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/actions.tsx#:~:text=getUrl), [anomaly_detection_empty_state.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/jobs/jobs_list/components/anomaly_detection_empty_state/anomaly_detection_empty_state.tsx#:~:text=getUrl), [use_view_action.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/use_view_action.tsx#:~:text=getUrl), [use_map_action.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_map/use_map_action.tsx#:~:text=getUrl), [actions.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/overview/components/analytics_panel/actions.tsx#:~:text=getUrl), [models_list.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx#:~:text=getUrl)+ 17 more | - | +| | [use_create_url.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts#:~:text=getUrl), [use_create_url.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/contexts/kibana/use_create_url.ts#:~:text=getUrl), [side_nav.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/components/ml_page/side_nav.tsx#:~:text=getUrl), [actions.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/actions.tsx#:~:text=getUrl), [actions.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/actions.tsx#:~:text=getUrl), [anomaly_detection_empty_state.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/jobs/jobs_list/components/anomaly_detection_empty_state/anomaly_detection_empty_state.tsx#:~:text=getUrl), [use_view_action.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_view/use_view_action.tsx#:~:text=getUrl), [use_map_action.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_map/use_map_action.tsx#:~:text=getUrl), [actions.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/overview/components/analytics_panel/actions.tsx#:~:text=getUrl), [models_list.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx#:~:text=getUrl)+ 17 more | - | | | [check_license.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/application/license/check_license.tsx#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/public/plugin.ts#:~:text=license%24) | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/server/plugin.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/server/plugin.ts#:~:text=license%24) | - | | | [annotations.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/ml/server/routes/annotations.ts#:~:text=authc) | - | @@ -865,10 +854,8 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | ---------------|-----------|-----------| | | [agg_type_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_filters.ts#:~:text=IndexPattern), [agg_type_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_filters.ts#:~:text=IndexPattern), [agg_type_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_filters.ts#:~:text=IndexPattern), [editor_config.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/utils/editor_config.ts#:~:text=IndexPattern), [editor_config.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/utils/editor_config.ts#:~:text=IndexPattern), [agg_params_helper.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_params_helper.ts#:~:text=IndexPattern), [agg_params_helper.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_params_helper.ts#:~:text=IndexPattern), [agg_select.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_select.tsx#:~:text=IndexPattern), [agg_select.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_select.tsx#:~:text=IndexPattern), [agg_params.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_params.tsx#:~:text=IndexPattern)+ 24 more | - | | | [agg_type_field_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_field_filters.ts#:~:text=IndexPatternField), [agg_type_field_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_field_filters.ts#:~:text=IndexPatternField), [agg_type_field_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_field_filters.ts#:~:text=IndexPatternField), [agg_param_props.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_param_props.ts#:~:text=IndexPatternField), [agg_param_props.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_param_props.ts#:~:text=IndexPatternField), [field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=IndexPatternField), [field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=IndexPatternField), [field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=IndexPatternField), [field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=IndexPatternField), [top_field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/top_field.tsx#:~:text=IndexPatternField)+ 38 more | - | -| | [reducers.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts#:~:text=toJSON), [reducers.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts#:~:text=toJSON), [reducers.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts#:~:text=toJSON), [sidebar.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx#:~:text=toJSON) | 8.1 | | | [agg_type_field_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_field_filters.ts#:~:text=IndexPatternField), [agg_type_field_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_field_filters.ts#:~:text=IndexPatternField), [agg_type_field_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_field_filters.ts#:~:text=IndexPatternField), [agg_param_props.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_param_props.ts#:~:text=IndexPatternField), [agg_param_props.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_param_props.ts#:~:text=IndexPatternField), [field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=IndexPatternField), [field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=IndexPatternField), [field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=IndexPatternField), [field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=IndexPatternField), [top_field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/top_field.tsx#:~:text=IndexPatternField)+ 38 more | - | | | [agg_type_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_filters.ts#:~:text=IndexPattern), [agg_type_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_filters.ts#:~:text=IndexPattern), [agg_type_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_filters.ts#:~:text=IndexPattern), [editor_config.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/utils/editor_config.ts#:~:text=IndexPattern), [editor_config.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/utils/editor_config.ts#:~:text=IndexPattern), [agg_params_helper.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_params_helper.ts#:~:text=IndexPattern), [agg_params_helper.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_params_helper.ts#:~:text=IndexPattern), [agg_select.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_select.tsx#:~:text=IndexPattern), [agg_select.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_select.tsx#:~:text=IndexPattern), [agg_params.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_params.tsx#:~:text=IndexPattern)+ 24 more | - | -| | [reducers.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts#:~:text=toJSON), [reducers.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts#:~:text=toJSON), [reducers.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts#:~:text=toJSON), [sidebar.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx#:~:text=toJSON) | 8.1 | | | [agg_type_field_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_field_filters.ts#:~:text=IndexPatternField), [agg_type_field_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_field_filters.ts#:~:text=IndexPatternField), [agg_type_field_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_field_filters.ts#:~:text=IndexPatternField), [agg_param_props.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_param_props.ts#:~:text=IndexPatternField), [agg_param_props.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_param_props.ts#:~:text=IndexPatternField), [field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=IndexPatternField), [field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=IndexPatternField), [field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=IndexPatternField), [field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=IndexPatternField), [top_field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/controls/top_field.tsx#:~:text=IndexPatternField)+ 14 more | - | | | [agg_type_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_filters.ts#:~:text=IndexPattern), [agg_type_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_filters.ts#:~:text=IndexPattern), [agg_type_filters.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/agg_filters/agg_type_filters.ts#:~:text=IndexPattern), [editor_config.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/utils/editor_config.ts#:~:text=IndexPattern), [editor_config.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/utils/editor_config.ts#:~:text=IndexPattern), [agg_params_helper.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_params_helper.ts#:~:text=IndexPattern), [agg_params_helper.ts](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_params_helper.ts#:~:text=IndexPattern), [agg_select.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_select.tsx#:~:text=IndexPattern), [agg_select.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_select.tsx#:~:text=IndexPattern), [agg_params.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/vis_default_editor/public/components/agg_params.tsx#:~:text=IndexPattern)+ 7 more | - | @@ -954,13 +941,10 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [base_vis_type.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/target/types/public/vis_types/base_vis_type.d.ts#:~:text=IndexPattern), [base_vis_type.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/target/types/public/vis_types/base_vis_type.d.ts#:~:text=IndexPattern), [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=IndexPattern), [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [create_vis_embeddable_from_object.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts#:~:text=IndexPattern), [create_vis_embeddable_from_object.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts#:~:text=IndexPattern), [visualize_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx#:~:text=IndexPattern)+ 20 more | - | -| | [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=toJSON) | 8.1 | | | [visualize_top_nav.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/visualize_app/components/visualize_top_nav.tsx#:~:text=indexPatterns), [visualize_top_nav.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/visualize_app/components/visualize_top_nav.tsx#:~:text=indexPatterns), [plugin.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/plugin.ts#:~:text=indexPatterns), [plugin.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/plugin.ts#:~:text=indexPatterns) | - | | | [controls_references.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [controls_references.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [timeseries_references.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [timeseries_references.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [visualization_saved_object_migrations.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [visualization_saved_object_migrations.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [visualization_saved_object_migrations.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [visualization_saved_object_migrations.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [visualization_saved_object_migrations.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [controls_references.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE)+ 8 more | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/plugin.ts#:~:text=ensureDefaultDataView), [plugin.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/plugin.ts#:~:text=ensureDefaultDataView) | - | | | [base_vis_type.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/target/types/public/vis_types/base_vis_type.d.ts#:~:text=IndexPattern), [base_vis_type.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/target/types/public/vis_types/base_vis_type.d.ts#:~:text=IndexPattern), [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=IndexPattern), [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [create_vis_embeddable_from_object.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts#:~:text=IndexPattern), [create_vis_embeddable_from_object.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts#:~:text=IndexPattern), [visualize_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx#:~:text=IndexPattern)+ 20 more | - | -| | [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/common/locator.ts#:~:text=isFilterPinned), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/common/locator.ts#:~:text=isFilterPinned), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/common/locator.ts#:~:text=isFilterPinned) | 8.1 | -| | [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=toJSON) | 8.1 | | | [base_vis_type.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/target/types/public/vis_types/base_vis_type.d.ts#:~:text=IndexPattern), [base_vis_type.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/target/types/public/vis_types/base_vis_type.d.ts#:~:text=IndexPattern), [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=IndexPattern), [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [create_vis_embeddable_from_object.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts#:~:text=IndexPattern), [create_vis_embeddable_from_object.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts#:~:text=IndexPattern), [visualize_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx#:~:text=IndexPattern)+ 5 more | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/plugin.ts#:~:text=ensureDefaultDataView) | - | | | [display_duplicate_title_confirm_modal.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/utils/saved_objects_utils/display_duplicate_title_confirm_modal.ts#:~:text=SavedObject), [display_duplicate_title_confirm_modal.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/utils/saved_objects_utils/display_duplicate_title_confirm_modal.ts#:~:text=SavedObject), [check_for_duplicate_title.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/utils/saved_objects_utils/check_for_duplicate_title.ts#:~:text=SavedObject), [check_for_duplicate_title.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/utils/saved_objects_utils/check_for_duplicate_title.ts#:~:text=SavedObject) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx new file mode 100644 index 0000000000000..a4eb29cdbd6b2 --- /dev/null +++ b/api_docs/deprecations_by_team.mdx @@ -0,0 +1,227 @@ +--- +id: kibDevDocsDeprecationsDueByTeam +slug: /kibana-dev-docs/api-meta/deprecations-due-by-team +title: Deprecated APIs due to be removed, by team +summary: Lists the teams that are referencing deprecated APIs with a remove by date. +date: 2022-01-31 +tags: ['contributor', 'dev', 'apidocs', 'kibana'] +warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +--- + + +## APM UI + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| +| apm | | [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=esKuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=esKuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=esKuery) | 8.1 | + + + +## App Services + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| +| dataViews | | [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/utils.ts#:~:text=IFieldType), [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/utils.ts#:~:text=IFieldType), [data_view_field.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/data_view_field.ts#:~:text=IFieldType), [data_view_field.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/data_view_field.ts#:~:text=IFieldType), [field_list.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/field_list.ts#:~:text=IFieldType), [field_list.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/field_list.ts#:~:text=IFieldType), [field_list.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/field_list.ts#:~:text=IFieldType), [field_list.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/field_list.ts#:~:text=IFieldType), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/types.ts#:~:text=IFieldType), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/types.ts#:~:text=IFieldType)+ 13 more | 8.1 | +| dataViews | | [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/utils.ts#:~:text=IFieldType), [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/utils.ts#:~:text=IFieldType), [data_view_field.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/data_view_field.ts#:~:text=IFieldType), [data_view_field.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/data_view_field.ts#:~:text=IFieldType), [field_list.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/field_list.ts#:~:text=IFieldType), [field_list.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/field_list.ts#:~:text=IFieldType), [field_list.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/field_list.ts#:~:text=IFieldType), [field_list.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/field_list.ts#:~:text=IFieldType), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/types.ts#:~:text=IFieldType), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/types.ts#:~:text=IFieldType)+ 66 more | 8.1 | +| dataViews | | [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/utils.ts#:~:text=IFieldType), [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/utils.ts#:~:text=IFieldType), [data_view_field.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/data_view_field.ts#:~:text=IFieldType), [data_view_field.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/data_view_field.ts#:~:text=IFieldType), [field_list.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/field_list.ts#:~:text=IFieldType), [field_list.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/field_list.ts#:~:text=IFieldType), [field_list.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/field_list.ts#:~:text=IFieldType), [field_list.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/field_list.ts#:~:text=IFieldType), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/types.ts#:~:text=IFieldType), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/types.ts#:~:text=IFieldType)+ 13 more | 8.1 | +| dataViewFieldEditor | | [field_format_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/data_view_field_editor/public/components/field_format_editor/field_format_editor.tsx#:~:text=castEsToKbnFieldTypeName), [field_format_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/data_view_field_editor/public/components/field_format_editor/field_format_editor.tsx#:~:text=castEsToKbnFieldTypeName) | 8.1 | +| dataViewFieldEditor | | [field_format_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/data_view_field_editor/public/components/field_format_editor/field_format_editor.tsx#:~:text=castEsToKbnFieldTypeName), [field_format_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/data_view_field_editor/public/components/field_format_editor/field_format_editor.tsx#:~:text=castEsToKbnFieldTypeName) | 8.1 | +| dataViewFieldEditor | | [field_format_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/data_view_field_editor/public/components/field_format_editor/field_format_editor.tsx#:~:text=castEsToKbnFieldTypeName), [field_format_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/data_view_field_editor/public/components/field_format_editor/field_format_editor.tsx#:~:text=castEsToKbnFieldTypeName) | 8.1 | +| dashboardEnhanced | | [embeddable_to_dashboard_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx#:~:text=esFilters), [embeddable_to_dashboard_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx#:~:text=esFilters), [embeddable_to_dashboard_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx#:~:text=esFilters) | 8.1 | +| dashboardEnhanced | | [embeddable_to_dashboard_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx#:~:text=isFilters), [embeddable_to_dashboard_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx#:~:text=isFilters) | 8.1 | +| dashboardEnhanced | | [embeddable_to_dashboard_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx#:~:text=Filter), [embeddable_to_dashboard_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx#:~:text=Filter), [context_variables.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/variables/context_variables.ts#:~:text=Filter), [context_variables.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/variables/context_variables.ts#:~:text=Filter), [url_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown.tsx#:~:text=Filter), [url_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown.tsx#:~:text=Filter), [data.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/test/data.ts#:~:text=Filter), [data.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/test/data.ts#:~:text=Filter) | 8.1 | +| dashboardEnhanced | | [embeddable_to_dashboard_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx#:~:text=Filter), [embeddable_to_dashboard_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx#:~:text=Filter), [context_variables.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/variables/context_variables.ts#:~:text=Filter), [context_variables.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/variables/context_variables.ts#:~:text=Filter), [url_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown.tsx#:~:text=Filter), [url_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown.tsx#:~:text=Filter), [data.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/test/data.ts#:~:text=Filter), [data.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/test/data.ts#:~:text=Filter) | 8.1 | +| dashboardEnhanced | | [embeddable_to_dashboard_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx#:~:text=isFilters), [embeddable_to_dashboard_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx#:~:text=isFilters) | 8.1 | +| dashboardEnhanced | | [embeddable_to_dashboard_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx#:~:text=Filter), [embeddable_to_dashboard_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx#:~:text=Filter), [context_variables.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/variables/context_variables.ts#:~:text=Filter), [context_variables.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/variables/context_variables.ts#:~:text=Filter), [url_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown.tsx#:~:text=Filter), [url_drilldown.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown.tsx#:~:text=Filter), [data.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/test/data.ts#:~:text=Filter), [data.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/drilldowns/url_drilldown/public/lib/test/data.ts#:~:text=Filter) | 8.1 | +| dataEnhanced | | [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/types.ts#:~:text=KueryNode), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/types.ts#:~:text=KueryNode), [get_search_session_page.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/get_search_session_page.ts#:~:text=KueryNode), [get_search_session_page.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/get_search_session_page.ts#:~:text=KueryNode), [check_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_persisted_sessions.ts#:~:text=KueryNode), [check_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_persisted_sessions.ts#:~:text=KueryNode), [check_non_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_non_persisted_sessions.ts#:~:text=KueryNode), [check_non_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_non_persisted_sessions.ts#:~:text=KueryNode), [expire_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/expire_persisted_sessions.ts#:~:text=KueryNode), [expire_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/expire_persisted_sessions.ts#:~:text=KueryNode)+ 2 more | 8.1 | +| dataEnhanced | | [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/types.ts#:~:text=KueryNode), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/types.ts#:~:text=KueryNode), [get_search_session_page.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/get_search_session_page.ts#:~:text=KueryNode), [get_search_session_page.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/get_search_session_page.ts#:~:text=KueryNode), [check_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_persisted_sessions.ts#:~:text=KueryNode), [check_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_persisted_sessions.ts#:~:text=KueryNode), [check_non_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_non_persisted_sessions.ts#:~:text=KueryNode), [check_non_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_non_persisted_sessions.ts#:~:text=KueryNode), [expire_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/expire_persisted_sessions.ts#:~:text=KueryNode), [expire_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/expire_persisted_sessions.ts#:~:text=KueryNode)+ 2 more | 8.1 | +| dataEnhanced | | [check_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_persisted_sessions.ts#:~:text=nodeBuilder), [check_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_persisted_sessions.ts#:~:text=nodeBuilder), [check_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_persisted_sessions.ts#:~:text=nodeBuilder), [check_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_persisted_sessions.ts#:~:text=nodeBuilder), [check_non_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_non_persisted_sessions.ts#:~:text=nodeBuilder), [check_non_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_non_persisted_sessions.ts#:~:text=nodeBuilder), [expire_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/expire_persisted_sessions.ts#:~:text=nodeBuilder), [expire_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/expire_persisted_sessions.ts#:~:text=nodeBuilder), [expire_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/expire_persisted_sessions.ts#:~:text=nodeBuilder), [expire_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/expire_persisted_sessions.ts#:~:text=nodeBuilder)+ 2 more | 8.1 | +| dataEnhanced | | [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/types.ts#:~:text=KueryNode), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/types.ts#:~:text=KueryNode), [get_search_session_page.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/get_search_session_page.ts#:~:text=KueryNode), [get_search_session_page.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/get_search_session_page.ts#:~:text=KueryNode), [check_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_persisted_sessions.ts#:~:text=KueryNode), [check_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_persisted_sessions.ts#:~:text=KueryNode), [check_non_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_non_persisted_sessions.ts#:~:text=KueryNode), [check_non_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/check_non_persisted_sessions.ts#:~:text=KueryNode), [expire_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/expire_persisted_sessions.ts#:~:text=KueryNode), [expire_persisted_sessions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_enhanced/server/search/session/expire_persisted_sessions.ts#:~:text=KueryNode)+ 2 more | 8.1 | + + + +## Data Discovery + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| +| graph | | [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/graph/public/components/search_bar.tsx#:~:text=esKuery), [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/graph/public/components/search_bar.tsx#:~:text=esKuery), [search_bar.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/graph/public/components/search_bar.tsx#:~:text=esKuery) | 8.1 | +| discover | | [anchor.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/context/services/anchor.ts#:~:text=fetch), [fetch_hits_in_interval.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/context/utils/fetch_hits_in_interval.ts#:~:text=fetch) | 8.1 | +| discover | | [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=esFilters), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=esFilters), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=esFilters), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=esFilters), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=esFilters), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=esFilters), [use_navigation_props.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/utils/use_navigation_props.tsx#:~:text=esFilters), [use_navigation_props.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/utils/use_navigation_props.tsx#:~:text=esFilters), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=esFilters), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=esFilters)+ 19 more | 8.1 | +| discover | | [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter)+ 29 more | 8.1 | +| discover | | [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter)+ 29 more | 8.1 | +| discover | | [anchor.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/context/services/anchor.ts#:~:text=fetch), [fetch_hits_in_interval.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/context/utils/fetch_hits_in_interval.ts#:~:text=fetch) | 8.1 | +| discover | | [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=Filter)+ 29 more | 8.1 | +| discoverEnhanced | | [explore_data_chart_action.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.test.ts#:~:text=RangeFilter), [explore_data_chart_action.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.test.ts#:~:text=RangeFilter) | 8.1 | +| discoverEnhanced | | [explore_data_chart_action.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.test.ts#:~:text=RangeFilter), [explore_data_chart_action.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.test.ts#:~:text=RangeFilter) | 8.1 | + + + +## Enterprise Search + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| + + + + +## Fleet + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| + + + + +## GIS + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| +| maps | | [es_source.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts#:~:text=fetch), [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=fetch), [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=fetch) | 8.1 | +| maps | | [es_tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts#:~:text=esFilters), [es_tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts#:~:text=esFilters), [es_tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts#:~:text=esFilters), [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=esFilters), [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=esFilters), [es_geo_line_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/es_geo_line_source.tsx#:~:text=esFilters), [es_geo_line_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/es_geo_line_source.tsx#:~:text=esFilters), [es_geo_line_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/es_geo_line_source.tsx#:~:text=esFilters), [app_sync.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/map_page/url_state/app_sync.ts#:~:text=esFilters), [app_sync.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/map_page/url_state/app_sync.ts#:~:text=esFilters)+ 9 more | 8.1 | +| maps | | [data_request_descriptor_types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts#:~:text=Filter), [data_request_descriptor_types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/elasticsearch_util/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/elasticsearch_util/types.ts#:~:text=Filter), [map_app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx#:~:text=Filter), [map_app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx#:~:text=Filter), [map_app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx#:~:text=Filter), [map_app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx#:~:text=Filter)+ 21 more | 8.1 | +| maps | | [data_request_descriptor_types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts#:~:text=Filter), [data_request_descriptor_types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/elasticsearch_util/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/elasticsearch_util/types.ts#:~:text=Filter), [map_app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx#:~:text=Filter), [map_app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx#:~:text=Filter), [map_app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx#:~:text=Filter), [map_app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx#:~:text=Filter)+ 21 more | 8.1 | +| maps | | [es_source.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts#:~:text=fetch), [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=fetch), [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=fetch) | 8.1 | +| maps | | [data_request_descriptor_types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts#:~:text=Filter), [data_request_descriptor_types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/elasticsearch_util/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/elasticsearch_util/types.ts#:~:text=Filter), [map_app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx#:~:text=Filter), [map_app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx#:~:text=Filter), [map_app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx#:~:text=Filter), [map_app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx#:~:text=Filter)+ 21 more | 8.1 | + + + +## Kibana Alerting + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| +| stackAlerts | | [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/target/types/public/alert_types/geo_containment/query_builder/util_components/single_field_select.d.ts#:~:text=IFieldType), [single_field_select.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/target/types/public/alert_types/geo_containment/query_builder/util_components/single_field_select.d.ts#:~:text=IFieldType)+ 16 more | 8.1 | +| stackAlerts | | [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=esKuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=esKuery) | 8.1 | +| stackAlerts | | [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=esQuery) | 8.1 | +| stackAlerts | | [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/target/types/public/alert_types/geo_containment/query_builder/util_components/single_field_select.d.ts#:~:text=IFieldType), [single_field_select.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/target/types/public/alert_types/geo_containment/query_builder/util_components/single_field_select.d.ts#:~:text=IFieldType)+ 42 more | 8.1 | +| stackAlerts | | [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/util_components/single_field_select.tsx#:~:text=IFieldType), [single_field_select.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/target/types/public/alert_types/geo_containment/query_builder/util_components/single_field_select.d.ts#:~:text=IFieldType), [single_field_select.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/stack_alerts/target/types/public/alert_types/geo_containment/query_builder/util_components/single_field_select.d.ts#:~:text=IFieldType)+ 16 more | 8.1 | +| alerting | | [rules_client.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/alerting/server/rules_client/rules_client.ts#:~:text=KueryNode), [rules_client.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/alerting/server/rules_client/rules_client.ts#:~:text=KueryNode), [rules_client.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/alerting/server/rules_client/rules_client.ts#:~:text=KueryNode) | 8.1 | +| alerting | | [rules_client.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/alerting/server/rules_client/rules_client.ts#:~:text=KueryNode), [rules_client.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/alerting/server/rules_client/rules_client.ts#:~:text=KueryNode), [rules_client.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/alerting/server/rules_client/rules_client.ts#:~:text=KueryNode) | 8.1 | +| alerting | | [rules_client.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/alerting/server/rules_client/rules_client.ts#:~:text=nodeBuilder), [rules_client.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/alerting/server/rules_client/rules_client.ts#:~:text=nodeBuilder), [rules_client.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/alerting/server/rules_client/rules_client.ts#:~:text=nodeBuilder), [find_and_cleanup_tasks.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/actions/server/cleanup_failed_executions/find_and_cleanup_tasks.ts#:~:text=nodeBuilder), [find_and_cleanup_tasks.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/actions/server/cleanup_failed_executions/find_and_cleanup_tasks.ts#:~:text=nodeBuilder), [find_and_cleanup_tasks.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/actions/server/cleanup_failed_executions/find_and_cleanup_tasks.ts#:~:text=nodeBuilder), [find_and_cleanup_tasks.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/actions/server/cleanup_failed_executions/find_and_cleanup_tasks.ts#:~:text=nodeBuilder), [find_and_cleanup_tasks.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/actions/server/cleanup_failed_executions/find_and_cleanup_tasks.ts#:~:text=nodeBuilder) | 8.1 | +| alerting | | [rules_client.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/alerting/server/rules_client/rules_client.ts#:~:text=KueryNode), [rules_client.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/alerting/server/rules_client/rules_client.ts#:~:text=KueryNode), [rules_client.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/alerting/server/rules_client/rules_client.ts#:~:text=KueryNode) | 8.1 | + + + +## Kibana Core + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| + + + + +## Kibana Presentation + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| +| dashboard | | [save_dashboard.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/save_dashboard.ts#:~:text=esFilters), [save_dashboard.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/save_dashboard.ts#:~:text=esFilters), [sync_dashboard_container_input.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/sync_dashboard_container_input.ts#:~:text=esFilters), [sync_dashboard_container_input.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/sync_dashboard_container_input.ts#:~:text=esFilters), [sync_dashboard_container_input.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/sync_dashboard_container_input.ts#:~:text=esFilters), [plugin.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/plugin.tsx#:~:text=esFilters), [plugin.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/plugin.tsx#:~:text=esFilters), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/locator.ts#:~:text=esFilters), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/locator.ts#:~:text=esFilters), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/url_generator.ts#:~:text=esFilters)+ 11 more | 8.1 | +| dashboard | | [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [saved_dashboard.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/saved_dashboards/saved_dashboard.ts#:~:text=Filter), [saved_dashboard.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/saved_dashboards/saved_dashboard.ts#:~:text=Filter), [dashboard_state_slice.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/state/dashboard_state_slice.ts#:~:text=Filter), [dashboard_state_slice.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/state/dashboard_state_slice.ts#:~:text=Filter), [dashboard_state_slice.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/state/dashboard_state_slice.ts#:~:text=Filter)+ 36 more | 8.1 | +| dashboard | | [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [saved_dashboard.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/saved_dashboards/saved_dashboard.ts#:~:text=Filter), [saved_dashboard.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/saved_dashboards/saved_dashboard.ts#:~:text=Filter), [dashboard_state_slice.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/state/dashboard_state_slice.ts#:~:text=Filter), [dashboard_state_slice.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/state/dashboard_state_slice.ts#:~:text=Filter), [dashboard_state_slice.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/state/dashboard_state_slice.ts#:~:text=Filter)+ 36 more | 8.1 | +| dashboard | | [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [filter_utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/lib/filter_utils.ts#:~:text=Filter), [saved_dashboard.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/saved_dashboards/saved_dashboard.ts#:~:text=Filter), [saved_dashboard.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/saved_dashboards/saved_dashboard.ts#:~:text=Filter), [dashboard_state_slice.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/state/dashboard_state_slice.ts#:~:text=Filter), [dashboard_state_slice.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/state/dashboard_state_slice.ts#:~:text=Filter), [dashboard_state_slice.ts](https://github.com/elastic/kibana/tree/master/src/plugins/dashboard/public/application/state/dashboard_state_slice.ts#:~:text=Filter)+ 36 more | 8.1 | +| inputControlVis | | [list_control_factory.ts](https://github.com/elastic/kibana/tree/master/src/plugins/input_control_vis/public/control/list_control_factory.ts#:~:text=fetch), [range_control_factory.ts](https://github.com/elastic/kibana/tree/master/src/plugins/input_control_vis/public/control/range_control_factory.ts#:~:text=fetch) | 8.1 | +| inputControlVis | | [list_control_factory.ts](https://github.com/elastic/kibana/tree/master/src/plugins/input_control_vis/public/control/list_control_factory.ts#:~:text=fetch), [range_control_factory.ts](https://github.com/elastic/kibana/tree/master/src/plugins/input_control_vis/public/control/range_control_factory.ts#:~:text=fetch) | 8.1 | + + + +## Kibana Reporting Services + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| + + + + +## Kibana Telemetry + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| + + + + +## Logs and Metrics UI + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| + + + + +## Logstash + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| + + + + +## Machine Learning UI + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| + + + + +## Observability UI + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| + + + + +## Platform Security + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| + + + + +## Security asset management + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| + + + + +## Security solution + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| + + + + +## Stack Management + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| + + + + +## Stack Monitoring + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| +| monitoring | | [use_derived_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/public/alerts/components/param_details_form/use_derived_index_pattern.tsx#:~:text=IFieldType), [use_derived_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/public/alerts/components/param_details_form/use_derived_index_pattern.tsx#:~:text=IFieldType) | 8.1 | +| monitoring | | [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/public/components/kuery_bar/index.tsx#:~:text=esKuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/public/components/kuery_bar/index.tsx#:~:text=esKuery), [kuery.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/public/lib/kuery.ts#:~:text=esKuery), [kuery.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/public/lib/kuery.ts#:~:text=esKuery), [kuery.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/public/lib/kuery.ts#:~:text=esKuery) | 8.1 | +| monitoring | | [use_derived_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/public/alerts/components/param_details_form/use_derived_index_pattern.tsx#:~:text=IFieldType), [use_derived_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/public/alerts/components/param_details_form/use_derived_index_pattern.tsx#:~:text=IFieldType), [use_derived_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/public/alerts/components/param_details_form/use_derived_index_pattern.tsx#:~:text=IFieldType), [use_derived_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/public/alerts/components/param_details_form/use_derived_index_pattern.tsx#:~:text=IFieldType) | 8.1 | +| monitoring | | [use_derived_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/public/alerts/components/param_details_form/use_derived_index_pattern.tsx#:~:text=IFieldType), [use_derived_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/monitoring/public/alerts/components/param_details_form/use_derived_index_pattern.tsx#:~:text=IFieldType) | 8.1 | + + + +## Uptime + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| + + + + +## Vis Editors + +| Plugin | Deprecated API | Reference location(s) | Remove By | +| --------|-------|-----------|-----------| \ No newline at end of file diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 95b90a3248ef1..8dd032f64d5e1 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github summary: API docs for the devTools plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index ed763c223de62..66a9cf62fdc04 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github summary: API docs for the discover plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index d0de6f5358f56..8efdfa4b38b16 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github summary: API docs for the discoverEnhanced plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/elastic_apm_synthtrace.devdocs.json b/api_docs/elastic_apm_synthtrace.devdocs.json index d3367b38ddf18..4188c3f35a777 100644 --- a/api_docs/elastic_apm_synthtrace.devdocs.json +++ b/api_docs/elastic_apm_synthtrace.devdocs.json @@ -484,7 +484,7 @@ "section": "def-server.ApmException", "text": "ApmException" }, - "[] | undefined; 'error.grouping_name'?: string | undefined; 'error.grouping_key'?: string | undefined; 'host.name'?: string | undefined; 'kubernetes.pod.uid'?: string | undefined; 'observer.version'?: string | undefined; 'observer.version_major'?: number | undefined; 'parent.id'?: string | undefined; 'processor.event'?: string | undefined; 'processor.name'?: string | undefined; 'trace.id'?: string | undefined; 'transaction.name'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.id'?: string | undefined; 'transaction.duration.us'?: number | undefined; 'transaction.sampled'?: true | undefined; 'service.name'?: string | undefined; 'service.environment'?: string | undefined; 'service.node.name'?: string | undefined; 'span.id'?: string | undefined; 'span.name'?: string | undefined; 'span.type'?: string | undefined; 'span.subtype'?: string | undefined; 'span.duration.us'?: number | undefined; 'span.destination.service.name'?: string | undefined; 'span.destination.service.resource'?: string | undefined; 'span.destination.service.type'?: string | undefined; 'span.destination.service.response_time.sum.us'?: number | undefined; 'span.destination.service.response_time.count'?: number | undefined; 'span.self_time.count'?: number | undefined; 'span.self_time.sum.us'?: number | undefined; 'system.process.memory.size'?: number | undefined; 'system.memory.actual.free'?: number | undefined; 'system.memory.total'?: number | undefined; 'system.cpu.total.norm.pct'?: number | undefined; 'system.process.memory.rss.bytes'?: number | undefined; 'system.process.cpu.total.norm.pct'?: number | undefined; 'jvm.memory.heap.used'?: number | undefined; 'jvm.memory.non_heap.used'?: number | undefined; 'jvm.thread.count'?: number | undefined; }[]" + "[] | undefined; 'error.grouping_name'?: string | undefined; 'error.grouping_key'?: string | undefined; 'host.name'?: string | undefined; 'kubernetes.pod.uid'?: string | undefined; 'observer.version'?: string | undefined; 'observer.version_major'?: number | undefined; 'parent.id'?: string | undefined; 'processor.event'?: string | undefined; 'processor.name'?: string | undefined; 'trace.id'?: string | undefined; 'transaction.name'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.id'?: string | undefined; 'transaction.duration.us'?: number | undefined; 'transaction.sampled'?: true | undefined; 'service.name'?: string | undefined; 'service.version'?: string | undefined; 'service.environment'?: string | undefined; 'service.node.name'?: string | undefined; 'service.runtime.name'?: string | undefined; 'service.runtime.version'?: string | undefined; 'service.framework.name'?: string | undefined; 'span.id'?: string | undefined; 'span.name'?: string | undefined; 'span.type'?: string | undefined; 'span.subtype'?: string | undefined; 'span.duration.us'?: number | undefined; 'span.destination.service.name'?: string | undefined; 'span.destination.service.resource'?: string | undefined; 'span.destination.service.type'?: string | undefined; 'span.destination.service.response_time.sum.us'?: number | undefined; 'span.destination.service.response_time.count'?: number | undefined; 'span.self_time.count'?: number | undefined; 'span.self_time.sum.us'?: number | undefined; 'cloud.provider'?: string | undefined; 'cloud.project.name'?: string | undefined; 'cloud.service.name'?: string | undefined; 'cloud.availability_zone'?: string | undefined; 'cloud.machine.type'?: string | undefined; 'cloud.region'?: string | undefined; 'host.os.platform'?: string | undefined; 'faas.id'?: string | undefined; 'faas.coldstart'?: boolean | undefined; 'faas.execution'?: string | undefined; 'faas.trigger.type'?: string | undefined; 'faas.trigger.request_id'?: string | undefined; 'system.process.memory.size'?: number | undefined; 'system.memory.actual.free'?: number | undefined; 'system.memory.total'?: number | undefined; 'system.cpu.total.norm.pct'?: number | undefined; 'system.process.memory.rss.bytes'?: number | undefined; 'system.process.cpu.total.norm.pct'?: number | undefined; 'jvm.memory.heap.used'?: number | undefined; 'jvm.memory.non_heap.used'?: number | undefined; 'jvm.thread.count'?: number | undefined; }[]" ], "path": "packages/elastic-apm-synthtrace/src/lib/apm/index.ts", "deprecated": false, @@ -524,7 +524,7 @@ "section": "def-server.ApmException", "text": "ApmException" }, - "[] | undefined; 'error.grouping_name'?: string | undefined; 'error.grouping_key'?: string | undefined; 'host.name'?: string | undefined; 'kubernetes.pod.uid'?: string | undefined; 'observer.version'?: string | undefined; 'observer.version_major'?: number | undefined; 'parent.id'?: string | undefined; 'processor.event'?: string | undefined; 'processor.name'?: string | undefined; 'trace.id'?: string | undefined; 'transaction.name'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.id'?: string | undefined; 'transaction.duration.us'?: number | undefined; 'transaction.duration.histogram'?: { values: number[]; counts: number[]; } | undefined; 'transaction.sampled'?: true | undefined; 'service.name'?: string | undefined; 'service.environment'?: string | undefined; 'service.node.name'?: string | undefined; 'span.id'?: string | undefined; 'span.name'?: string | undefined; 'span.type'?: string | undefined; 'span.subtype'?: string | undefined; 'span.duration.us'?: number | undefined; 'span.destination.service.name'?: string | undefined; 'span.destination.service.resource'?: string | undefined; 'span.destination.service.type'?: string | undefined; 'span.self_time.count'?: number | undefined; 'span.self_time.sum.us'?: number | undefined; 'system.process.memory.size'?: number | undefined; 'system.memory.actual.free'?: number | undefined; 'system.memory.total'?: number | undefined; 'system.cpu.total.norm.pct'?: number | undefined; 'system.process.memory.rss.bytes'?: number | undefined; 'system.process.cpu.total.norm.pct'?: number | undefined; 'jvm.memory.heap.used'?: number | undefined; 'jvm.memory.non_heap.used'?: number | undefined; 'jvm.thread.count'?: number | undefined; }[]" + "[] | undefined; 'error.grouping_name'?: string | undefined; 'error.grouping_key'?: string | undefined; 'host.name'?: string | undefined; 'kubernetes.pod.uid'?: string | undefined; 'observer.version'?: string | undefined; 'observer.version_major'?: number | undefined; 'parent.id'?: string | undefined; 'processor.event'?: string | undefined; 'processor.name'?: string | undefined; 'trace.id'?: string | undefined; 'transaction.name'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.id'?: string | undefined; 'transaction.duration.us'?: number | undefined; 'transaction.duration.histogram'?: { values: number[]; counts: number[]; } | undefined; 'transaction.sampled'?: true | undefined; 'service.name'?: string | undefined; 'service.version'?: string | undefined; 'service.environment'?: string | undefined; 'service.node.name'?: string | undefined; 'service.runtime.name'?: string | undefined; 'service.runtime.version'?: string | undefined; 'service.framework.name'?: string | undefined; 'span.id'?: string | undefined; 'span.name'?: string | undefined; 'span.type'?: string | undefined; 'span.subtype'?: string | undefined; 'span.duration.us'?: number | undefined; 'span.destination.service.name'?: string | undefined; 'span.destination.service.resource'?: string | undefined; 'span.destination.service.type'?: string | undefined; 'span.self_time.count'?: number | undefined; 'span.self_time.sum.us'?: number | undefined; 'cloud.provider'?: string | undefined; 'cloud.project.name'?: string | undefined; 'cloud.service.name'?: string | undefined; 'cloud.availability_zone'?: string | undefined; 'cloud.machine.type'?: string | undefined; 'cloud.region'?: string | undefined; 'host.os.platform'?: string | undefined; 'faas.id'?: string | undefined; 'faas.coldstart'?: boolean | undefined; 'faas.execution'?: string | undefined; 'faas.trigger.type'?: string | undefined; 'faas.trigger.request_id'?: string | undefined; 'system.process.memory.size'?: number | undefined; 'system.memory.actual.free'?: number | undefined; 'system.memory.total'?: number | undefined; 'system.cpu.total.norm.pct'?: number | undefined; 'system.process.memory.rss.bytes'?: number | undefined; 'system.process.cpu.total.norm.pct'?: number | undefined; 'jvm.memory.heap.used'?: number | undefined; 'jvm.memory.non_heap.used'?: number | undefined; 'jvm.thread.count'?: number | undefined; }[]" ], "path": "packages/elastic-apm-synthtrace/src/lib/apm/index.ts", "deprecated": false, diff --git a/api_docs/elastic_apm_synthtrace.mdx b/api_docs/elastic_apm_synthtrace.mdx index ff32bcd269521..c7e1e721ec579 100644 --- a/api_docs/elastic_apm_synthtrace.mdx +++ b/api_docs/elastic_apm_synthtrace.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/elastic-apm-synthtrace title: "@elastic/apm-synthtrace" image: https://source.unsplash.com/400x175/?github summary: API docs for the @elastic/apm-synthtrace plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@elastic/apm-synthtrace'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/elastic_datemath.mdx b/api_docs/elastic_datemath.mdx index 13d610d79d740..17412cf9336c3 100644 --- a/api_docs/elastic_datemath.mdx +++ b/api_docs/elastic_datemath.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/elastic-datemath title: "@elastic/datemath" image: https://source.unsplash.com/400x175/?github summary: API docs for the @elastic/datemath plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@elastic/datemath'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index dfb7ba9c8b0cc..0cd1d9d0ffb0b 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github summary: API docs for the embeddable plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index f4796a5a9a03a..9e35225aeed18 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github summary: API docs for the embeddableEnhanced plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 228e107f08266..4b0f9f1d27e12 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github summary: API docs for the encryptedSavedObjects plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index ecdd4c4be82e1..90e3baa926ed2 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github summary: API docs for the enterpriseSearch plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 3bca566863bfd..46c2630a3dced 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github summary: API docs for the esUiShared plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index 552c90307b02b..f0d6dd77b7fd0 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github summary: API docs for the eventLog plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index 54fbc95643d7d..018a43a0d1ede 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionError plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index e2fd4ce7a12c6..ca78d69bcdafa 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionGauge plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 8c428f4ebe563..276355f698815 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionHeatmap plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index 420184f8b75fe..f1ed57455a566 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionImage plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index 6093c5bfcde1a..e5ed85750e1b0 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionMetric plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index d445cda2d232c..91e2a27265816 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionMetricVis plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_pie.mdx b/api_docs/expression_pie.mdx index 7d684f0bab50f..9f30f8d8643cb 100644 --- a/api_docs/expression_pie.mdx +++ b/api_docs/expression_pie.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionPie title: "expressionPie" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionPie plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPie'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 0b8b2df34aa66..0e25dd631b0cd 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionRepeatImage plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index 53a3a39558ed4..36b1278166a9f 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionRevealImage plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index 72c8f7063a414..b17d82a0c4c87 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionShape plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index c8502e3247063..bc835e9b95daf 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionTagcloud plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 853b1d48f80dd..399bea13537c8 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressions plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 5a851d07e3756..ea065bbe54b22 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github summary: API docs for the features plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index 0638f4ef72455..104be21a086b5 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github summary: API docs for the fieldFormats plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 6ea39247b4a0d..af752579b0a54 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github summary: API docs for the fileUpload plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 0591712f9d6d8..bb628b4492b91 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github summary: API docs for the fleet plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 4356c36102ce6..32d4863678f5e 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github summary: API docs for the globalSearch plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/home.devdocs.json b/api_docs/home.devdocs.json index 1a3d4fb0fa88a..43e3e4a7f74f9 100644 --- a/api_docs/home.devdocs.json +++ b/api_docs/home.devdocs.json @@ -1099,7 +1099,7 @@ "references": [ { "plugin": "cloud", - "path": "x-pack/plugins/cloud/public/plugin.ts" + "path": "x-pack/plugins/cloud/public/plugin.tsx" }, { "plugin": "apm", diff --git a/api_docs/home.mdx b/api_docs/home.mdx index a45fbfd59d06f..3400ea7b74c77 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github summary: API docs for the home plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index d822b17115945..cb38a550ce58b 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the indexLifecycleManagement plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/index_management.devdocs.json b/api_docs/index_management.devdocs.json index 81f748459e33d..ab724a4b13239 100644 --- a/api_docs/index_management.devdocs.json +++ b/api_docs/index_management.devdocs.json @@ -112,6 +112,9 @@ "tags": [], "label": "health", "description": [], + "signature": [ + "string | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, @@ -122,6 +125,9 @@ "tags": [], "label": "status", "description": [], + "signature": [ + "string | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, @@ -142,52 +148,55 @@ "tags": [], "label": "uuid", "description": [], + "signature": [ + "string | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, { "parentPluginId": "indexManagement", "id": "def-public.Index.primary", - "type": "string", + "type": "CompoundType", "tags": [], "label": "primary", "description": [], + "signature": [ + "string | number | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, { "parentPluginId": "indexManagement", "id": "def-public.Index.replica", - "type": "string", + "type": "CompoundType", "tags": [], "label": "replica", "description": [], + "signature": [ + "string | number | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, { "parentPluginId": "indexManagement", "id": "def-public.Index.documents", - "type": "string", + "type": "number", "tags": [], "label": "documents", "description": [], - "signature": [ - "string | undefined" - ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, { "parentPluginId": "indexManagement", "id": "def-public.Index.size", - "type": "Any", + "type": "string", "tags": [], "label": "size", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, @@ -375,6 +384,9 @@ "tags": [], "label": "health", "description": [], + "signature": [ + "string | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, @@ -385,6 +397,9 @@ "tags": [], "label": "status", "description": [], + "signature": [ + "string | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, @@ -405,52 +420,55 @@ "tags": [], "label": "uuid", "description": [], + "signature": [ + "string | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, { "parentPluginId": "indexManagement", "id": "def-server.Index.primary", - "type": "string", + "type": "CompoundType", "tags": [], "label": "primary", "description": [], + "signature": [ + "string | number | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, { "parentPluginId": "indexManagement", "id": "def-server.Index.replica", - "type": "string", + "type": "CompoundType", "tags": [], "label": "replica", "description": [], + "signature": [ + "string | number | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, { "parentPluginId": "indexManagement", "id": "def-server.Index.documents", - "type": "string", + "type": "number", "tags": [], "label": "documents", "description": [], - "signature": [ - "string | undefined" - ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, { "parentPluginId": "indexManagement", "id": "def-server.Index.size", - "type": "Any", + "type": "string", "tags": [], "label": "size", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, @@ -1438,6 +1456,9 @@ "tags": [], "label": "health", "description": [], + "signature": [ + "string | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, @@ -1448,6 +1469,9 @@ "tags": [], "label": "status", "description": [], + "signature": [ + "string | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, @@ -1468,52 +1492,55 @@ "tags": [], "label": "uuid", "description": [], + "signature": [ + "string | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, { "parentPluginId": "indexManagement", "id": "def-common.Index.primary", - "type": "string", + "type": "CompoundType", "tags": [], "label": "primary", "description": [], + "signature": [ + "string | number | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, { "parentPluginId": "indexManagement", "id": "def-common.Index.replica", - "type": "string", + "type": "CompoundType", "tags": [], "label": "replica", "description": [], + "signature": [ + "string | number | undefined" + ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, { "parentPluginId": "indexManagement", "id": "def-common.Index.documents", - "type": "string", + "type": "number", "tags": [], "label": "documents", "description": [], - "signature": [ - "string | undefined" - ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, { "parentPluginId": "indexManagement", "id": "def-common.Index.size", - "type": "Any", + "type": "string", "tags": [], "label": "size", "description": [], - "signature": [ - "any" - ], "path": "x-pack/plugins/index_management/common/types/indices.ts", "deprecated": false }, diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 029223ed66a2f..1ca48ed8d4e42 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the indexManagement plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,7 +18,7 @@ Contact [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-ma | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 169 | 3 | 164 | 3 | +| 169 | 0 | 164 | 3 | ## Client diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 626608d0cfb12..fe9667eae1442 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github summary: API docs for the infra plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 13dcdca6c76af..c272173dbf0d6 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github summary: API docs for the inspector plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 272e3880cbae1..5729f801acba1 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github summary: API docs for the interactiveSetup plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index 0c3b8d3c23085..b54f7af1d61d1 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ace plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index 66f644bc432a2..121b1c8740407 100644 --- a/api_docs/kbn_alerts.mdx +++ b/api_docs/kbn_alerts.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-alerts title: "@kbn/alerts" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/alerts plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index 53f6c6aa3d186..31529e687dccb 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/analytics plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 79837dd6dc09e..d7a3634e1c02f 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/apm-config-loader plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index dace3da180009..93f48b7d18d8a 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/apm-utils plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index c783e172c8d72..b5766b136a98f 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/cli-dev-mode plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index 3fa38a34b0680..e86ecfe240169 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/config plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index d6ef1ea0186fd..a2c655201d178 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/config-schema plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 3dc3647259db3..a0c9b30e38dcc 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/crypto plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index 3289527637504..7bc1798dac801 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/dev-utils plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index 1710d4b84a9f3..95b6f30cbda1e 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/docs-utils plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 6517e3f9e3ca4..22080cb75af77 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/es-archiver plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index 88afa3fcd145b..a3cb51446becd 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/es-query plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 30444e4f5904a..197ac441bc792 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/field-types plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index 49da6d668b667..c83d0d3c50f00 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/i18n plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 94fd0897fe1a3..55d059965ecb1 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/interpreter plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -12,7 +12,7 @@ import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; -Contact [Owner missing] for questions regarding this plugin. +Contact App Services for questions regarding this plugin. **Code health stats** diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index da1ef28891025..3625829226576 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/io-ts-utils plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index a7cc25ba000f7..92d18856bad7c 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/logging plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index b92f3b66bda46..573a077d93aed 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/mapbox-gl plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 35835226ad936..df75605be760b 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/monaco plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 9981ad9f47da3..8aa1509f17210 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/optimizer plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index d819c24ae99ea..92c93c36b174a 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/plugin-generator plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index 10a03b103e60d..ebdb90cb77685 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/plugin-helpers plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_pm.mdx b/api_docs/kbn_pm.mdx index 3fde9cc524785..f5c1f0bf69e08 100644 --- a/api_docs/kbn_pm.mdx +++ b/api_docs/kbn_pm.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-pm title: "@kbn/pm" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/pm plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/pm'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index 1389e78737356..49ee1aa9c823c 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/react-field plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index d4a630ab7d377..9bb8b7144b2fa 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/rule-data-utils plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 7e99ef4f4558a..8032305998f26 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 2235ccc9f5276..1c984077e50b7 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-es-utils plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 6b2b4ec1dac3e..28cb7da82c5ee 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index 689fdfd6c3fbe..679af1df82423 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.devdocs.json b/api_docs/kbn_securitysolution_io_ts_list_types.devdocs.json index 7d525a716f3d3..5976f7481cb35 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.devdocs.json +++ b/api_docs/kbn_securitysolution_io_ts_list_types.devdocs.json @@ -3790,7 +3790,7 @@ "label": "SummaryExceptionListSchema", "description": [], "signature": [ - "{ id?: string | undefined; list_id?: string | undefined; namespace_type?: \"single\" | \"agnostic\" | undefined; }" + "{ filter?: string | undefined; id?: string | undefined; list_id?: string | undefined; namespace_type?: \"single\" | \"agnostic\" | undefined; }" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.ts", "deprecated": false, @@ -3804,7 +3804,7 @@ "label": "SummaryExceptionListSchemaDecoded", "description": [], "signature": [ - "Omit<{ id: string | undefined; list_id: string | undefined; namespace_type: \"single\" | \"agnostic\" | undefined; }, \"namespace_type\"> & { namespace_type: \"single\" | \"agnostic\"; }" + "Omit<{ filter: string | undefined; id: string | undefined; list_id: string | undefined; namespace_type: \"single\" | \"agnostic\" | undefined; }, \"namespace_type\"> & { namespace_type: \"single\" | \"agnostic\"; filter: string; }" ], "path": "packages/kbn-securitysolution-io-ts-list-types/src/request/summary_exception_list_schema/index.ts", "deprecated": false, @@ -8082,7 +8082,9 @@ "ExactC", "<", "PartialC", - "<{ id: ", + "<{ filter: ", + "StringC", + "; id: ", "Type", "; list_id: ", "Type", diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index b006ed07c5c1a..e545a2628db14 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index 514c53211b67b..a809b1c48427d 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index 79917150b1746..8b6df135d9853 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index e0cb314cd4d49..cc79a95bcad3a 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-list-api plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index b6ede38c26ab0..a4f18d9647a3b 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-list-constants plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index 465bdbc7457e9..1ff24984a869a 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index a4fdbae577e2f..4974a3121c43a 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-list-utils plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index 55303e48b54d5..380a973c8109c 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-rules plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index 5467f2659dacd..8ce257e6d44db 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-t-grid plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index 93e625706da95..41fa703812efc 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-utils plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index f36659b79489f..d5eac6a0694a2 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/server-http-tools plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index cb268a2f9cb51..a3a80d3e389f1 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/server-route-repository plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index f0226566129a5..291089f525db1 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/std plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index e376dc0f468ac..94cbaa583e3d3 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/storybook plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -12,7 +12,7 @@ import kbnStorybookObj from './kbn_storybook.devdocs.json'; -Contact [Owner missing] for questions regarding this plugin. +Contact Operations for questions regarding this plugin. **Code health stats** diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index e4e4064530f77..fafa09e140292 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/telemetry-tools plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index 07f4243d68ab9..8c6af854e191a 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/test plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -12,7 +12,7 @@ import kbnTestObj from './kbn_test.devdocs.json'; -Contact [Owner missing] for questions regarding this plugin. +Contact Operations for questions regarding this plugin. **Code health stats** diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 1a7f7fc353b63..ce2a13817156a 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/typed-react-router-config plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index c64f599e230c3..e54cab4d69818 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ui-theme plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index 9085cf9e0c844..4774234d1878e 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/utility-types plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index 31c917591dcb7..9e93f672cf3c7 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/utils plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index 0b87d40a82d18..91f202a6234b7 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github summary: API docs for the kibanaOverview plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index 58904fbd011e2..aaca51943ccc7 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github summary: API docs for the kibanaReact plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 4662b67b91eb1..d18745ae21302 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github summary: API docs for the kibanaUtils plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/lens.devdocs.json b/api_docs/lens.devdocs.json index a5401a4ff7d80..901e88503788d 100644 --- a/api_docs/lens.devdocs.json +++ b/api_docs/lens.devdocs.json @@ -2299,7 +2299,15 @@ }, " | ", "LensByReferenceInput", - ") & { withActions?: boolean | undefined; }" + ") & { withDefaultActions?: boolean | undefined; extraActions?: ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.Action", + "text": "Action" + }, + "[] | undefined; }" ], "path": "x-pack/plugins/lens/public/embeddable/embeddable_component.tsx", "deprecated": false, @@ -3337,6 +3345,25 @@ ], "path": "x-pack/plugins/lens/server/plugin.tsx", "deprecated": false + }, + { + "parentPluginId": "lens", + "id": "def-server.PluginStartContract.dataViews", + "type": "Object", + "tags": [], + "label": "dataViews", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "server", + "docId": "kibDataViewsPluginApi", + "section": "def-server.DataViewsServerPluginStart", + "text": "DataViewsServerPluginStart" + } + ], + "path": "x-pack/plugins/lens/server/plugin.tsx", + "deprecated": false } ], "initialIsOpen": false @@ -4462,6 +4489,20 @@ "deprecated": false, "initialIsOpen": false }, + { + "parentPluginId": "lens", + "id": "def-common.DOCUMENT_FIELD_NAME", + "type": "string", + "tags": [], + "label": "DOCUMENT_FIELD_NAME", + "description": [], + "signature": [ + "\"___records___\"" + ], + "path": "x-pack/plugins/lens/common/constants.ts", + "deprecated": false, + "initialIsOpen": false + }, { "parentPluginId": "lens", "id": "def-common.FormatFactory", diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 55e8d55499443..9db735fd22525 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github summary: API docs for the lens plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,7 +18,7 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 274 | 0 | 252 | 31 | +| 276 | 0 | 254 | 31 | ## Client diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 699fff49bff0f..f3a4df3a4cedf 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github summary: API docs for the licenseApiGuard plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index f2ad08dfd5cc6..54ab3f110c3e6 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the licenseManagement plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 1198fe6807582..f98edec73a073 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github summary: API docs for the licensing plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/lists.devdocs.json b/api_docs/lists.devdocs.json index 132246088013b..755ff1c172200 100644 --- a/api_docs/lists.devdocs.json +++ b/api_docs/lists.devdocs.json @@ -536,6 +536,7 @@ "params", "params", "params", + "params", "return" ], "label": "getExceptionListSummary", @@ -543,7 +544,7 @@ "\nFetch an exception list parent container" ], "signature": [ - "({ listId, id, namespaceType, }: ", + "({ filter, listId, id, namespaceType, }: ", "GetExceptionListSummaryOptions", ") => Promise<{ windows: number; linux: number; macos: number; total: number; } | null>" ], @@ -555,7 +556,7 @@ "id": "def-server.ExceptionListClient.getExceptionListSummary.$1", "type": "Object", "tags": [], - "label": "{\n listId,\n id,\n namespaceType,\n }", + "label": "{\n filter,\n listId,\n id,\n namespaceType,\n }", "description": [], "signature": [ "GetExceptionListSummaryOptions" @@ -2792,6 +2793,146 @@ "deprecated": false, "initialIsOpen": false }, + { + "parentPluginId": "lists", + "id": "def-server.ExceptionsListPreDeleteItemServerExtension", + "type": "Type", + "tags": [], + "label": "ExceptionsListPreDeleteItemServerExtension", + "description": [ + "\nExtension point is triggered prior to performing a list item deletion. Note, this extension point\nis triggered by both `deleteExceptionListItem()` and `deleteExceptionListItemById()` methods of the\n`ExceptionListClient` class" + ], + "signature": [ + "ServerExtensionPointDefinition<\"exceptionsListPreDeleteItem\", ", + "DeleteExceptionListItemOptions", + ", ", + "DeleteExceptionListItemOptions", + ">" + ], + "path": "x-pack/plugins/lists/server/services/extension_points/types.ts", + "deprecated": false, + "initialIsOpen": false + }, + { + "parentPluginId": "lists", + "id": "def-server.ExceptionsListPreExportServerExtension", + "type": "Type", + "tags": [], + "label": "ExceptionsListPreExportServerExtension", + "description": [ + "\nExtension point is triggered prior to performing an `export` operation against exceptions list and items" + ], + "signature": [ + "ServerExtensionPointDefinition<\"exceptionsListPreExport\", ", + "ExportExceptionListAndItemsOptions", + ", ", + "ExportExceptionListAndItemsOptions", + ">" + ], + "path": "x-pack/plugins/lists/server/services/extension_points/types.ts", + "deprecated": false, + "initialIsOpen": false + }, + { + "parentPluginId": "lists", + "id": "def-server.ExceptionsListPreGetOneItemServerExtension", + "type": "Type", + "tags": [], + "label": "ExceptionsListPreGetOneItemServerExtension", + "description": [ + "\nExtension point is triggered prior to performing a `patch` operation on the exception item" + ], + "signature": [ + "ServerExtensionPointDefinition<\"exceptionsListPreGetOneItem\", ", + "GetExceptionListItemOptions", + ", ", + "GetExceptionListItemOptions", + ">" + ], + "path": "x-pack/plugins/lists/server/services/extension_points/types.ts", + "deprecated": false, + "initialIsOpen": false + }, + { + "parentPluginId": "lists", + "id": "def-server.ExceptionsListPreImportServerExtension", + "type": "Type", + "tags": [], + "label": "ExceptionsListPreImportServerExtension", + "description": [ + "\nExtension point is triggered prior processing an import of data into the Exceptions Lists. The callback\nin this extension will be called by both the `importExceptionListAndItems()` and\n`importExceptionListAndItemsAsArray()`" + ], + "signature": [ + "ServerExtensionPointDefinition<\"exceptionsListPreImport\", ", + "PromiseFromStreams", + ", ", + "PromiseFromStreams", + ">" + ], + "path": "x-pack/plugins/lists/server/services/extension_points/types.ts", + "deprecated": false, + "initialIsOpen": false + }, + { + "parentPluginId": "lists", + "id": "def-server.ExceptionsListPreMultiListFindServerExtension", + "type": "Type", + "tags": [], + "label": "ExceptionsListPreMultiListFindServerExtension", + "description": [ + "\nExtension point is triggered prior to performing a `find` operation against a multiple lists" + ], + "signature": [ + "ServerExtensionPointDefinition<\"exceptionsListPreMultiListFind\", ", + "FindExceptionListsItemOptions", + ", ", + "FindExceptionListsItemOptions", + ">" + ], + "path": "x-pack/plugins/lists/server/services/extension_points/types.ts", + "deprecated": false, + "initialIsOpen": false + }, + { + "parentPluginId": "lists", + "id": "def-server.ExceptionsListPreSingleListFindServerExtension", + "type": "Type", + "tags": [], + "label": "ExceptionsListPreSingleListFindServerExtension", + "description": [ + "\nExtension point is triggered prior to performing a `find` operation against a SINGLE list" + ], + "signature": [ + "ServerExtensionPointDefinition<\"exceptionsListPreSingleListFind\", ", + "FindExceptionListItemOptions", + ", ", + "FindExceptionListItemOptions", + ">" + ], + "path": "x-pack/plugins/lists/server/services/extension_points/types.ts", + "deprecated": false, + "initialIsOpen": false + }, + { + "parentPluginId": "lists", + "id": "def-server.ExceptionsListPreSummaryServerExtension", + "type": "Type", + "tags": [], + "label": "ExceptionsListPreSummaryServerExtension", + "description": [ + "\nExtension point is triggered prior to performing a list summary operation" + ], + "signature": [ + "ServerExtensionPointDefinition<\"exceptionsListPreSummary\", ", + "GetExceptionListSummaryOptions", + ", ", + "GetExceptionListSummaryOptions", + ">" + ], + "path": "x-pack/plugins/lists/server/services/extension_points/types.ts", + "deprecated": false, + "initialIsOpen": false + }, { "parentPluginId": "lists", "id": "def-server.ExceptionsListPreUpdateItemServerExtension", @@ -2832,6 +2973,14 @@ "label": "ExtensionPoint", "description": [], "signature": [ + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreImportServerExtension", + "text": "ExceptionsListPreImportServerExtension" + }, + " | ", { "pluginId": "lists", "scope": "server", @@ -2848,17 +2997,53 @@ "text": "ExceptionsListPreUpdateItemServerExtension" }, " | ", - "ExceptionsListPreGetOneItemServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreGetOneItemServerExtension", + "text": "ExceptionsListPreGetOneItemServerExtension" + }, " | ", - "ExceptionsListPreSingleListFindServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreSingleListFindServerExtension", + "text": "ExceptionsListPreSingleListFindServerExtension" + }, " | ", - "ExceptionsListPreMultiListFindServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreMultiListFindServerExtension", + "text": "ExceptionsListPreMultiListFindServerExtension" + }, " | ", - "ExceptionsListPreExportServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreExportServerExtension", + "text": "ExceptionsListPreExportServerExtension" + }, " | ", - "ExceptionsListPreSummaryServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreSummaryServerExtension", + "text": "ExceptionsListPreSummaryServerExtension" + }, " | ", - "ExceptionsListPreDeleteItemServerExtension" + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreDeleteItemServerExtension", + "text": "ExceptionsListPreDeleteItemServerExtension" + } ], "path": "x-pack/plugins/lists/server/services/extension_points/types.ts", "deprecated": false, @@ -2896,6 +3081,14 @@ "label": "extension", "description": [], "signature": [ + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreImportServerExtension", + "text": "ExceptionsListPreImportServerExtension" + }, + " | ", { "pluginId": "lists", "scope": "server", @@ -2912,17 +3105,53 @@ "text": "ExceptionsListPreUpdateItemServerExtension" }, " | ", - "ExceptionsListPreGetOneItemServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreGetOneItemServerExtension", + "text": "ExceptionsListPreGetOneItemServerExtension" + }, " | ", - "ExceptionsListPreSingleListFindServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreSingleListFindServerExtension", + "text": "ExceptionsListPreSingleListFindServerExtension" + }, " | ", - "ExceptionsListPreMultiListFindServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreMultiListFindServerExtension", + "text": "ExceptionsListPreMultiListFindServerExtension" + }, " | ", - "ExceptionsListPreExportServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreExportServerExtension", + "text": "ExceptionsListPreExportServerExtension" + }, " | ", - "ExceptionsListPreSummaryServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreSummaryServerExtension", + "text": "ExceptionsListPreSummaryServerExtension" + }, " | ", - "ExceptionsListPreDeleteItemServerExtension" + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreDeleteItemServerExtension", + "text": "ExceptionsListPreDeleteItemServerExtension" + } ], "path": "x-pack/plugins/lists/server/services/extension_points/types.ts", "deprecated": false @@ -2958,7 +3187,7 @@ "section": "def-server.SavedObjectsClientContract", "text": "SavedObjectsClientContract" }, - ", user: string, disableServerExtensionPoints?: boolean | undefined) => ", + ", user: string, enableServerExtensionPoints?: boolean | undefined) => ", { "pluginId": "lists", "scope": "server", @@ -3323,7 +3552,7 @@ "id": "def-server.ListPluginSetup.getExceptionListClient.$3", "type": "CompoundType", "tags": [], - "label": "disableServerExtensionPoints", + "label": "enableServerExtensionPoints", "description": [], "signature": [ "boolean | undefined" @@ -3435,6 +3664,14 @@ "label": "extension", "description": [], "signature": [ + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreImportServerExtension", + "text": "ExceptionsListPreImportServerExtension" + }, + " | ", { "pluginId": "lists", "scope": "server", @@ -3451,17 +3688,53 @@ "text": "ExceptionsListPreUpdateItemServerExtension" }, " | ", - "ExceptionsListPreGetOneItemServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreGetOneItemServerExtension", + "text": "ExceptionsListPreGetOneItemServerExtension" + }, " | ", - "ExceptionsListPreSingleListFindServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreSingleListFindServerExtension", + "text": "ExceptionsListPreSingleListFindServerExtension" + }, " | ", - "ExceptionsListPreMultiListFindServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreMultiListFindServerExtension", + "text": "ExceptionsListPreMultiListFindServerExtension" + }, " | ", - "ExceptionsListPreExportServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreExportServerExtension", + "text": "ExceptionsListPreExportServerExtension" + }, " | ", - "ExceptionsListPreSummaryServerExtension", + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreSummaryServerExtension", + "text": "ExceptionsListPreSummaryServerExtension" + }, " | ", - "ExceptionsListPreDeleteItemServerExtension" + { + "pluginId": "lists", + "scope": "server", + "docId": "kibListsPluginApi", + "section": "def-server.ExceptionsListPreDeleteItemServerExtension", + "text": "ExceptionsListPreDeleteItemServerExtension" + } ], "path": "x-pack/plugins/lists/server/services/extension_points/types.ts", "deprecated": false diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 4285a72430c91..5ba6977335c53 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github summary: API docs for the lists plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,7 +18,7 @@ Contact [Security detections response](https://github.com/orgs/elastic/teams/sec | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 178 | 0 | 155 | 48 | +| 185 | 0 | 155 | 43 | ## Client diff --git a/api_docs/management.mdx b/api_docs/management.mdx index 10313181e7a87..3c23f7d71aeae 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github summary: API docs for the management plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index b6e7fd89d7fa2..75cc23c71d358 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github summary: API docs for the maps plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index 8ba74b9918d64..219aea9b6e7ff 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github summary: API docs for the mapsEms plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/metrics_entities.mdx b/api_docs/metrics_entities.mdx index 6dd3e841eaa9c..1bfb53b578187 100644 --- a/api_docs/metrics_entities.mdx +++ b/api_docs/metrics_entities.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/metricsEntities title: "metricsEntities" image: https://source.unsplash.com/400x175/?github summary: API docs for the metricsEntities plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'metricsEntities'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/ml.devdocs.json b/api_docs/ml.devdocs.json index 8c762bdbe4f39..5246fd09dc4a3 100644 --- a/api_docs/ml.devdocs.json +++ b/api_docs/ml.devdocs.json @@ -91,7 +91,7 @@ "tags": [], "label": "getFormattedSeverityScore", "description": [ - "\nReturn formatted severity score." + "\nReturns formatted severity score." ], "signature": [ "(score: number) => string" @@ -105,7 +105,9 @@ "type": "number", "tags": [], "label": "score", - "description": [], + "description": [ + "- A normalized score between 0-100, which is based on the probability of the anomalousness of this record" + ], "signature": [ "number" ], @@ -141,7 +143,9 @@ "type": "Function", "tags": [], "label": "getSeverity", - "description": [], + "description": [ + "\nReturns a severity label (one of critical, major, minor, warning or unknown)\nfor the supplied normalized anomaly score (a value between 0 and 100)." + ], "signature": [ "(normalizedScore: number) => ", "SeverityType" @@ -155,7 +159,9 @@ "type": "number", "tags": [], "label": "normalizedScore", - "description": [], + "description": [ + "- A normalized score between 0-100, which is based on the probability of the anomalousness of this record" + ], "signature": [ "number" ], @@ -173,7 +179,9 @@ "type": "Function", "tags": [], "label": "getSeverityColor", - "description": [], + "description": [ + "\nReturns a severity RGB color (one of critical, major, minor, warning, low or blank)\nfor the supplied normalized anomaly score (a value between 0 and 100)." + ], "signature": [ "(normalizedScore: number) => string" ], @@ -186,7 +194,9 @@ "type": "number", "tags": [], "label": "normalizedScore", - "description": [], + "description": [ + "- A normalized score between 0-100, which is based on the probability of the anomalousness of this record" + ], "signature": [ "number" ], @@ -204,7 +214,9 @@ "type": "Function", "tags": [], "label": "getSeverityType", - "description": [], + "description": [ + "\nReturns a severity type (indicating a critical, major, minor, warning or low severity anomaly)\nfor the supplied normalized anomaly score (a value between 0 and 100)." + ], "signature": [ "(normalizedScore: number) => ", { @@ -224,7 +236,9 @@ "type": "number", "tags": [], "label": "normalizedScore", - "description": [], + "description": [ + "- A normalized score between 0-100, which is based on the probability of the anomalousness of this record" + ], "signature": [ "number" ], @@ -342,7 +356,9 @@ "type": "Interface", "tags": [], "label": "AnomaliesTableRecord", - "description": [], + "description": [ + "\nAnomaly table record, representing the fields shown in the ML UI anomalies table." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false, "children": [ @@ -352,7 +368,9 @@ "type": "number", "tags": [], "label": "time", - "description": [], + "description": [ + "\nThe start time of the interval for which the anomaly data in the table is being aggregated.\nAnomalies in the table are commonly aggregated by day, hour, or at the bucket span of the job." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -362,7 +380,9 @@ "type": "Object", "tags": [], "label": "source", - "description": [], + "description": [ + "\nThe source anomaly record document, containing the full source anomaly record fields." + ], "signature": [ "AnomalyRecordDoc" ], @@ -375,7 +395,9 @@ "type": "string", "tags": [], "label": "rowId", - "description": [], + "description": [ + "\nUnique identifier for the table row." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -385,7 +407,9 @@ "type": "string", "tags": [], "label": "jobId", - "description": [], + "description": [ + "\nIdentifier for the anomaly detection job." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -395,7 +419,9 @@ "type": "number", "tags": [], "label": "detectorIndex", - "description": [], + "description": [ + "\nA unique identifier for the detector.\nThis identifier is based on the order of the detectors in the analysis configuration, starting at zero." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -405,7 +431,9 @@ "type": "number", "tags": [], "label": "severity", - "description": [], + "description": [ + "\nSeverity of the anomaly displaying the anomaly record_score, a normalized score between 0-100,\nwhich is based on the probability of the anomalousness of this record." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -415,7 +443,9 @@ "type": "string", "tags": [], "label": "entityName", - "description": [], + "description": [ + "\nThe entity name of the anomaly, looking first for a by_field, then over_field,\nthen partition_field, returning undefined if none of these fields are present." + ], "signature": [ "string | undefined" ], @@ -428,7 +458,9 @@ "type": "Any", "tags": [], "label": "entityValue", - "description": [], + "description": [ + "\nThe value of the entity field." + ], "signature": [ "any" ], @@ -441,7 +473,9 @@ "type": "Array", "tags": [], "label": "influencers", - "description": [], + "description": [ + "\nIf influencers was specified in the detector configuration, this array contains influencers\nthat contributed to or were to blame for an anomaly." + ], "signature": [ "{ [key: string]: any; }[] | undefined" ], @@ -454,7 +488,9 @@ "type": "Array", "tags": [], "label": "actual", - "description": [], + "description": [ + "\nThe actual value for the anomaly." + ], "signature": [ "number[] | undefined" ], @@ -467,7 +503,9 @@ "type": "Any", "tags": [], "label": "actualSort", - "description": [], + "description": [ + "\nProperty used by the table to sort anomalies by their actual value,\nwhich is a single numeric value rather than the underlying arrays." + ], "signature": [ "any" ], @@ -480,7 +518,9 @@ "type": "Array", "tags": [], "label": "typical", - "description": [], + "description": [ + "\nThe typical value for the anomaly." + ], "signature": [ "number[] | undefined" ], @@ -493,7 +533,9 @@ "type": "Any", "tags": [], "label": "typicalSort", - "description": [], + "description": [ + "\nProperty used by the table to sort anomalies by their typical value,\nwhich is a single numeric value rather than the underlying arrays." + ], "signature": [ "any" ], @@ -506,7 +548,9 @@ "type": "number", "tags": [], "label": "metricDescriptionSort", - "description": [], + "description": [ + "\nProperty used by the table to sort anomalies by the description of how the\nactual value compares to the typical value." + ], "signature": [ "number | undefined" ], @@ -519,7 +563,9 @@ "type": "Array", "tags": [], "label": "customUrls", - "description": [], + "description": [ + "\nList of custom URL drilldowns from the table row to other pages such as\nDiscover, Dashboard or other web pages." + ], "signature": [ "KibanaUrlConfig", "[] | undefined" @@ -533,7 +579,9 @@ "type": "CompoundType", "tags": [], "label": "isTimeSeriesViewRecord", - "description": [], + "description": [ + "\nReturns true if the anomaly record represented by the table row is for a time series\nwhich can be plotted by the ML UI in an anomaly chart." + ], "signature": [ "boolean | undefined" ], @@ -609,7 +657,9 @@ "type": "Interface", "tags": [], "label": "Influencer", - "description": [], + "description": [ + "\nInfluencers are the entities that have contributed to, or are to blame for, the anomalies.\nInfluencer results are available only if an influencer_field_name is specified in the job configuration." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false, "children": [ @@ -619,7 +669,9 @@ "type": "string", "tags": [], "label": "influencer_field_name", - "description": [], + "description": [ + "\nThe field name of the influencer." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -629,7 +681,9 @@ "type": "Array", "tags": [], "label": "influencer_field_values", - "description": [], + "description": [ + "\nThe entities that influenced, contributed to, or were to blame for the anomaly." + ], "signature": [ "string[]" ], @@ -794,7 +848,9 @@ "type": "Interface", "tags": [], "label": "MlSummaryJob", - "description": [], + "description": [ + "\nA summary of an anomaly detection job." + ], "path": "x-pack/plugins/ml/common/types/anomaly_detection_jobs/summary_job.ts", "deprecated": false, "children": [ @@ -804,7 +860,9 @@ "type": "string", "tags": [], "label": "id", - "description": [], + "description": [ + "\nThe identifier for the anomaly detection job." + ], "path": "x-pack/plugins/ml/common/types/anomaly_detection_jobs/summary_job.ts", "deprecated": false }, @@ -814,7 +872,9 @@ "type": "string", "tags": [], "label": "description", - "description": [], + "description": [ + "\nA description of the job." + ], "path": "x-pack/plugins/ml/common/types/anomaly_detection_jobs/summary_job.ts", "deprecated": false }, @@ -824,7 +884,9 @@ "type": "Array", "tags": [], "label": "groups", - "description": [], + "description": [ + "\nA list of job groups. A job can belong to no groups, one or many." + ], "signature": [ "string[]" ], @@ -837,7 +899,9 @@ "type": "number", "tags": [], "label": "processed_record_count", - "description": [], + "description": [ + "\nThe number of input documents that have been processed by the anomaly detection job.\nThis value includes documents with missing fields, since they are nonetheless analyzed." + ], "signature": [ "number | undefined" ], @@ -850,7 +914,9 @@ "type": "string", "tags": [], "label": "memory_status", - "description": [], + "description": [ + "\nThe status of the mathematical models, which can take the values ok, soft_limit or hard_limit." + ], "signature": [ "string | undefined" ], @@ -863,7 +929,9 @@ "type": "string", "tags": [], "label": "jobState", - "description": [], + "description": [ + "\nThe status of the job." + ], "path": "x-pack/plugins/ml/common/types/anomaly_detection_jobs/summary_job.ts", "deprecated": false }, @@ -873,7 +941,9 @@ "type": "Array", "tags": [], "label": "datafeedIndices", - "description": [], + "description": [ + "\nAn array of index names used by the datafeed. Wildcards are supported." + ], "signature": [ "string[]" ], @@ -886,7 +956,9 @@ "type": "boolean", "tags": [], "label": "hasDatafeed", - "description": [], + "description": [ + "\nFlag indicating whether a datafeed exists for the job." + ], "path": "x-pack/plugins/ml/common/types/anomaly_detection_jobs/summary_job.ts", "deprecated": false }, @@ -896,7 +968,9 @@ "type": "string", "tags": [], "label": "datafeedId", - "description": [], + "description": [ + "\nThe identifier for the datafeed." + ], "path": "x-pack/plugins/ml/common/types/anomaly_detection_jobs/summary_job.ts", "deprecated": false }, @@ -906,7 +980,9 @@ "type": "string", "tags": [], "label": "datafeedState", - "description": [], + "description": [ + "\nThe status of the datafeed." + ], "path": "x-pack/plugins/ml/common/types/anomaly_detection_jobs/summary_job.ts", "deprecated": false }, @@ -916,7 +992,9 @@ "type": "number", "tags": [], "label": "latestTimestampMs", - "description": [], + "description": [ + "\nThe timestamp of the latest chronologically input document." + ], "signature": [ "number | undefined" ], @@ -929,7 +1007,9 @@ "type": "number", "tags": [], "label": "earliestTimestampMs", - "description": [], + "description": [ + "\nThe timestamp of the earliest chronologically input document." + ], "signature": [ "number | undefined" ], @@ -942,7 +1022,9 @@ "type": "number", "tags": [], "label": "latestResultsTimestampMs", - "description": [], + "description": [ + "\nThe latest of the timestamp of the latest chronologically input document or the latest bucket that was processed." + ], "signature": [ "number | undefined" ], @@ -955,7 +1037,9 @@ "type": "Object", "tags": [], "label": "fullJob", - "description": [], + "description": [ + "\nUsed in older implementations of the job config, where the datafeed was placed inside the job for convenience.\nThis will be populated if the job's id has been passed to the /api/ml/jobs/jobs_summary endpoint." + ], "signature": [ "CombinedJob", " | undefined" @@ -969,7 +1053,9 @@ "type": "string", "tags": [], "label": "nodeName", - "description": [], + "description": [ + "\nThe name of the node that runs the job." + ], "signature": [ "string | undefined" ], @@ -982,7 +1068,9 @@ "type": "Object", "tags": [], "label": "auditMessage", - "description": [], + "description": [ + "\nAudit message for the job." + ], "signature": [ "Partial<", "AuditMessage", @@ -997,7 +1085,9 @@ "type": "boolean", "tags": [], "label": "isSingleMetricViewerJob", - "description": [], + "description": [ + "\nFlag indicating whether results of the job can be viewed in the Single Metric Viewer." + ], "path": "x-pack/plugins/ml/common/types/anomaly_detection_jobs/summary_job.ts", "deprecated": false }, @@ -1007,7 +1097,9 @@ "type": "string", "tags": [], "label": "isNotSingleMetricViewerJobMessage", - "description": [], + "description": [ + "\nFor jobs which cannot be viewed in the Single Metric Viewer, a message indicating the reason why\nresults for the job cannot be viewed in the Single Metric Viewer." + ], "signature": [ "string | undefined" ], @@ -1020,7 +1112,9 @@ "type": "Object", "tags": [], "label": "blocked", - "description": [], + "description": [ + "\nWhen present, it explains that a task is currently running on the job, which is stopping\nany other actions from being performed on the job." + ], "signature": [ "MlJobBlocked", " | undefined" @@ -1034,7 +1128,9 @@ "type": "number", "tags": [], "label": "latestTimestampSortValue", - "description": [], + "description": [ + "\nValue of the latest timestamp for the job used for sorting." + ], "signature": [ "number | undefined" ], @@ -1047,7 +1143,9 @@ "type": "number", "tags": [], "label": "earliestStartTimestampMs", - "description": [], + "description": [ + "\nThe earlist of the timestamp of the earliest chronologically input document or the earliest bucket that was processed." + ], "signature": [ "number | undefined" ], @@ -1060,7 +1158,9 @@ "type": "boolean", "tags": [], "label": "awaitingNodeAssignment", - "description": [], + "description": [ + "\nIndicates whether the job is currently awaiting assignment to a node before opening." + ], "path": "x-pack/plugins/ml/common/types/anomaly_detection_jobs/summary_job.ts", "deprecated": false }, @@ -1070,7 +1170,9 @@ "type": "Array", "tags": [], "label": "alertingRules", - "description": [], + "description": [ + "\nList of anomaly detection alerting rules configured for the job." + ], "signature": [ "MlAnomalyDetectionAlertRule", "[] | undefined" @@ -1084,7 +1186,9 @@ "type": "Object", "tags": [], "label": "jobTags", - "description": [], + "description": [ + "\nList of tags that have been added to the job." + ], "signature": [ "{ [x: string]: string; }" ], @@ -1097,7 +1201,9 @@ "type": "number", "tags": [], "label": "bucketSpanSeconds", - "description": [], + "description": [ + "\nThe size of the interval that the analysis is aggregated into, typically between 5m and 1h." + ], "path": "x-pack/plugins/ml/common/types/anomaly_detection_jobs/summary_job.ts", "deprecated": false }, @@ -1107,7 +1213,9 @@ "type": "Any", "tags": [], "label": "customSettings", - "description": [], + "description": [ + "\nAdvanced configuration option. Contains custom meta data about the job. For example, it can contain custom URL information." + ], "signature": [ "any" ], @@ -1196,7 +1304,9 @@ "type": "Enum", "tags": [], "label": "ANOMALY_SEVERITY", - "description": [], + "description": [ + "\nLabels displayed in the ML UI to indicate the severity of the anomaly according\nto the normalized anomaly score." + ], "path": "x-pack/plugins/ml/common/constants/anomalies.ts", "deprecated": false, "initialIsOpen": false @@ -1685,7 +1795,9 @@ "type": "Interface", "tags": [], "label": "AnomaliesTableRecord", - "description": [], + "description": [ + "\nAnomaly table record, representing the fields shown in the ML UI anomalies table." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false, "children": [ @@ -1695,7 +1807,9 @@ "type": "number", "tags": [], "label": "time", - "description": [], + "description": [ + "\nThe start time of the interval for which the anomaly data in the table is being aggregated.\nAnomalies in the table are commonly aggregated by day, hour, or at the bucket span of the job." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -1705,7 +1819,9 @@ "type": "Object", "tags": [], "label": "source", - "description": [], + "description": [ + "\nThe source anomaly record document, containing the full source anomaly record fields." + ], "signature": [ "AnomalyRecordDoc" ], @@ -1718,7 +1834,9 @@ "type": "string", "tags": [], "label": "rowId", - "description": [], + "description": [ + "\nUnique identifier for the table row." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -1728,7 +1846,9 @@ "type": "string", "tags": [], "label": "jobId", - "description": [], + "description": [ + "\nIdentifier for the anomaly detection job." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -1738,7 +1858,9 @@ "type": "number", "tags": [], "label": "detectorIndex", - "description": [], + "description": [ + "\nA unique identifier for the detector.\nThis identifier is based on the order of the detectors in the analysis configuration, starting at zero." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -1748,7 +1870,9 @@ "type": "number", "tags": [], "label": "severity", - "description": [], + "description": [ + "\nSeverity of the anomaly displaying the anomaly record_score, a normalized score between 0-100,\nwhich is based on the probability of the anomalousness of this record." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -1758,7 +1882,9 @@ "type": "string", "tags": [], "label": "entityName", - "description": [], + "description": [ + "\nThe entity name of the anomaly, looking first for a by_field, then over_field,\nthen partition_field, returning undefined if none of these fields are present." + ], "signature": [ "string | undefined" ], @@ -1771,7 +1897,9 @@ "type": "Any", "tags": [], "label": "entityValue", - "description": [], + "description": [ + "\nThe value of the entity field." + ], "signature": [ "any" ], @@ -1784,7 +1912,9 @@ "type": "Array", "tags": [], "label": "influencers", - "description": [], + "description": [ + "\nIf influencers was specified in the detector configuration, this array contains influencers\nthat contributed to or were to blame for an anomaly." + ], "signature": [ "{ [key: string]: any; }[] | undefined" ], @@ -1797,7 +1927,9 @@ "type": "Array", "tags": [], "label": "actual", - "description": [], + "description": [ + "\nThe actual value for the anomaly." + ], "signature": [ "number[] | undefined" ], @@ -1810,7 +1942,9 @@ "type": "Any", "tags": [], "label": "actualSort", - "description": [], + "description": [ + "\nProperty used by the table to sort anomalies by their actual value,\nwhich is a single numeric value rather than the underlying arrays." + ], "signature": [ "any" ], @@ -1823,7 +1957,9 @@ "type": "Array", "tags": [], "label": "typical", - "description": [], + "description": [ + "\nThe typical value for the anomaly." + ], "signature": [ "number[] | undefined" ], @@ -1836,7 +1972,9 @@ "type": "Any", "tags": [], "label": "typicalSort", - "description": [], + "description": [ + "\nProperty used by the table to sort anomalies by their typical value,\nwhich is a single numeric value rather than the underlying arrays." + ], "signature": [ "any" ], @@ -1849,7 +1987,9 @@ "type": "number", "tags": [], "label": "metricDescriptionSort", - "description": [], + "description": [ + "\nProperty used by the table to sort anomalies by the description of how the\nactual value compares to the typical value." + ], "signature": [ "number | undefined" ], @@ -1862,7 +2002,9 @@ "type": "Array", "tags": [], "label": "customUrls", - "description": [], + "description": [ + "\nList of custom URL drilldowns from the table row to other pages such as\nDiscover, Dashboard or other web pages." + ], "signature": [ "KibanaUrlConfig", "[] | undefined" @@ -1876,7 +2018,9 @@ "type": "CompoundType", "tags": [], "label": "isTimeSeriesViewRecord", - "description": [], + "description": [ + "\nReturns true if the anomaly record represented by the table row is for a time series\nwhich can be plotted by the ML UI in an anomaly chart." + ], "signature": [ "boolean | undefined" ], @@ -1892,7 +2036,9 @@ "type": "Interface", "tags": [], "label": "AnomalyRecordDoc", - "description": [], + "description": [ + "\nAnomaly record document. Records contain the detailed analytical results.\nThey describe the anomalous activity that has been identified in the input data based on the detector configuration." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false, "children": [ @@ -1902,7 +2048,9 @@ "type": "IndexSignature", "tags": [], "label": "[key: string]: any", - "description": [], + "description": [ + "\nIndex signature to cover dynamic attributes added to the record depending on the fields being analyzed.\nFor example, if the job is analyzing hostname as a by field, then a field hostname is added to the result document." + ], "signature": [ "[key: string]: any" ], @@ -1915,7 +2063,9 @@ "type": "string", "tags": [], "label": "job_id", - "description": [], + "description": [ + "\nThe identifier for the anomaly detection job." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -1925,7 +2075,9 @@ "type": "string", "tags": [], "label": "result_type", - "description": [], + "description": [ + "\nThe type of the result document, which is 'record' for record level results." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -1935,7 +2087,9 @@ "type": "number", "tags": [], "label": "probability", - "description": [], + "description": [ + "\nThe probability of the individual anomaly occurring, in the range 0 to 1.\nThis value can be held to a high precision of over 300 decimal places,\nso the record_score is provided as a human-readable and friendly interpretation of this." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -1945,7 +2099,9 @@ "type": "number", "tags": [], "label": "record_score", - "description": [], + "description": [ + "\nA normalized score between 0-100, which is based on the probability of the anomalousness of this record.\nUnlike initial_record_score, this value will be updated by a re-normalization process as new data is analyzed." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -1955,7 +2111,9 @@ "type": "number", "tags": [], "label": "initial_record_score", - "description": [], + "description": [ + "\nA normalized score between 0-100, which is based on the probability of the anomalousness of this record.\nThis is the initial value that was calculated at the time the bucket was processed." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -1965,7 +2123,9 @@ "type": "number", "tags": [], "label": "bucket_span", - "description": [], + "description": [ + "\nThe length of the bucket in seconds. This value matches the bucket_span that is specified in the job." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -1975,7 +2135,9 @@ "type": "number", "tags": [], "label": "detector_index", - "description": [], + "description": [ + "\nA unique identifier for the detector. This identifier is based on the order of the detectors\nin the analysis configuration, starting at zero." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -1985,7 +2147,9 @@ "type": "boolean", "tags": [], "label": "is_interim", - "description": [], + "description": [ + "\nIf true, this is an interim result. In other words, the results are calculated based on partial input data." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -1995,7 +2159,9 @@ "type": "number", "tags": [], "label": "timestamp", - "description": [], + "description": [ + "\nThe start time of the bucket for which these results were calculated." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -2005,7 +2171,9 @@ "type": "string", "tags": [], "label": "partition_field_name", - "description": [], + "description": [ + "\nThe field used to segment the analysis.\nWhen you use this property, you have completely independent baselines for each value of this field." + ], "signature": [ "string | undefined" ], @@ -2018,7 +2186,9 @@ "type": "CompoundType", "tags": [], "label": "partition_field_value", - "description": [], + "description": [ + "\nThe value of the partition field." + ], "signature": [ "string | number | undefined" ], @@ -2031,7 +2201,9 @@ "type": "string", "tags": [], "label": "function", - "description": [], + "description": [ + "\nThe function in which the anomaly occurs, as specified in the detector configuration. For example, max." + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -2041,7 +2213,24 @@ "type": "string", "tags": [], "label": "function_description", - "description": [], + "description": [ + "\nThe description of the function in which the anomaly occurs, as specified in the detector configuration." + ], + "path": "x-pack/plugins/ml/common/types/anomalies.ts", + "deprecated": false + }, + { + "parentPluginId": "ml", + "id": "def-server.AnomalyRecordDoc.field_name", + "type": "string", + "tags": [], + "label": "field_name", + "description": [ + "\nCertain functions require a field to operate on, for example, sum().\nFor those functions, this value is the name of the field to be analyzed." + ], + "signature": [ + "string | undefined" + ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false }, @@ -2051,7 +2240,9 @@ "type": "Array", "tags": [], "label": "typical", - "description": [], + "description": [ + "\nThe typical value for the bucket, according to analytical modeling." + ], "signature": [ "number[] | undefined" ], @@ -2064,7 +2255,9 @@ "type": "Array", "tags": [], "label": "actual", - "description": [], + "description": [ + "\nThe actual value for the bucket." + ], "signature": [ "number[] | undefined" ], @@ -2077,7 +2270,9 @@ "type": "Array", "tags": [], "label": "influencers", - "description": [], + "description": [ + "\nIf influencers was specified in the detector configuration, this array contains influencers\nthat contributed to or were to blame for an anomaly." + ], "signature": [ "Influencer", "[] | undefined" @@ -2091,20 +2286,9 @@ "type": "string", "tags": [], "label": "by_field_name", - "description": [], - "signature": [ - "string | undefined" + "description": [ + "\nThe field used to split the data. In particular, this property is used for analyzing the splits\nwith respect to their own history. It is used for finding unusual values in the context of the split." ], - "path": "x-pack/plugins/ml/common/types/anomalies.ts", - "deprecated": false - }, - { - "parentPluginId": "ml", - "id": "def-server.AnomalyRecordDoc.field_name", - "type": "string", - "tags": [], - "label": "field_name", - "description": [], "signature": [ "string | undefined" ], @@ -2117,22 +2301,11 @@ "type": "string", "tags": [], "label": "by_field_value", - "description": [], - "signature": [ - "string | undefined" + "description": [ + "\nThe value of the by field." ], - "path": "x-pack/plugins/ml/common/types/anomalies.ts", - "deprecated": false - }, - { - "parentPluginId": "ml", - "id": "def-server.AnomalyRecordDoc.multi_bucket_impact", - "type": "number", - "tags": [], - "label": "multi_bucket_impact", - "description": [], "signature": [ - "number | undefined" + "string | undefined" ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false @@ -2143,7 +2316,9 @@ "type": "string", "tags": [], "label": "over_field_name", - "description": [], + "description": [ + "\nThe field used to split the data. In particular, this property is used for analyzing\nthe splits with respect to the history of all splits.\nIt is used for finding unusual values in the population of all splits." + ], "signature": [ "string | undefined" ], @@ -2156,7 +2331,9 @@ "type": "string", "tags": [], "label": "over_field_value", - "description": [], + "description": [ + "\nThe value of the over field." + ], "signature": [ "string | undefined" ], @@ -2169,12 +2346,29 @@ "type": "Array", "tags": [], "label": "causes", - "description": [], + "description": [ + "\nFor population analysis, this property contains an array of anomaly records that are the causes\nfor the anomaly that has been identified for the over field. If no over fields exist, this field is not present.\nThis sub-resource contains the most anomalous records for the over_field_name.\nThe causes resource contains similar elements to the record resource.\nProbability and scores are not applicable to causes." + ], "signature": [ "{ function: string; function_description: string; probability: number; actual: number[]; typical: number[]; field_name?: string | undefined; over_field_name?: string | undefined; over_field_value?: string | undefined; by_field_name?: string | undefined; by_field_value?: string | undefined; partition_field_name?: string | undefined; partition_field_value?: string | number | undefined; }[] | undefined" ], "path": "x-pack/plugins/ml/common/types/anomalies.ts", "deprecated": false + }, + { + "parentPluginId": "ml", + "id": "def-server.AnomalyRecordDoc.multi_bucket_impact", + "type": "number", + "tags": [], + "label": "multi_bucket_impact", + "description": [ + "\nAn indication of how strongly an anomaly is multi bucket or single bucket.\nThe value is on a scale of -5.0 to +5.0 where -5.0 means the anomaly is\npurely single bucket and +5.0 means the anomaly is purely multi bucket." + ], + "signature": [ + "number | undefined" + ], + "path": "x-pack/plugins/ml/common/types/anomalies.ts", + "deprecated": false } ], "initialIsOpen": false @@ -2188,7 +2382,9 @@ "type": "Type", "tags": [], "label": "AnomalyResultType", - "description": [], + "description": [ + "\nThe type of the anomaly result, such as bucket, influencer or record." + ], "signature": [ "\"bucket\" | \"record\" | \"influencer\"" ], @@ -2376,7 +2572,9 @@ "type": "Function", "tags": [], "label": "getSeverityColor", - "description": [], + "description": [ + "\nReturns a severity RGB color (one of critical, major, minor, warning, low or blank)\nfor the supplied normalized anomaly score (a value between 0 and 100)." + ], "signature": [ "(normalizedScore: number) => string" ], @@ -2389,7 +2587,9 @@ "type": "number", "tags": [], "label": "normalizedScore", - "description": [], + "description": [ + "- A normalized score between 0-100, which is based on the probability of the anomalousness of this record" + ], "signature": [ "number" ], @@ -2407,7 +2607,9 @@ "type": "Function", "tags": [], "label": "getSeverityType", - "description": [], + "description": [ + "\nReturns a severity type (indicating a critical, major, minor, warning or low severity anomaly)\nfor the supplied normalized anomaly score (a value between 0 and 100)." + ], "signature": [ "(normalizedScore: number) => ", { @@ -2427,7 +2629,9 @@ "type": "number", "tags": [], "label": "normalizedScore", - "description": [], + "description": [ + "- A normalized score between 0-100, which is based on the probability of the anomalousness of this record" + ], "signature": [ "number" ], @@ -2588,7 +2792,9 @@ "type": "Enum", "tags": [], "label": "ANOMALY_SEVERITY", - "description": [], + "description": [ + "\nLabels displayed in the ML UI to indicate the severity of the anomaly according\nto the normalized anomaly score." + ], "path": "x-pack/plugins/ml/common/constants/anomalies.ts", "deprecated": false, "initialIsOpen": false @@ -2599,7 +2805,9 @@ "type": "Enum", "tags": [], "label": "ANOMALY_THRESHOLD", - "description": [], + "description": [ + "\nAnomaly score numeric thresholds to indicate the severity of the anomaly." + ], "path": "x-pack/plugins/ml/common/constants/anomalies.ts", "deprecated": false, "initialIsOpen": false @@ -2610,7 +2818,9 @@ "type": "Enum", "tags": [], "label": "DATAFEED_STATE", - "description": [], + "description": [ + "\nThe status of the datafeed." + ], "path": "x-pack/plugins/ml/common/constants/states.ts", "deprecated": false, "initialIsOpen": false @@ -2621,7 +2831,9 @@ "type": "Enum", "tags": [], "label": "JOB_STATE", - "description": [], + "description": [ + "\nThe status of the anomaly detection job." + ], "path": "x-pack/plugins/ml/common/constants/states.ts", "deprecated": false, "initialIsOpen": false @@ -2710,7 +2922,9 @@ "type": "Object", "tags": [], "label": "SEVERITY_COLORS", - "description": [], + "description": [ + "\nRGB hex codes used to indicate the severity of an anomaly according to its anomaly score." + ], "path": "x-pack/plugins/ml/common/constants/anomalies.ts", "deprecated": false, "children": [ @@ -2720,7 +2934,9 @@ "type": "string", "tags": [], "label": "CRITICAL", - "description": [], + "description": [ + "/**\n * Color used in the UI to indicate a critical anomaly, with a score greater than or equal to 75.\n */" + ], "path": "x-pack/plugins/ml/common/constants/anomalies.ts", "deprecated": false }, @@ -2730,7 +2946,9 @@ "type": "string", "tags": [], "label": "MAJOR", - "description": [], + "description": [ + "/**\n * Color used in the UI to indicate a major anomaly, with a score greater than or equal to 50 and less than 75 .\n */" + ], "path": "x-pack/plugins/ml/common/constants/anomalies.ts", "deprecated": false }, @@ -2740,7 +2958,9 @@ "type": "string", "tags": [], "label": "MINOR", - "description": [], + "description": [ + "/**\n * Color used in the UI to indicate a minor anomaly, with a score greater than or equal to 25 and less than 50.\n */" + ], "path": "x-pack/plugins/ml/common/constants/anomalies.ts", "deprecated": false }, @@ -2750,7 +2970,9 @@ "type": "string", "tags": [], "label": "WARNING", - "description": [], + "description": [ + "/**\n * Color used in the UI to indicate a warning anomaly, with a score greater than or equal to 3 and less than 25.\n * Note in some parts of the UI, warning severity is used when the score is greater than or equal to 0.\n */" + ], "path": "x-pack/plugins/ml/common/constants/anomalies.ts", "deprecated": false }, @@ -2760,7 +2982,9 @@ "type": "string", "tags": [], "label": "LOW", - "description": [], + "description": [ + "/**\n * Color used in some parts of the UI to indicate a low severity anomaly, with a score greater than or equal to 0 and less than 3.\n */" + ], "path": "x-pack/plugins/ml/common/constants/anomalies.ts", "deprecated": false }, @@ -2770,7 +2994,9 @@ "type": "string", "tags": [], "label": "BLANK", - "description": [], + "description": [ + "/**\n * Color used in the UI to indicate an anomaly for which the score is unknown.\n */" + ], "path": "x-pack/plugins/ml/common/constants/anomalies.ts", "deprecated": false } diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 0bf283918e755..2945f2c6e8937 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github summary: API docs for the ml plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,7 +18,7 @@ Contact [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) for q | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 196 | 8 | 192 | 30 | +| 196 | 8 | 79 | 30 | ## Client diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index a96ab53a3426f..bfc586c0dcaac 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github summary: API docs for the monitoring plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index 720848946de31..6ad1a5dd9e901 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github summary: API docs for the navigation plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index 003f17186d897..2388c2d65a49b 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github summary: API docs for the newsfeed plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/observability.devdocs.json b/api_docs/observability.devdocs.json index 231e72cb1a2bd..1f9b7f7b264ec 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -99,7 +99,7 @@ "section": "def-public.AllSeries", "text": "AllSeries" }, - "; }, baseHref: string) => string" + "; }, baseHref: string, appId: string) => string" ], "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts", "deprecated": false, @@ -162,6 +162,20 @@ "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts", "deprecated": false, "isRequired": true + }, + { + "parentPluginId": "observability", + "id": "def-public.createExploratoryViewUrl.$3", + "type": "string", + "tags": [], + "label": "appId", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts", + "deprecated": false, + "isRequired": true } ], "returnComment": [], @@ -847,75 +861,11 @@ "label": "useChartTheme", "description": [], "signature": [ - "() => { chartMargins: { left: number; right: number; top: number; bottom: number; }; background: { color: string; }; lineSeriesStyle: { point: { visible: boolean; }; line?: ", - "RecursivePartial", - "<", - "LineStyle", - "> | undefined; fit?: ", - "RecursivePartial", - "<{ line: ", - "LineFitStyle", - "; }> | undefined; }; areaSeriesStyle: { point: { visible: boolean; }; area?: ", - "RecursivePartial", - "<", - "AreaStyle", - "> | undefined; line?: ", - "RecursivePartial", - "<", - "LineStyle", - "> | undefined; fit?: ", - "RecursivePartial", - "<{ line: ", - "LineFitStyle", - "; area: ", - "AreaFitStyle", - "; }> | undefined; }; chartPaddings?: ", - "RecursivePartial", - "<", - "PerSideDistance", - "> | undefined; barSeriesStyle?: ", - "RecursivePartial", - "<", - "BarSeriesStyle", - "> | undefined; bubbleSeriesStyle?: ", - "RecursivePartial", - "<", - "BubbleSeriesStyle", - "> | undefined; arcSeriesStyle?: ", - "RecursivePartial", - "<", - "ArcSeriesStyle", - "> | undefined; sharedStyle?: ", - "RecursivePartial", - "<", - "SharedGeometryStateStyle", - "> | undefined; axes?: ", - "RecursivePartial", - "<", - "AxisStyle", - "> | undefined; scales?: ", - "RecursivePartial", - "<", - "ScalesConfig", - "> | undefined; colors?: ", - "RecursivePartial", - "<", - "ColorConfig", - "> | undefined; legend?: ", - "RecursivePartial", - "<", - "LegendStyle", - "> | undefined; crosshair?: ", - "RecursivePartial", - "<", - "CrosshairStyle", - "> | undefined; markSizeRatio?: ", - "RecursivePartial", - "; goal?: ", + "() => ", "RecursivePartial", "<", - "GoalStyles", - "> | undefined; }" + "Theme", + ">[]" ], "path": "x-pack/plugins/observability/public/hooks/use_chart_theme.tsx", "deprecated": false, @@ -1779,6 +1729,34 @@ ], "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/embeddable.tsx", "deprecated": false + }, + { + "parentPluginId": "observability", + "id": "def-public.ExploratoryEmbeddableProps.withActions", + "type": "CompoundType", + "tags": [], + "label": "withActions", + "description": [], + "signature": [ + "boolean | ", + "ActionTypes", + "[] | undefined" + ], + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/embeddable.tsx", + "deprecated": false + }, + { + "parentPluginId": "observability", + "id": "def-public.ExploratoryEmbeddableProps.appId", + "type": "CompoundType", + "tags": [], + "label": "appId", + "description": [], + "signature": [ + "\"security\" | \"observability\" | undefined" + ], + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/embeddable.tsx", + "deprecated": false } ], "initialIsOpen": false @@ -4286,7 +4264,7 @@ "section": "def-public.AllSeries", "text": "AllSeries" }, - "; }, baseHref?: string) => string; ExploratoryViewEmbeddable: (props: ", + "; }, baseHref?: string, appId?: string) => string; ExploratoryViewEmbeddable: (props: ", { "pluginId": "observability", "scope": "public", diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 1b9dc72f0c156..d0de12835f82c 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github summary: API docs for the observability plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,7 +18,7 @@ Contact [Observability UI](https://github.com/orgs/elastic/teams/observability-u | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 319 | 1 | 316 | 25 | +| 322 | 1 | 319 | 26 | ## Client diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 71a3c3ad64f55..412994ea44b61 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github summary: API docs for the osquery plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 2477db7d36fa7..482f23e164bc5 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -3,7 +3,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory summary: Directory of public APIs available through plugins or packages. -date: 2021-09-22 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -12,13 +12,13 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 210 | 166 | 31 | +| 210 | 166 | 32 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 23213 | 169 | 17753 | 1709 | +| 23237 | 166 | 17652 | 1690 | ## Plugin Directory @@ -29,11 +29,11 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Kibana Alerting](https://github.com/orgs/elastic/teams/kibana-alerting-services) | - | 283 | 0 | 275 | 19 | | | [APM UI](https://github.com/orgs/elastic/teams/apm-ui) | The user interface for Elastic APM | 40 | 0 | 40 | 49 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 9 | 0 | 9 | 0 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Considering using bfetch capabilities when fetching large amounts of data. This services supports batching HTTP requests and streaming responses back. | 76 | 1 | 67 | 2 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Considering using bfetch capabilities when fetching large amounts of data. This services supports batching HTTP requests and streaming responses back. | 78 | 1 | 69 | 2 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds Canvas application to Kibana | 9 | 0 | 8 | 3 | | | [ResponseOps](https://github.com/orgs/elastic/teams/response-ops) | The Case management system in Kibana | 83 | 0 | 57 | 23 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | - | 319 | 2 | 286 | 4 | -| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 22 | 0 | 22 | 0 | +| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 28 | 0 | 23 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 13 | 0 | 13 | 1 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Controls Plugin contains embeddable components intended to create a simple query interface for end users, and a powerful editing suite that allows dashboard authors to build controls | 118 | 0 | 117 | 3 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2353 | 15 | 968 | 32 | @@ -41,7 +41,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Fleet](https://github.com/orgs/elastic/teams/fleet) | Add custom data integrations so they can be displayed in the Fleet integrations app | 96 | 0 | 77 | 1 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds the Dashboard app to Kibana | 155 | 0 | 142 | 13 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 51 | 0 | 50 | 0 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 3364 | 39 | 2767 | 26 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 3368 | 39 | 2771 | 26 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Enhanced data plugin. (See src/plugins/data.) Enhances the main data plugin with a search session management UI. Includes a reusable search session indicator component to use in other applications. Exposes routes for managing search sessions. Includes a service that monitors, updates, and cleans up search session saved objects. | 16 | 0 | 16 | 2 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | This plugin provides the ability to create data views via a modal flyout from any kibana app | 13 | 0 | 7 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Reusable data view field editor across Kibana | 42 | 0 | 37 | 3 | @@ -80,7 +80,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | grokdebugger | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 133 | 0 | 97 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 4 | 0 | 4 | 0 | -| | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 169 | 3 | 164 | 3 | +| | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 169 | 0 | 164 | 3 | | | [Logs and Metrics UI](https://github.com/orgs/elastic/teams/logs-metrics-ui) | This plugin visualizes data from Filebeat and Metricbeat, and integrates with other Observability solutions | 28 | 0 | 25 | 3 | | ingestPipelines | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | inputControlVis | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds Input Control visualization to Kibana | 0 | 0 | 0 | 0 | @@ -90,21 +90,21 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 236 | 0 | 201 | 5 | | kibanaUsageCollection | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 0 | 0 | 0 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 615 | 3 | 420 | 9 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 274 | 0 | 252 | 31 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 276 | 0 | 254 | 31 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 8 | 0 | 8 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 3 | 0 | 3 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 117 | 0 | 42 | 10 | -| | [Security detections response](https://github.com/orgs/elastic/teams/security-detections-response) | - | 178 | 0 | 155 | 48 | +| | [Security detections response](https://github.com/orgs/elastic/teams/security-detections-response) | - | 185 | 0 | 155 | 43 | | logstash | [Logstash](https://github.com/orgs/elastic/teams/logstash) | - | 0 | 0 | 0 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | - | 41 | 0 | 41 | 6 | | | [GIS](https://github.com/orgs/elastic/teams/kibana-gis) | - | 215 | 0 | 214 | 27 | | | [GIS](https://github.com/orgs/elastic/teams/kibana-gis) | - | 67 | 0 | 67 | 0 | | | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 4 | 0 | 4 | 1 | -| | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the machine learning features provided by Elastic. | 196 | 8 | 192 | 30 | +| | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the machine learning features provided by Elastic. | 196 | 8 | 79 | 30 | | | [Stack Monitoring](https://github.com/orgs/elastic/teams/stack-monitoring-ui) | - | 10 | 0 | 10 | 2 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 31 | 0 | 31 | 2 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 17 | 0 | 17 | 0 | -| | [Observability UI](https://github.com/orgs/elastic/teams/observability-ui) | - | 319 | 1 | 316 | 25 | +| | [Observability UI](https://github.com/orgs/elastic/teams/observability-ui) | - | 322 | 1 | 319 | 26 | | | [Security asset management](https://github.com/orgs/elastic/teams/security-asset-management) | - | 10 | 0 | 10 | 0 | | painlessLab | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas). | 228 | 2 | 177 | 11 | @@ -179,7 +179,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Owner missing] | - | 211 | 1 | 159 | 11 | | | [Owner missing] | - | 20 | 0 | 16 | 0 | | | [Owner missing] | - | 51 | 0 | 48 | 0 | -| | [Owner missing] | - | 35 | 3 | 35 | 1 | +| | App Services | - | 35 | 3 | 35 | 1 | | | [Owner missing] | - | 20 | 0 | 20 | 2 | | | [Owner missing] | - | 30 | 0 | 5 | 36 | | | [Owner missing] | - | 466 | 1 | 1 | 0 | @@ -207,9 +207,9 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Owner missing] | - | 53 | 0 | 50 | 1 | | | [Owner missing] | - | 25 | 0 | 24 | 1 | | | [Owner missing] | - | 96 | 1 | 63 | 2 | -| | [Owner missing] | - | 22 | 2 | 21 | 0 | +| | Operations | - | 22 | 2 | 21 | 0 | | | [Owner missing] | - | 2 | 0 | 2 | 0 | -| | [Owner missing] | - | 221 | 5 | 195 | 10 | +| | Operations | - | 221 | 5 | 195 | 10 | | | [Owner missing] | - | 83 | 0 | 83 | 1 | | | [Owner missing] | - | 7 | 0 | 6 | 0 | | | [Owner missing] | - | 27 | 0 | 10 | 1 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 455c184064d88..6a229ee9923ad 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github summary: API docs for the presentationUtil plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 764acfed74116..887ca2f6b5e25 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github summary: API docs for the remoteClusters plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index 38a10b3ed9dd0..c37650f248c97 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github summary: API docs for the reporting plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index 2ab83d6b7c70f..c3d565e282490 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github summary: API docs for the rollup plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 0915109310ac4..1dabd0d68aece 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github summary: API docs for the ruleRegistry plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index b9adc74de4d46..bf1fcf9cad8b9 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github summary: API docs for the runtimeFields plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index 8a206d05b61e7..e26cdc437c892 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github summary: API docs for the savedObjects plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index 5d0479487ea31..f4395f56e86ba 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the savedObjectsManagement plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index de7333a2f140e..d5811b0625421 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github summary: API docs for the savedObjectsTagging plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 16b6a646e0cd8..9d4e11fe9c528 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github summary: API docs for the savedObjectsTaggingOss plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index 0a3b46a31d9ae..8bffb222c0d03 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github summary: API docs for the screenshotMode plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 5a0d3abdd9ab0..00a846192508d 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github summary: API docs for the screenshotting plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/security.devdocs.json b/api_docs/security.devdocs.json index 537377bc339e7..ccb64b30ed10a 100644 --- a/api_docs/security.devdocs.json +++ b/api_docs/security.devdocs.json @@ -1754,6 +1754,10 @@ "plugin": "actions", "path": "x-pack/plugins/actions/server/plugin.ts" }, + { + "plugin": "cloud", + "path": "x-pack/plugins/cloud/server/routes/chat.ts" + }, { "plugin": "ml", "path": "x-pack/plugins/ml/server/routes/annotations.ts" diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 02f4a118e21bd..4272662795123 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github summary: API docs for the security plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/security_solution.devdocs.json b/api_docs/security_solution.devdocs.json index 1ba7557881b9a..0b83d1c9648b7 100644 --- a/api_docs/security_solution.devdocs.json +++ b/api_docs/security_solution.devdocs.json @@ -62,7 +62,7 @@ "label": "experimentalFeatures", "description": [], "signature": [ - "{ readonly metricsEntitiesEnabled: boolean; readonly ruleRegistryEnabled: boolean; readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly uebaEnabled: boolean; readonly disableIsolationUIPendingStatuses: boolean; readonly riskyHostsEnabled: boolean; readonly securityRulesCancelEnabled: boolean; readonly pendingActionResponsesWithAck: boolean; readonly policyListEnabled: boolean; }" + "{ readonly metricsEntitiesEnabled: boolean; readonly ruleRegistryEnabled: boolean; readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly uebaEnabled: boolean; readonly disableIsolationUIPendingStatuses: boolean; readonly riskyHostsEnabled: boolean; readonly securityRulesCancelEnabled: boolean; readonly pendingActionResponsesWithAck: boolean; readonly rulesBulkEditEnabled: boolean; readonly policyListEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/public/plugin.tsx", "deprecated": false @@ -887,7 +887,7 @@ "label": "ConfigType", "description": [], "signature": [ - "Readonly<{} & { signalsIndex: string; maxRuleImportExportSize: number; maxRuleImportPayloadBytes: number; maxTimelineImportExportSize: number; maxTimelineImportPayloadBytes: number; alertMergeStrategy: \"allFields\" | \"missingFields\" | \"noFields\"; alertIgnoreFields: string[]; enableExperimental: string[]; packagerTaskInterval: string; prebuiltRulesFromFileSystem: boolean; prebuiltRulesFromSavedObjects: boolean; }> & { experimentalFeatures: Readonly<{ metricsEntitiesEnabled: boolean; ruleRegistryEnabled: boolean; tGridEnabled: boolean; tGridEventRenderedViewEnabled: boolean; excludePoliciesInFilterEnabled: boolean; uebaEnabled: boolean; disableIsolationUIPendingStatuses: boolean; riskyHostsEnabled: boolean; securityRulesCancelEnabled: boolean; pendingActionResponsesWithAck: boolean; policyListEnabled: boolean; }>; }" + "Readonly<{} & { signalsIndex: string; maxRuleImportExportSize: number; maxRuleImportPayloadBytes: number; maxTimelineImportExportSize: number; maxTimelineImportPayloadBytes: number; alertMergeStrategy: \"allFields\" | \"missingFields\" | \"noFields\"; alertIgnoreFields: string[]; enableExperimental: string[]; packagerTaskInterval: string; prebuiltRulesFromFileSystem: boolean; prebuiltRulesFromSavedObjects: boolean; }> & { experimentalFeatures: Readonly<{ metricsEntitiesEnabled: boolean; ruleRegistryEnabled: boolean; tGridEnabled: boolean; tGridEventRenderedViewEnabled: boolean; excludePoliciesInFilterEnabled: boolean; uebaEnabled: boolean; disableIsolationUIPendingStatuses: boolean; riskyHostsEnabled: boolean; securityRulesCancelEnabled: boolean; pendingActionResponsesWithAck: boolean; rulesBulkEditEnabled: boolean; policyListEnabled: boolean; }>; }" ], "path": "x-pack/plugins/security_solution/server/config.ts", "deprecated": false, diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index a47a10d8c4d52..6847dbec9f88c 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github summary: API docs for the securitySolution plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/share.devdocs.json b/api_docs/share.devdocs.json index 58935cb956d5e..219e9c5e5ce54 100644 --- a/api_docs/share.devdocs.json +++ b/api_docs/share.devdocs.json @@ -697,10 +697,6 @@ "plugin": "ml", "path": "x-pack/plugins/ml/public/application/components/anomaly_results_view_selector/anomaly_results_view_selector.tsx" }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseriesexplorer_no_jobs_found/timeseriesexplorer_no_jobs_found.tsx" - }, { "plugin": "ml", "path": "x-pack/plugins/ml/public/application/app.tsx" @@ -2401,10 +2397,6 @@ "plugin": "ml", "path": "x-pack/plugins/ml/public/application/components/anomaly_results_view_selector/anomaly_results_view_selector.tsx" }, - { - "plugin": "ml", - "path": "x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseriesexplorer_no_jobs_found/timeseriesexplorer_no_jobs_found.tsx" - }, { "plugin": "ml", "path": "x-pack/plugins/ml/public/application/app.tsx" diff --git a/api_docs/share.mdx b/api_docs/share.mdx index fde07adc1a8f1..fd734bd7dc667 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github summary: API docs for the share plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/shared_u_x.mdx b/api_docs/shared_u_x.mdx index 6153e6643994e..4b9dbf66109a5 100644 --- a/api_docs/shared_u_x.mdx +++ b/api_docs/shared_u_x.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/sharedUX title: "sharedUX" image: https://source.unsplash.com/400x175/?github summary: API docs for the sharedUX plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sharedUX'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index b7b63200e9705..34654d2db8ff1 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github summary: API docs for the snapshotRestore plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index c3d99ae66d8a5..bb64ffb6f6bf2 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github summary: API docs for the spaces plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index 50b88186a1368..aa362623efdee 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github summary: API docs for the stackAlerts plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index eb62f916a1f72..fef89d4959072 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github summary: API docs for the taskManager plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index 1fda3e1be1d86..37df078f5925a 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github summary: API docs for the telemetry plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 5de467cede62a..7ed490b94526c 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github summary: API docs for the telemetryCollectionManager plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 99f0fc03c8e03..147208cab92b0 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github summary: API docs for the telemetryCollectionXpack plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index 1aee905a09db3..3344b01f33534 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github summary: API docs for the telemetryManagementSection plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index aaadb0375ca46..55a0baa7d668c 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github summary: API docs for the timelines plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index dcb2fceedf8b2..46a51e594fa98 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github summary: API docs for the transform plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/triggers_actions_ui.devdocs.json b/api_docs/triggers_actions_ui.devdocs.json index 905eb1592c5ce..caabef769f7a1 100644 --- a/api_docs/triggers_actions_ui.devdocs.json +++ b/api_docs/triggers_actions_ui.devdocs.json @@ -2268,7 +2268,7 @@ "label": "ActionVariables", "description": [], "signature": [ - "AsActionVariables<\"params\" | \"state\"> & Partial>" + "AsActionVariables<\"params\"> & Partial>" ], "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", "deprecated": false, diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index aff1f9c6b0f58..c03571dd585e3 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github summary: API docs for the triggersActionsUi plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index ffb35430700ef..4b82a03570c33 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github summary: API docs for the uiActions plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index 2e1df86a1e749..6e127b2481f25 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github summary: API docs for the uiActionsEnhanced plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index 861d73e29126c..fde1c806412d0 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github summary: API docs for the urlForwarding plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 5232cffff0b44..a7afb41e6d828 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github summary: API docs for the usageCollection plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index d7adf220a3800..aeb91b732b320 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github summary: API docs for the visDefaultEditor plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index feabafde5a751..fcc444df197ad 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeHeatmap plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index b65ec9a34e2cd..48ef62e80e72e 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypePie plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index 982994e396e42..d975cab5a314f 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeTable plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index d8458d6d974f8..0e943ff5df7e2 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeTimelion plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index e8c6c39d97e68..f84d75e672896 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeTimeseries plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index 6a8cffb34b126..bf818de84cc2f 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeVega plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index 79b0594c646d3..0779dda1a3a00 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeVislib plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 69ac6f406be0f..d0e04ffea402d 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeXy plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index d199ce3c552c1..e57e724ebb7fe 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github summary: API docs for the visualizations plugin -date: 2020-11-16 +date: 2022-01-31 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/config/kibana.yml b/config/kibana.yml index aedea8ce83bfb..9143b23d590ff 100644 --- a/config/kibana.yml +++ b/config/kibana.yml @@ -62,6 +62,10 @@ # must be a positive integer. #elasticsearch.requestTimeout: 30000 +# Specifies whether Kibana should use compression for communications with elasticsearch +# Defaults to `false`. +#elasticsearch.compression: false + # List of Kibana client-side headers to send to Elasticsearch. To send *no* client-side # headers, set this value to [] (an empty list). #elasticsearch.requestHeadersWhitelist: [ authorization ] diff --git a/docs/api/index-patterns.asciidoc b/docs/api/index-patterns.asciidoc new file mode 100644 index 0000000000000..212f43118e659 --- /dev/null +++ b/docs/api/index-patterns.asciidoc @@ -0,0 +1,44 @@ +[[index-patterns-api]] +== Index patterns APIs + +deprecated::[8.0.0,Use <> instead.] + +experimental[] Manage {kib} index patterns. + +WARNING: Do not write documents directly to the `.kibana` index. When you write directly +to the `.kibana` index, the data becomes corrupted and permanently breaks future {kib} versions. + +WARNING: Use the index patterns API for managing {kib} index patterns instead of lower-level <>. + +The following index patterns APIs are available: + +* Index patterns + ** <> to retrieve a single {kib} index pattern + ** <> to create {kib} index pattern + ** <> to partially updated {kib} index pattern + ** <> to delete {kib} index pattern +* Default index pattern + ** <> to retrieve a default index pattern + ** <> to set a default index pattern +* Fields + ** <> to change field metadata, such as `count`, `customLabel` and `format` +* Runtime fields + ** <> to retrieve a runtime field + ** <> to create a runtime field + ** <> to create or update a runtime field + ** <> to partially update an existing runtime field + ** <> to delete a runtime field + +include::index-patterns/get.asciidoc[] +include::index-patterns/create.asciidoc[] +include::index-patterns/update.asciidoc[] +include::index-patterns/delete.asciidoc[] +include::index-patterns/default-get.asciidoc[] +include::index-patterns/default-set.asciidoc[] +include::index-patterns/update-fields.asciidoc[] +include::index-patterns/runtime-fields/get.asciidoc[] +include::index-patterns/runtime-fields/create.asciidoc[] +include::index-patterns/runtime-fields/upsert.asciidoc[] +include::index-patterns/runtime-fields/update.asciidoc[] +include::index-patterns/runtime-fields/delete.asciidoc[] + diff --git a/docs/api/index-patterns/create.asciidoc b/docs/api/index-patterns/create.asciidoc new file mode 100644 index 0000000000000..0e91254336456 --- /dev/null +++ b/docs/api/index-patterns/create.asciidoc @@ -0,0 +1,105 @@ +[[index-patterns-api-create]] +=== Create index pattern API +++++ +Create index pattern +++++ + +deprecated::[8.0.0,Use <> instead.] + +experimental[] Create {kib} index patterns. + +[[index-patterns-api-create-request]] +==== Request + +`POST :/api/index_patterns/index_pattern` + +`POST :/s//api/index_patterns/index_pattern` + +[[index-patterns-api-create-path-params]] +==== Path parameters + +`space_id`:: + (Optional, string) An identifier for the space. If `space_id` is not provided in the URL, the default space is used. + +[[index-patterns-api-create-body-params]] +==== Request body + +`override`:: (Optional, boolean) Overrides an existing index pattern if an +index pattern with the provided title already exists. The default is `false`. + +`refresh_fields`:: (Optional, boolean) Reloads index pattern fields after +the index pattern is stored. The default is `false`. + +`index_pattern`:: (Required, object) The index pattern object. All fields are optional. + +[[index-patterns-api-create-request-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +[[index-patterns-api-create-example]] +==== Examples + +Create an index pattern with a custom title: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/index_patterns/index_pattern +{ + "index_pattern": { + "title": "hello" + } +} +-------------------------------------------------- +// KIBANA + +Customize the creation behavior: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/index_patterns/index_pattern +{ + "override": false, + "refresh_fields": true, + "index_pattern": { + "title": "hello" + } +} +-------------------------------------------------- +// KIBANA + +At creation, all index pattern fields are optional: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/index_patterns/index_pattern +{ + "index_pattern": { + "id": "...", + "version": "...", + "title": "...", + "type": "...", + "timeFieldName": "...", + "sourceFilters": [], + "fields": {}, + "typeMeta": {}, + "fieldFormats": {}, + "fieldAttrs": {}, + "runtimeFieldMap": {} + "allowNoIndex": "..." + } +} +-------------------------------------------------- +// KIBANA + + +The API returns the index pattern object: + +[source,sh] +-------------------------------------------------- +{ + "index_pattern": {...} +} +-------------------------------------------------- + diff --git a/docs/api/index-patterns/default-get.asciidoc b/docs/api/index-patterns/default-get.asciidoc new file mode 100644 index 0000000000000..fb27ef000c6a0 --- /dev/null +++ b/docs/api/index-patterns/default-get.asciidoc @@ -0,0 +1,57 @@ +[[index-patterns-api-default-get]] +=== Get default index pattern API +++++ +Get default index pattern +++++ + +deprecated::[8.0.0,Use <> instead.] + +experimental[] Retrieve a default index pattern ID. Kibana UI uses default index pattern unless user picks a different one. + +[[index-patterns-api-default-get-request]] +==== Request + +`GET :/api/index_patterns/default` + +`GET :/s//api/index_patterns/default` + +[[index-patterns-api-default-get-params]] +==== Path parameters + +`space_id`:: +(Optional, string) An identifier for the space. If `space_id` is not provided in the URL, the default space is used. + +[[index-patterns-api-default-get-codes]] +==== Response code + +`200`:: +Indicates a successful call. + +[[index-patterns-api-default-get-example]] +==== Example + +Retrieve the default index pattern id: + +[source,sh] +-------------------------------------------------- +$ curl -X GET api/index_patterns/default +-------------------------------------------------- +// KIBANA + +The API returns an ID of a default index pattern: + +[source,sh] +-------------------------------------------------- +{ + "index_pattern_id": "..." +} +-------------------------------------------------- + +In case there is no default index pattern, the API returns: + +[source,sh] +-------------------------------------------------- +{ + "index_pattern_id": null +} +-------------------------------------------------- diff --git a/docs/api/index-patterns/default-set.asciidoc b/docs/api/index-patterns/default-set.asciidoc new file mode 100644 index 0000000000000..3a9e91001d36e --- /dev/null +++ b/docs/api/index-patterns/default-set.asciidoc @@ -0,0 +1,86 @@ +[[index-patterns-api-default-set]] +=== Set default index pattern API +++++ +Set default index pattern +++++ + +deprecated::[8.0.0,Use <> instead.] + +experimental[] Set a default index pattern ID. Kibana UI will use default index pattern unless user picks a different one. +The API doesn't validate if given `index_pattern_id` is a valid id. + +[[index-patterns-api-default-set-request]] +==== Request + +`POST :/api/index_patterns/default` + +`POST :/s//api/index_patterns/default` + +[[index-patterns-api-default-set-params]] +==== Path parameters + +`space_id`:: +(Optional, string) An identifier for the space. If `space_id` is not provided in the URL, the default space is used. + +[[index-patterns-api-default-set-body]] +==== Request body + +`index_pattern_id`:: (Required, `string` or `null`) Sets a default index pattern id. Use `null` to unset a default index pattern. + +`force`:: (Optional, boolean) Updates existing default index pattern id. The default is `false`. + + +[[index-patterns-api-default-set-codes]] +==== Response code + +`200`:: +Indicates a successful call. + +[[index-patterns-api-default-set-example]] +==== Example + +Set the default index pattern id if none is set: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/index_patterns/default +{ + "index_pattern_id": "..." +} +-------------------------------------------------- +// KIBANA + + +Upsert the default index pattern: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/index_patterns/default +{ + "index_pattern_id": "...", + "force": true +} +-------------------------------------------------- +// KIBANA + +Unset the default index pattern: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/index_patterns/default +{ + "index_pattern_id": null, + "force": true +} +-------------------------------------------------- +// KIBANA + +The API returns: + +[source,sh] +-------------------------------------------------- +{ + "acknowledged": true +} +-------------------------------------------------- + diff --git a/docs/api/index-patterns/delete.asciidoc b/docs/api/index-patterns/delete.asciidoc new file mode 100644 index 0000000000000..013f0e55c37a1 --- /dev/null +++ b/docs/api/index-patterns/delete.asciidoc @@ -0,0 +1,43 @@ +[[index-patterns-api-delete]] +=== Delete index pattern API +++++ +Delete index pattern +++++ + +deprecated::[8.0.0,Use <> instead.] + +experimental[] Delete {kib} index patterns. + +WARNING: Once you delete an index pattern, _it cannot be recovered_. + +[[index-patterns-api-delete-request]] +==== Request + +`DELETE :/api/index_patterns/index_pattern/` + +`DELETE :/s//api/index_patterns/index_pattern/` + +[[index-patterns-api-delete-path-params]] +==== Path parameters + +`space_id`:: + (Optional, string) An identifier for the space. If `space_id` is not provided in the URL, the default space is used. + +`id`:: + (Required, string) The ID of the index pattern you want to delete. + +[[index-patterns-api-delete-response-codes]] +==== Response code + +`200`:: + Indicates that index pattern is deleted. Returns an empty response body. + +==== Example + +Delete an index pattern object with the `my-pattern` ID: + +[source,sh] +-------------------------------------------------- +$ curl -X DELETE api/index_patterns/index_pattern/my-pattern +-------------------------------------------------- +// KIBANA diff --git a/docs/api/index-patterns/get.asciidoc b/docs/api/index-patterns/get.asciidoc new file mode 100644 index 0000000000000..3ae3eb4a84eb5 --- /dev/null +++ b/docs/api/index-patterns/get.asciidoc @@ -0,0 +1,67 @@ +[[index-patterns-api-get]] +=== Get index pattern API +++++ +Get index pattern +++++ + +deprecated::[8.0.0,Use <> instead.] + +experimental[] Retrieve a single {kib} index pattern by ID. + +[[index-patterns-api-get-request]] +==== Request + +`GET :/api/index_patterns/index_pattern/` + +`GET :/s//api/index_patterns/index_pattern/` + +[[index-patterns-api-get-params]] +==== Path parameters + +`space_id`:: +(Optional, string) An identifier for the space. If `space_id` is not provided in the URL, the default space is used. + +`id`:: +(Required, string) The ID of the index pattern you want to retrieve. + +[[index-patterns-api-get-codes]] +==== Response code + +`200`:: +Indicates a successful call. + +`404`:: +The specified index pattern and ID doesn't exist. + +[[index-patterns-api-get-example]] +==== Example + +Retrieve the index pattern object with the `my-pattern` ID: + +[source,sh] +-------------------------------------------------- +$ curl -X GET api/index_patterns/index_pattern/my-pattern +-------------------------------------------------- +// KIBANA + +The API returns an index pattern object: + +[source,sh] +-------------------------------------------------- +{ + "index_pattern": { + "id": "my-pattern", + "version": "...", + "title": "...", + "type": "...", + "timeFieldName": "...", + "sourceFilters": [], + "fields": {}, + "typeMeta": {}, + "fieldFormats": {}, + "fieldAttrs": {}, + "runtimeFieldMap" {}, + "allowNoIndex: "..." + } +} +-------------------------------------------------- diff --git a/docs/api/index-patterns/runtime-fields/create.asciidoc b/docs/api/index-patterns/runtime-fields/create.asciidoc new file mode 100644 index 0000000000000..bd50a5a66dcb6 --- /dev/null +++ b/docs/api/index-patterns/runtime-fields/create.asciidoc @@ -0,0 +1,63 @@ +[[index-patterns-runtime-field-api-create]] +=== Create runtime field API +++++ +Create runtime field +++++ + +deprecated::[8.0.0,Use <> instead.] + +experimental[] Create a runtime field + +[[index-patterns-runtime-field-create-request]] +==== Request + +`POST :/api/index_patterns/index_pattern//runtime_field` + +`POST :/s//api/index_patterns/index_pattern//runtime_field` + +[[index-patterns-runtime-field-create-params]] +==== Path parameters + +`space_id`:: +(Optional, string) An identifier for the space. If `space_id` is not provided in the URL, the default space is used. + +`index_pattern_id`:: +(Required, string) The ID of the index pattern. + +[[index-patterns-runtime-field-create-body]] +==== Request body + +`name`:: (Required, string) The name for a runtime field. + +`runtimeField`:: (Required, object) The runtime field definition object. + + +[[index-patterns-runtime-field-create-example]] +==== Examples + +Create a runtime field on an index pattern: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/index_patterns/index_pattern//runtime_field +{ + "name": "runtimeFoo", + "runtimeField": { + "type": "long", + "script": { + "source": "emit(doc["foo"].value)" + } + } +} +-------------------------------------------------- +// KIBANA + +The API returns created runtime field object and update index pattern object: + +[source,sh] +-------------------------------------------------- +{ + "index_pattern": {...}, + "field": {...} +} +-------------------------------------------------- diff --git a/docs/api/index-patterns/runtime-fields/delete.asciidoc b/docs/api/index-patterns/runtime-fields/delete.asciidoc new file mode 100644 index 0000000000000..838954abe8b3f --- /dev/null +++ b/docs/api/index-patterns/runtime-fields/delete.asciidoc @@ -0,0 +1,39 @@ +[[index-patterns-runtime-field-api-delete]] +=== Delete runtime field API +++++ +Delete runtime field +++++ + +deprecated::[8.0.0,Use <> instead.] + +experimental[] Delete a runtime field from an index pattern. + +[[index-patterns-runtime-field-api-delete-request]] +==== Request + +`DELETE :/api/index_patterns/index_pattern//runtime_field/` + +`DELETE :/s//api/index_patterns/index_pattern//runtime_field/` + +[[index-patterns-runtime-field-api-delete-path-params]] +==== Path parameters + +`space_id`:: +(Optional, string) An identifier for the space. If `space_id` is not provided in the URL, the default space is used. + +`index_pattern_id`:: +(Required, string) The ID of the index pattern your want to delete a runtime field from. + +`name`:: +(Required, string) The name of the runtime field you want to delete. + + +==== Example + +Delete a runtime field from an index pattern: + +[source,sh] +-------------------------------------------------- +$ curl -X DELETE api/index_patterns/index_pattern//runtime_field/ +-------------------------------------------------- +// KIBANA diff --git a/docs/api/index-patterns/runtime-fields/get.asciidoc b/docs/api/index-patterns/runtime-fields/get.asciidoc new file mode 100644 index 0000000000000..155267fa40e44 --- /dev/null +++ b/docs/api/index-patterns/runtime-fields/get.asciidoc @@ -0,0 +1,54 @@ +[[index-patterns-runtime-field-api-get]] +=== Get runtime field API +++++ +Get runtime field +++++ + +deprecated::[8.0.0,Use <> instead.] + +experimental[] Get a runtime field + +[[index-patterns-runtime-field-get-request]] +==== Request + +`GET :/api/index_patterns/index_pattern//runtime_field/` + +`GET :/s//api/index_patterns/index_pattern//runtime_field/` + +[[index-patterns-runtime-field-get-params]] +==== Path parameters + +`space_id`:: +(Optional, string) An identifier for the space. If `space_id` is not provided in the URL, the default space is used. + +`index_pattern_id`:: +(Required, string) The ID of the index pattern. + +`name`:: +(Required, string) The name of the runtime field you want to retrieve. + + +[[index-patterns-runtime-field-get-example]] +==== Example + +Retrieve a runtime field named `foo` of index pattern with the `my-pattern` ID: + +[source,sh] +-------------------------------------------------- +$ curl -X GET api/index_patterns/index_pattern/my-pattern/runtime_field/foo +-------------------------------------------------- +// KIBANA + +The API returns a runtime `field` object, and a `runtimeField` definition object: + +[source,sh] +-------------------------------------------------- +{ + "field": { + ... + }, + "runtimeField": { + ... + } +} +-------------------------------------------------- diff --git a/docs/api/index-patterns/runtime-fields/update.asciidoc b/docs/api/index-patterns/runtime-fields/update.asciidoc new file mode 100644 index 0000000000000..9879b8b457329 --- /dev/null +++ b/docs/api/index-patterns/runtime-fields/update.asciidoc @@ -0,0 +1,68 @@ +[[index-patterns-runtime-field-api-update]] +=== Update runtime field API +++++ +Update runtime field +++++ + +deprecated::[8.0.0,Use <> instead.] + +experimental[] Update an existing runtime field + +[[index-patterns-runtime-field-update-request]] +==== Request + +`POST :/api/index_patterns/index_pattern//runtime_field/` + +`POST :/s//api/index_patterns/index_pattern//runtime_field/` + +[[index-patterns-runtime-field-update-params]] +==== Path parameters + +`space_id`:: +(Optional, string) An identifier for the space. If `space_id` is not provided in the URL, the default space is used. + +`index_pattern_id`:: +(Required, string) The ID of the index pattern. + +`name`:: +(Required, string) The name of the runtime field you want to update. + +[[index-patterns-runtime-field-update-body]] +==== Request body + +`runtimeField`:: (Required, object) The runtime field definition object. + +You can update following fields: + +* `type` +* `script` + + + +[[index-patterns-runtime-field-update-example]] +==== Examples + +Update an existing runtime field on an index pattern: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/index_patterns/index_pattern//runtime_field/ +{ + "runtimeField": { + "script": { + "source": "emit(doc["bar"].value)" + } + } +} +-------------------------------------------------- +// KIBANA + +The API returns updated runtime field object and updated index pattern object: + +[source,sh] +-------------------------------------------------- +{ + "index_pattern": {...}, + "field": {...} +} +-------------------------------------------------- diff --git a/docs/api/index-patterns/runtime-fields/upsert.asciidoc b/docs/api/index-patterns/runtime-fields/upsert.asciidoc new file mode 100644 index 0000000000000..cd15f8c63b5d8 --- /dev/null +++ b/docs/api/index-patterns/runtime-fields/upsert.asciidoc @@ -0,0 +1,63 @@ +[[index-patterns-runtime-field-api-upsert]] +=== Upsert runtime field API +++++ +Upsert runtime field +++++ + +deprecated::[8.0.0,Use <> instead.] + +experimental[] Create or update an existing runtime field + +[[index-patterns-runtime-field-upsert-request]] +==== Request + +`PUT :/api/index_patterns/index_pattern//runtime_field` + +`PUT :/s//api/index_patterns/index_pattern//runtime_field` + +[[index-patterns-runtime-field-upsert-params]] +==== Path parameters + +`space_id`:: +(Optional, string) An identifier for the space. If `space_id` is not provided in the URL, the default space is used. + +`index_pattern_id`:: +(Required, string) The ID of the index pattern. + +[[index-patterns-runtime-field-upsert-body]] +==== Request body + +`name`:: (Required, string) The name for a new runtime field or a name of an existing runtime field. + +`runtimeField`:: (Required, object) The runtime field definition object. + + +[[index-patterns-runtime-field-upsert-example]] +==== Examples + +Create or update an existing runtime field on an index pattern: + +[source,sh] +-------------------------------------------------- +$ curl -X PUT api/index_patterns/index_pattern//runtime_field +{ + "name": "runtimeFoo", + "runtimeField": { + "type": "long", + "script": { + "source": "emit(doc["foo"].value)" + } + } +} +-------------------------------------------------- +// KIBANA + +The API returns created or updated runtime field object and updated index pattern object: + +[source,sh] +-------------------------------------------------- +{ + "index_pattern": {...}, + "field": {...} +} +-------------------------------------------------- diff --git a/docs/api/index-patterns/update-fields.asciidoc b/docs/api/index-patterns/update-fields.asciidoc new file mode 100644 index 0000000000000..e3ac304745f39 --- /dev/null +++ b/docs/api/index-patterns/update-fields.asciidoc @@ -0,0 +1,102 @@ +[[index-patterns-fields-api-update]] +=== Update index pattern fields API +++++ +Update index pattern fields metadata +++++ + +deprecated::[8.0.0,Use <> instead.] + +experimental[] Update fields presentation metadata, such as `count`, +`customLabel`, and `format`. You can update multiple fields in one request. Updates +are merged with persisted metadata. To remove existing metadata, specify `null` as the value. + +[[index-patterns-fields-api-update-request]] +==== Request + +`POST :/api/index_patterns/index_pattern//fields` + +`POST :/s//api/index_patterns/index_pattern//fields` + +[[index-patterns-fields-api-update-path-params]] +==== Path parameters + +`space_id`:: +(Optional, string) An identifier for the space. If `space_id` is not provided in the URL, the default space is used. + +`id`:: +(Required, string) The ID of the index pattern fields you want to update. + +[[index-patterns-fields-api-update-request-body]] +==== Request body + +`fields`:: +(Required, object) the field object + + +[[index-patterns-fields-api-update-errors-codes]] +==== Response code + +`200`:: +Indicates a successful call. + +[[index-patterns-fields-api-update-example]] +==== Examples + +Set popularity `count` for field `foo`: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/saved_objects/index-pattern/my-pattern/fields +{ + "fields": { + "foo": { + "count": 123 + } + } +} +-------------------------------------------------- +// KIBANA + +Update multiple metadata fields in one request: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/saved_objects/index-pattern/my-pattern/fields +{ + "fields": { + "foo": { + "count": 123, + "customLabel": "Foo" + }, + "bar": { + "customLabel": "Bar" + } + } +} +-------------------------------------------------- +// KIBANA + +Use `null` value to delete metadata: +[source,sh] +-------------------------------------------------- +$ curl -X POST api/saved_objects/index-pattern/my-pattern/fields +{ + "fields": { + "foo": { + "customLabel": null + } + } +} +-------------------------------------------------- +// KIBANA + + +The endpoint returns the updated index pattern object: +[source,sh] +-------------------------------------------------- +{ + "index_pattern": { + + } +} +-------------------------------------------------- diff --git a/docs/api/index-patterns/update.asciidoc b/docs/api/index-patterns/update.asciidoc new file mode 100644 index 0000000000000..366afd336d15a --- /dev/null +++ b/docs/api/index-patterns/update.asciidoc @@ -0,0 +1,114 @@ +[[index-patterns-api-update]] +=== Update index pattern API +++++ +Update index pattern +++++ + +deprecated::[8.0.0,Use <> instead.] + +experimental[] Update part of an index pattern. Only the specified fields are updated in the +index pattern. Unspecified fields stay as they are persisted. + +[[index-patterns-api-update-request]] +==== Request + +`POST :/api/index_patterns/index_pattern/` + +`POST :/s//api/index_patterns/index_pattern/` + +[[index-patterns-api-update-path-params]] +==== Path parameters + +`space_id`:: + (Optional, string) An identifier for the space. If `space_id` is not provided in the URL, the default space is used. + +`id`:: + (Required, string) The ID of the index pattern you want to update. + +[[index-patterns-api-update-request-body]] +==== Request body + +`refresh_fields`:: (Optional, boolean) Reloads the index pattern fields after +the index pattern is updated. The default is `false`. + +`index_pattern`:: + (Required, object) The index patterns fields you want to update. ++ + +You can partially update the following fields: + +* `title` +* `timeFieldName` +* `fields` +* `sourceFilters` +* `fieldFormatMap` +* `type` +* `typeMeta` + +[[index-patterns-api-update-errors-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +[[index-patterns-api-update-example]] +==== Examples + +Update a title of the `` index pattern: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/saved_objects/index-pattern/my-pattern +{ + "index_pattern": { + "title": "some-other-pattern-*" + } +} +-------------------------------------------------- +// KIBANA + +Customize the update behavior: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/saved_objects/index-pattern/my-pattern +{ + "refresh_fields": true, + "index_pattern": { + "fields": {} + } +} +-------------------------------------------------- +// KIBANA + + +All update fields are optional, but you can specify the following fields: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/saved_objects/index-pattern/my-pattern +{ + "index_pattern": { + "title": "...", + "timeFieldName": "...", + "sourceFilters": [], + "fieldFormats": {}, + "type": "...", + "typeMeta": {}, + "fields": {}, + "runtimeFieldMap": {} + } +} +-------------------------------------------------- +// KIBANA + +The API returns the updated index pattern object: + +[source,sh] +-------------------------------------------------- +{ + "index_pattern": { + + } +} +-------------------------------------------------- diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md index 7864f2ca828db..7cf5a8a749302 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md @@ -11,7 +11,8 @@ readonly links: { readonly settings: string; readonly elasticStackGetStarted: string; readonly upgrade: { - readonly upgradingElasticStack: string; + readonly upgradingStackOnPrem: string; + readonly upgradingStackOnCloud: string; }; readonly apm: { readonly kibanaSettings: string; diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchclientconfig.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchclientconfig.md index 0084b0b50c869..e7b65fc9dfa56 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchclientconfig.md +++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchclientconfig.md @@ -9,7 +9,7 @@ Configuration options to be used to create a [cluster client](./kibana-plugin-co Signature: ```typescript -export declare type ElasticsearchClientConfig = Pick & { +export declare type ElasticsearchClientConfig = Pick & { pingTimeout?: ElasticsearchConfig['pingTimeout'] | ClientOptions['pingTimeout']; requestTimeout?: ElasticsearchConfig['requestTimeout'] | ClientOptions['requestTimeout']; ssl?: Partial; diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.compression.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.compression.md new file mode 100644 index 0000000000000..5bc85dfb05647 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.compression.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchConfig](./kibana-plugin-core-server.elasticsearchconfig.md) > [compression](./kibana-plugin-core-server.elasticsearchconfig.compression.md) + +## ElasticsearchConfig.compression property + +Whether to use compression for communications with elasticsearch. + +Signature: + +```typescript +readonly compression: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.md index c75f6377f4038..3e9bb43c98501 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.md +++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchconfig.md @@ -23,6 +23,7 @@ export declare class ElasticsearchConfig | Property | Modifiers | Type | Description | | --- | --- | --- | --- | | [apiVersion](./kibana-plugin-core-server.elasticsearchconfig.apiversion.md) | | string | Version of the Elasticsearch (6.7, 7.1 or master) client will be connecting to. | +| [compression](./kibana-plugin-core-server.elasticsearchconfig.compression.md) | | boolean | Whether to use compression for communications with elasticsearch. | | [customHeaders](./kibana-plugin-core-server.elasticsearchconfig.customheaders.md) | | ElasticsearchConfigType\['customHeaders'\] | Header names and values to send to Elasticsearch with every request. These headers cannot be overwritten by client-side headers and aren't affected by requestHeadersWhitelist configuration. | | [healthCheckDelay](./kibana-plugin-core-server.elasticsearchconfig.healthcheckdelay.md) | | Duration | The interval between health check requests Kibana sends to the Elasticsearch. | | [hosts](./kibana-plugin-core-server.elasticsearchconfig.hosts.md) | | string\[\] | Hosts that the client will connect to. If sniffing is enabled, this list will be used as seeds to discover the rest of your cluster. | diff --git a/docs/redirects.asciidoc b/docs/redirects.asciidoc index 5d161711719ac..4e0f0d4f99e66 100644 --- a/docs/redirects.asciidoc +++ b/docs/redirects.asciidoc @@ -381,66 +381,6 @@ This content has moved. Refer to <>. This content has moved. Refer to <>. -[role="exclude",id="index-patterns-api"] -== Index patterns has been renamed to data views. - -This content has moved. Refer to <>. - -[role="exclude",id="index-patterns-api-create"] -== Index patterns has been renamed to data views. - -This content has moved. Refer to <>. - -[role="exclude",id="index-patterns-api-default-get"] -== Index patterns has been renamed to data views. - -This content has moved. Refer to <>. - -[role="exclude",id="index-patterns-api-default-set"] -== Index patterns has been renamed to data views. - -This content has moved. Refer to <>. - -[role="exclude",id="index-patterns-api-delete"] -== Index patterns has been renamed to data views. - -This content has moved. Refer to <>. - -[role="exclude",id="index-patterns-api-get"] -== Index patterns has been renamed to data views. - -This content has moved. Refer to <>. - -[role="exclude",id="index-patterns-runtime-field-api-create"] -== Index patterns has been renamed to data views. - -This content has moved. Refer to <>. - -[role="exclude",id="index-patterns-runtime-field-api-delete"] -== Index patterns has been renamed to data views. - -This content has moved. Refer to <>. - -[role="exclude",id="index-patterns-runtime-field-api-get"] -== Index patterns has been renamed to data views. - -This content has moved. Refer to <>. - -[role="exclude",id="index-patterns-runtime-field-api-update"] -== Index patterns has been renamed to data views. - -This content has moved. Refer to <>. - -[role="exclude",id="index-patterns-runtime-field-api-upsert"] -== Index patterns has been renamed to data views. - -This content has moved. Refer to <>. - -[role="exclude",id="index-patterns-api-update"] -== Index patterns has been renamed to data views. - -This content has moved. Refer to <>. - [role="exclude",id="xpack-kibana-role-management"] == Kibana role management. diff --git a/docs/settings/reporting-settings.asciidoc b/docs/settings/reporting-settings.asciidoc index 9b5b5b37aa62d..3c1b86f771064 100644 --- a/docs/settings/reporting-settings.asciidoc +++ b/docs/settings/reporting-settings.asciidoc @@ -97,10 +97,10 @@ NOTE: Running multiple instances of {kib} in a cluster for load balancing of reporting requires identical values for <> and, if security is enabled, <>. -`xpack.reporting.queue.pollInterval`:: +`xpack.reporting.queue.pollInterval`:: Specifies the {time-units}[time] that the reporting poller waits between polling the index for any pending Reporting jobs. Can be specified as number of milliseconds. Defaults to `3s`. -[[xpack-reporting-q-timeout]] `xpack.reporting.queue.timeout` {ess-icon}:: +[[xpack-reporting-q-timeout]] `xpack.reporting.queue.timeout` {ess-icon}:: {time-units}[How long] each worker has to produce a report. If your machine is slow or under heavy load, you might need to increase this timeout. If a Reporting job execution goes over this time limit, the job is marked as a failure and no download will be available. Can be specified as number of milliseconds. Defaults to `2m`. [float] @@ -109,7 +109,7 @@ Specifies the {time-units}[time] that the reporting poller waits between polling Reporting works by capturing screenshots from {kib}. The following settings control the capturing process. -`xpack.reporting.capture.timeouts.openUrl` {ess-icon}:: +`xpack.reporting.capture.timeouts.openUrl` {ess-icon}:: Specify the {time-units}[time] to allow the Reporting browser to wait for the "Loading..." screen to dismiss and find the initial data for the page. If the time is exceeded, a screenshot is captured showing the current page, and the download link shows a warning message. Can be specified as number of milliseconds. Defaults to `1m`. `xpack.reporting.capture.timeouts.waitForElements` {ess-icon}:: @@ -123,7 +123,7 @@ running a report job, Reporting will log the error and try to continue capturing the page with a screenshot. As a result, a download will be available, but there will likely be errors in the visualizations in the report. -`xpack.reporting.capture.maxAttempts` {ess-icon}:: +`xpack.reporting.capture.maxAttempts` {ess-icon}:: If capturing a report fails for any reason, {kib} will re-attempt other reporting job, as many times as this setting. Defaults to `3`. `xpack.reporting.capture.loadDelay`:: @@ -172,14 +172,14 @@ The rule objects are evaluated sequentially from the beginning to the end of the ------------------------------------------------------- # Only allow requests to placeholder.com xpack.reporting.capture.networkPolicy: - rules: [ { allow: true, host: "placeholder.com" } ] + rules: [ { allow: true, host: "placeholder.com" } ] ------------------------------------------------------- [source,yaml] ------------------------------------------------------- -# Only allow requests to https://placeholder.com +# Only allow requests to https://placeholder.com xpack.reporting.capture.networkPolicy: - rules: [ { allow: true, host: "placeholder.com", protocol: "https:" } ] + rules: [ { allow: true, host: "placeholder.com", protocol: "https:" } ] ------------------------------------------------------- A final `allow` rule with no host or protocol allows all requests that are not explicitly denied: @@ -235,12 +235,18 @@ Number of documents retrieved from {es} for each scroll iteration during a CSV e Amount of {time-units}[time] allowed before {kib} cleans the scroll context during a CSV export. Defaults to `30s`. `xpack.reporting.csv.checkForFormulas`:: -Enables a check that warns you when there's a potential formula involved in the output (=, -, +, and @ chars). See OWASP: https://www.owasp.org/index.php/CSV_Injection. Defaults to `true`. +Enables a check that warns you when there's a potential formula included in the output (=, -, +, and @ chars). See OWASP: https://www.owasp.org/index.php/CSV_Injection. Defaults to `true`. -`xpack.reporting.csv` `.enablePanelActionDownload`:: +`xpack.reporting.csv.escapeFormulaValues`:: +Escape formula values in cells with a `'`. See OWASP: https://www.owasp.org/index.php/CSV_Injection. Defaults to `true`. + +`xpack.reporting.csv.enablePanelActionDownload`:: Enables CSV export from a saved search on a dashboard. This action is available in the dashboard panel menu for the saved search. NOTE: This setting exists for backwards compatibility, but is unused and hardcoded to `true`. CSV export from a saved search on a dashboard is enabled when Reporting is enabled. +`xpack.reporting.csv.useByteOrderMarkEncoding`:: +Adds a byte order mark (`\ufeff`) at the beginning of the CSV file. Defaults to `false`. + [float] [[reporting-advanced-settings]] ==== Security settings diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index 8384e65997ee0..e55a94a516d68 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -152,6 +152,9 @@ This value must be a positive integer. *Default: `30000`* | Time in milliseconds for {es} to wait for responses from shards. Set to 0 to disable. *Default: `30000`* +| `elasticsearch.compression:` +| Specifies whether {kib} should use compression for communications with {es}. *Default: `false`* + | `elasticsearch.sniffInterval:` | Time in milliseconds between requests to check {es} for an updated list of nodes. *Default: `false`* diff --git a/docs/user/api.asciidoc b/docs/user/api.asciidoc index 1564d78c8f444..5a9c5fe6cdf21 100644 --- a/docs/user/api.asciidoc +++ b/docs/user/api.asciidoc @@ -92,6 +92,7 @@ include::{kib-repo-dir}/api/role-management.asciidoc[] include::{kib-repo-dir}/api/session-management.asciidoc[] include::{kib-repo-dir}/api/saved-objects.asciidoc[] include::{kib-repo-dir}/api/data-views.asciidoc[] +include::{kib-repo-dir}/api/index-patterns.asciidoc[] include::{kib-repo-dir}/api/alerting.asciidoc[] include::{kib-repo-dir}/api/actions-and-connectors.asciidoc[] include::{kib-repo-dir}/api/dashboard-api.asciidoc[] diff --git a/docs/user/dashboard/vega-reference.asciidoc b/docs/user/dashboard/vega-reference.asciidoc index 1277797417c9e..860261129a364 100644 --- a/docs/user/dashboard/vega-reference.asciidoc +++ b/docs/user/dashboard/vega-reference.asciidoc @@ -351,6 +351,8 @@ a configuration option for changing the tooltip position and padding: *Vega* can load data from any URL. To enable, set `vis_type_vega.enableExternalUrls: true` in `kibana.yml`, then restart {kib}. +You can make the current time range part of the external as a millisecond timestamp by using the placeholders `%timefilter_min%` and `%timefilter_max%`, e.g. `http://example.com?min=%timefilter_min%`. + [float] [[vega-inspector]] ====== Vega Inspector diff --git a/nav-kibana-dev.docnav.json b/nav-kibana-dev.docnav.json index 6f3389bc02e09..fae6a0ea99ccd 100644 --- a/nav-kibana-dev.docnav.json +++ b/nav-kibana-dev.docnav.json @@ -82,6 +82,7 @@ "items": [ { "id": "kibDevDocsApiWelcome" }, { "id": "kibDevDocsPluginDirectory" }, + { "id": "kibDevDocsDeprecationsDueByTeam" }, { "id": "kibDevDocsDeprecationsByPlugin" }, { "id": "kibDevDocsDeprecationsByApi" }, { "id": "kibCorePluginApi" }, diff --git a/package.json b/package.json index c5c8a81a82017..802f5f6d04eb2 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "yarn": "^1.21.1" }, "resolutions": { - "**/@babel/runtime": "^7.16.3", + "**/@babel/runtime": "^7.16.7", "**/@types/node": "16.10.2", "**/chokidar": "^3.4.3", "**/deepmerge": "^4.2.2", @@ -96,7 +96,7 @@ "globby/fast-glob": "3.2.7" }, "dependencies": { - "@babel/runtime": "^7.16.3", + "@babel/runtime": "^7.16.7", "@dnd-kit/core": "^3.1.1", "@dnd-kit/sortable": "^4.0.0", "@dnd-kit/utilities": "^2.0.0", @@ -278,6 +278,7 @@ "json-stable-stringify": "^1.0.1", "json-stringify-pretty-compact": "1.2.0", "json-stringify-safe": "5.0.1", + "jsonwebtoken": "^8.3.0", "jsts": "^1.6.2", "kea": "^2.4.2", "load-json-file": "^6.2.0", @@ -420,25 +421,25 @@ }, "devDependencies": { "@apidevtools/swagger-parser": "^10.0.3", - "@babel/cli": "^7.16.0", - "@babel/core": "^7.16.0", - "@babel/eslint-parser": "^7.16.3", - "@babel/eslint-plugin": "^7.14.5", - "@babel/generator": "^7.16.0", - "@babel/parser": "^7.16.4", - "@babel/plugin-proposal-class-properties": "^7.16.0", - "@babel/plugin-proposal-export-namespace-from": "^7.16.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", - "@babel/plugin-proposal-object-rest-spread": "^7.16.0", - "@babel/plugin-proposal-optional-chaining": "^7.16.0", - "@babel/plugin-proposal-private-methods": "^7.16.0", - "@babel/plugin-transform-runtime": "^7.16.4", - "@babel/preset-env": "^7.16.4", - "@babel/preset-react": "^7.16.0", - "@babel/preset-typescript": "^7.16.0", - "@babel/register": "^7.16.0", - "@babel/traverse": "^7.16.3", - "@babel/types": "^7.16.0", + "@babel/cli": "^7.16.8", + "@babel/core": "^7.16.12", + "@babel/eslint-parser": "^7.16.5", + "@babel/eslint-plugin": "^7.16.5", + "@babel/generator": "^7.16.8", + "@babel/parser": "^7.16.12", + "@babel/plugin-proposal-class-properties": "^7.16.7", + "@babel/plugin-proposal-export-namespace-from": "^7.16.7", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", + "@babel/plugin-proposal-object-rest-spread": "^7.16.7", + "@babel/plugin-proposal-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-private-methods": "^7.16.11", + "@babel/plugin-transform-runtime": "^7.16.10", + "@babel/preset-env": "^7.16.11", + "@babel/preset-react": "^7.16.7", + "@babel/preset-typescript": "^7.16.7", + "@babel/register": "^7.16.9", + "@babel/traverse": "^7.16.10", + "@babel/types": "^7.16.8", "@bazel/ibazel": "^0.15.10", "@bazel/typescript": "^3.8.0", "@cypress/code-coverage": "^3.9.12", @@ -501,7 +502,7 @@ "@testing-library/user-event": "^13.1.1", "@types/apidoc": "^0.22.3", "@types/archiver": "^5.1.0", - "@types/babel__core": "^7.1.16", + "@types/babel__core": "^7.1.18", "@types/base64-js": "^1.2.5", "@types/chance": "^1.0.0", "@types/chroma-js": "^1.4.2", diff --git a/packages/elastic-apm-synthtrace/src/lib/apm/apm_fields.ts b/packages/elastic-apm-synthtrace/src/lib/apm/apm_fields.ts index e0a48fdcf2b89..4afebf0352a6a 100644 --- a/packages/elastic-apm-synthtrace/src/lib/apm/apm_fields.ts +++ b/packages/elastic-apm-synthtrace/src/lib/apm/apm_fields.ts @@ -63,8 +63,12 @@ export type ApmFields = Fields & }; 'transaction.sampled': true; 'service.name': string; + 'service.version': string; 'service.environment': string; 'service.node.name': string; + 'service.runtime.name': string; + 'service.runtime.version': string; + 'service.framework.name': string; 'span.id': string; 'span.name': string; 'span.type': string; @@ -77,5 +81,17 @@ export type ApmFields = Fields & 'span.destination.service.response_time.count': number; 'span.self_time.count': number; 'span.self_time.sum.us': number; + 'cloud.provider': string; + 'cloud.project.name': string; + 'cloud.service.name': string; + 'cloud.availability_zone': string; + 'cloud.machine.type': string; + 'cloud.region': string; + 'host.os.platform': string; + 'faas.id': string; + 'faas.coldstart': boolean; + 'faas.execution': string; + 'faas.trigger.type': string; + 'faas.trigger.request_id': string; }> & ApmApplicationMetricFields; diff --git a/packages/elastic-apm-synthtrace/src/lib/apm/utils/get_transaction_metrics.ts b/packages/elastic-apm-synthtrace/src/lib/apm/utils/get_transaction_metrics.ts index 8545ae65d8aa0..baa9f57a19a46 100644 --- a/packages/elastic-apm-synthtrace/src/lib/apm/utils/get_transaction_metrics.ts +++ b/packages/elastic-apm-synthtrace/src/lib/apm/utils/get_transaction_metrics.ts @@ -51,6 +51,20 @@ export function getTransactionMetrics(events: ApmFields[]) { 'host.name', 'container.id', 'kubernetes.pod.name', + 'cloud.account.id', + 'cloud.account.name', + 'cloud.machine.type', + 'cloud.project.id', + 'cloud.project.name', + 'cloud.service.name', + 'service.language.name', + 'service.language.version', + 'service.runtime.name', + 'service.runtime.version', + 'host.os.platform', + 'faas.id', + 'faas.coldstart', + 'faas.trigger.type', ]); return metricsets.map((metricset) => { diff --git a/packages/kbn-docs-utils/src/api_docs/build_api_docs_cli.ts b/packages/kbn-docs-utils/src/api_docs/build_api_docs_cli.ts index 3e466f581702b..15658361b3627 100644 --- a/packages/kbn-docs-utils/src/api_docs/build_api_docs_cli.ts +++ b/packages/kbn-docs-utils/src/api_docs/build_api_docs_cli.ts @@ -23,6 +23,7 @@ import { writeDeprecationDocByPlugin } from './mdx/write_deprecations_doc_by_plu import { writePluginDirectoryDoc } from './mdx/write_plugin_directory_doc'; import { collectApiStatsForPlugin } from './stats'; import { countEslintDisableLine, EslintDisableCounts } from './count_eslint_disable'; +import { writeDeprecationDueByTeam } from './mdx/write_deprecations_due_by_team'; function isStringArray(arr: unknown | string[]): arr is string[] { return Array.isArray(arr) && arr.every((p) => typeof p === 'string'); @@ -248,6 +249,7 @@ export function runBuildApiDocsCli() { log.info(`Plugin ${pluginApi.id} has no public API.`); } writeDeprecationDocByPlugin(outputFolder, referencedDeprecations, log); + writeDeprecationDueByTeam(outputFolder, referencedDeprecations, plugins, log); writeDeprecationDocByApi( outputFolder, referencedDeprecations, diff --git a/packages/kbn-docs-utils/src/api_docs/mdx/build_plugin_deprecations_table.ts b/packages/kbn-docs-utils/src/api_docs/mdx/build_plugin_deprecations_table.ts new file mode 100644 index 0000000000000..4e4d5e2bf0ceb --- /dev/null +++ b/packages/kbn-docs-utils/src/api_docs/mdx/build_plugin_deprecations_table.ts @@ -0,0 +1,68 @@ +/* + * 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 { ToolingLog } from '@kbn/dev-utils'; +import Path from 'path'; +import { ApiDeclaration, ApiReference, ReferencedDeprecationsByPlugin } from '../types'; +import { getPluginApiDocId } from '../utils'; + +export function buildPluginDeprecationsTable( + folder: string, + deprecationsByPlugin: ReferencedDeprecationsByPlugin, + log: ToolingLog +): string { + const tableMdx = Object.keys(deprecationsByPlugin) + .sort() + .map((key) => { + const groupedDeprecationReferences: { + [key: string]: { api: ApiDeclaration; refs: ApiReference[] }; + } = deprecationsByPlugin[key].reduce((acc, deprecation) => { + if (acc[deprecation.deprecatedApi.id] === undefined) { + acc[deprecation.deprecatedApi.id] = { api: deprecation.deprecatedApi, refs: [] }; + } + acc[deprecation.deprecatedApi.id].refs.push(deprecation.ref); + return acc; + }, {} as { [key: string]: { api: ApiDeclaration; refs: ApiReference[] } }); + + return ` + ## ${key} + + | Deprecated API | Reference location(s) | Remove By | + | ---------------|-----------|-----------| + ${Object.keys(groupedDeprecationReferences) + .map((dep) => { + const api = groupedDeprecationReferences[dep].api; + const refs = groupedDeprecationReferences[dep].refs; + + const deprecatedAPILink = ``; + + const firstTen = refs.splice(0, 10); + const referencedLocations = + firstTen + .map( + (ref) => + `[${ref.path.substr( + ref.path.lastIndexOf(Path.sep) + 1 + )}](https://github.com/elastic/kibana/tree/master/${ + ref.path + }#:~:text=${encodeURIComponent(api.label)})` + ) + .join(', ') + (refs.length > 0 ? `+ ${refs.length} more` : ''); + + const removeBy = api.removeBy ? api.removeBy : '-'; + + return `| ${deprecatedAPILink} | ${referencedLocations} | ${removeBy} |`; + }) + .join('\n')} + `; + }) + .join('\n\n'); + return tableMdx; +} diff --git a/packages/kbn-docs-utils/src/api_docs/mdx/write_deprecations_doc_by_api.ts b/packages/kbn-docs-utils/src/api_docs/mdx/write_deprecations_doc_by_api.ts index 28e149bd8e272..031dc8cf35bce 100644 --- a/packages/kbn-docs-utils/src/api_docs/mdx/write_deprecations_doc_by_api.ts +++ b/packages/kbn-docs-utils/src/api_docs/mdx/write_deprecations_doc_by_api.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import moment from 'moment'; import { ToolingLog } from '@kbn/dev-utils'; import dedent from 'dedent'; import fs from 'fs'; @@ -79,7 +80,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API summary: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2021-07-27 +date: ${moment().format('YYYY-MM-DD')} tags: ['contributor', 'dev', 'apidocs', 'kibana'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. --- diff --git a/packages/kbn-docs-utils/src/api_docs/mdx/write_deprecations_doc_by_plugin.ts b/packages/kbn-docs-utils/src/api_docs/mdx/write_deprecations_doc_by_plugin.ts index 896dd806603e3..6be1ca11d3d4f 100644 --- a/packages/kbn-docs-utils/src/api_docs/mdx/write_deprecations_doc_by_plugin.ts +++ b/packages/kbn-docs-utils/src/api_docs/mdx/write_deprecations_doc_by_plugin.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import moment from 'moment'; import { ToolingLog } from '@kbn/dev-utils'; import dedent from 'dedent'; import fs from 'fs'; @@ -73,7 +74,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin summary: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2021-05-02 +date: ${moment().format('YYYY-MM-DD')} tags: ['contributor', 'dev', 'apidocs', 'kibana'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. --- diff --git a/packages/kbn-docs-utils/src/api_docs/mdx/write_deprecations_due_by_team.ts b/packages/kbn-docs-utils/src/api_docs/mdx/write_deprecations_due_by_team.ts new file mode 100644 index 0000000000000..596532a730f49 --- /dev/null +++ b/packages/kbn-docs-utils/src/api_docs/mdx/write_deprecations_due_by_team.ts @@ -0,0 +1,114 @@ +/* + * 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 moment from 'moment'; +import { ToolingLog } from '@kbn/dev-utils'; +import dedent from 'dedent'; +import fs from 'fs'; +import Path from 'path'; +import { + ApiDeclaration, + ApiReference, + PluginOrPackage, + ReferencedDeprecationsByPlugin, +} from '../types'; +import { getPluginApiDocId } from '../utils'; + +export function writeDeprecationDueByTeam( + folder: string, + deprecationsByPlugin: ReferencedDeprecationsByPlugin, + plugins: PluginOrPackage[], + log: ToolingLog +): void { + const groupedByTeam: ReferencedDeprecationsByPlugin = Object.keys(deprecationsByPlugin).reduce( + (teamMap: ReferencedDeprecationsByPlugin, pluginId: string) => { + const dueDeprecations = deprecationsByPlugin[pluginId].filter( + (dep) => !!dep.deprecatedApi.removeBy + ); + if (!dueDeprecations) return teamMap; + + const pluginMetaInfo = plugins.find((p) => p.manifest.id === pluginId); + if (!pluginMetaInfo || !pluginMetaInfo.manifest.owner.name) return teamMap; + + if (!teamMap[pluginMetaInfo.manifest.owner.name]) { + teamMap[pluginMetaInfo.manifest.owner.name] = []; + } + teamMap[pluginMetaInfo.manifest.owner.name].push(...dueDeprecations); + return teamMap; + }, + {} as ReferencedDeprecationsByPlugin + ); + + const tableMdx = Object.keys(groupedByTeam) + .sort() + .map((key) => { + const groupedDeprecationReferences: { + [key: string]: { api: ApiDeclaration; refs: ApiReference[] }; + } = groupedByTeam[key].reduce((acc, deprecation) => { + if (acc[deprecation.deprecatedApi.id] === undefined) { + acc[deprecation.deprecatedApi.id] = { api: deprecation.deprecatedApi, refs: [] }; + } + acc[deprecation.deprecatedApi.id].refs.push(deprecation.ref); + return acc; + }, {} as { [key: string]: { api: ApiDeclaration; refs: ApiReference[] } }); + + return ` + ## ${key} + + | Plugin | Deprecated API | Reference location(s) | Remove By | + | --------|-------|-----------|-----------| + ${Object.keys(groupedDeprecationReferences) + .map((dep) => { + const api = groupedDeprecationReferences[dep].api; + const refs = groupedDeprecationReferences[dep].refs; + + if (refs.length === 0) return; + + const deprecatedAPILink = ``; + + const firstTen = refs.splice(0, 10); + const referencedLocations = + firstTen + .map( + (ref) => + `[${ref.path.substr( + ref.path.lastIndexOf(Path.sep) + 1 + )}](https://github.com/elastic/kibana/tree/master/${ + ref.path + }#:~:text=${encodeURIComponent(api.label)})` + ) + .join(', ') + (refs.length > 0 ? `+ ${refs.length} more` : ''); + + const removeBy = api.removeBy ? api.removeBy : '-'; + + // These were initially grouped by plugin, so each array of references is coming from a specific plugin. + return `| ${firstTen[0].plugin} | ${deprecatedAPILink} | ${referencedLocations} | ${removeBy} |`; + }) + .join('\n')} + `; + }) + .join('\n\n'); + + const mdx = dedent(` +--- +id: kibDevDocsDeprecationsDueByTeam +slug: /kibana-dev-docs/api-meta/deprecations-due-by-team +title: Deprecated APIs due to be removed, by team +summary: Lists the teams that are referencing deprecated APIs with a remove by date. +date: ${moment().format('YYYY-MM-DD')} +tags: ['contributor', 'dev', 'apidocs', 'kibana'] +warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +--- + +${tableMdx} + +`); + + fs.writeFileSync(Path.resolve(folder, 'deprecations_by_team.mdx'), mdx); +} diff --git a/packages/kbn-docs-utils/src/api_docs/mdx/write_plugin_directory_doc.ts b/packages/kbn-docs-utils/src/api_docs/mdx/write_plugin_directory_doc.ts index 05613cdbd34fe..f7099e6c1a23b 100644 --- a/packages/kbn-docs-utils/src/api_docs/mdx/write_plugin_directory_doc.ts +++ b/packages/kbn-docs-utils/src/api_docs/mdx/write_plugin_directory_doc.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - +import moment from 'moment'; import fs from 'fs'; import Path from 'path'; import dedent from 'dedent'; @@ -78,7 +78,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory summary: Directory of public APIs available through plugins or packages. -date: 2021-09-22 +date: ${moment().format('YYYY-MM-DD')} tags: ['contributor', 'dev', 'apidocs', 'kibana'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/packages/kbn-docs-utils/src/api_docs/mdx/write_plugin_mdx_docs.ts b/packages/kbn-docs-utils/src/api_docs/mdx/write_plugin_mdx_docs.ts index 562296418bbbe..562d2a8981764 100644 --- a/packages/kbn-docs-utils/src/api_docs/mdx/write_plugin_mdx_docs.ts +++ b/packages/kbn-docs-utils/src/api_docs/mdx/write_plugin_mdx_docs.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - +import moment from 'moment'; import fs from 'fs'; import Path from 'path'; import dedent from 'dedent'; @@ -80,7 +80,7 @@ slug: /kibana-dev-docs/api/${slug} title: "${doc.id}" image: https://source.unsplash.com/400x175/?github summary: API docs for the ${doc.id} plugin -date: 2020-11-16 +date: ${moment().format('YYYY-MM-DD')} tags: ['contributor', 'dev', 'apidocs', 'kibana', '${doc.id}'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/packages/kbn-docs-utils/src/api_docs/types.ts b/packages/kbn-docs-utils/src/api_docs/types.ts index 08f48d320d824..afbbec82935e4 100644 --- a/packages/kbn-docs-utils/src/api_docs/types.ts +++ b/packages/kbn-docs-utils/src/api_docs/types.ts @@ -234,6 +234,12 @@ export interface ReferencedDeprecationsByPlugin { [key: string]: Array<{ deprecatedApi: ApiDeclaration; ref: ApiReference }>; } +// A mapping of plugin owner to it's plugin deprecation list. +export interface ReferencedDeprecationsByTeam { + // Key is the plugin owner. + [key: string]: ReferencedDeprecationsByPlugin; +} + export interface UnreferencedDeprecationsByPlugin { // Key is the plugin id. [key: string]: ApiDeclaration[]; diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 3896c67454b90..d4105a5edd7a5 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -746,8 +746,7 @@ function _interopRequireDefault(obj) { }; } -module.exports = _interopRequireDefault; -module.exports["default"] = module.exports, module.exports.__esModule = true; +module.exports = _interopRequireDefault, module.exports.__esModule = true, module.exports["default"] = module.exports; /***/ }), /* 8 */ @@ -768,8 +767,7 @@ function _defineProperty(obj, key, value) { return obj; } -module.exports = _defineProperty; -module.exports["default"] = module.exports, module.exports.__esModule = true; +module.exports = _defineProperty, module.exports.__esModule = true, module.exports["default"] = module.exports; /***/ }), /* 9 */ @@ -8869,9 +8867,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_validate_dependencies__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(419); /* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(421); /* harmony import */ var _utils_bazel_setup_remote_cache__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(527); -function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } @@ -15634,9 +15632,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(222); /* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(220); -function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } @@ -30362,9 +30360,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(220); /* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(343); /* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(407); -function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } @@ -30569,9 +30567,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(read_pkg__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(396); /* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(write_pkg__WEBPACK_IMPORTED_MODULE_1__); -function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } @@ -52694,9 +52692,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(221); /* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(220); /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(341); -function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } @@ -61723,9 +61721,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(340); /* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(420); /* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(559); -function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } @@ -61858,9 +61856,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(408); /* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(340); /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(563); -function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 186f6b337fbde..205d4f4fe61fb 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -22,7 +22,6 @@ export class DocLinksService { // Documentation for `main` branches is still published at a `master` URL. const DOC_LINK_VERSION = kibanaBranch === 'main' ? 'master' : kibanaBranch; const ELASTIC_WEBSITE_URL = 'https://www.elastic.co/'; - const STACK_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/elastic-stack/${DOC_LINK_VERSION}/`; const ELASTICSEARCH_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`; const KIBANA_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/`; const FLEET_DOCS = `${ELASTIC_WEBSITE_URL}guide/en/fleet/${DOC_LINK_VERSION}/`; @@ -41,7 +40,8 @@ export class DocLinksService { settings: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/settings.html`, elasticStackGetStarted: `${STACK_GETTING_STARTED}get-started-elastic-stack.html`, upgrade: { - upgradingElasticStack: `${STACK_DOCS}upgrading-elastic-stack.html`, + upgradingStackOnPrem: `${ELASTIC_WEBSITE_URL}guide/en/elastic-stack/8.0/upgrading-elastic-stack-on-prem.html`, + upgradingStackOnCloud: `${ELASTIC_WEBSITE_URL}guide/en/elastic-stack/8.0/upgrade-elastic-stack-for-elastic-cloud.html`, }, apm: { kibanaSettings: `${KIBANA_DOCS}apm-settings-in-kibana.html`, @@ -239,6 +239,7 @@ export class DocLinksService { asyncSearch: `${ELASTICSEARCH_DOCS}async-search-intro.html`, dataStreams: `${ELASTICSEARCH_DOCS}data-streams.html`, deprecationLogging: `${ELASTICSEARCH_DOCS}logging.html#deprecation-logging`, + hiddenIndices: `${ELASTICSEARCH_DOCS}multi-index.html#hidden`, ilm: `${ELASTICSEARCH_DOCS}index-lifecycle-management.html`, ilmForceMerge: `${ELASTICSEARCH_DOCS}ilm-forcemerge.html`, ilmFreeze: `${ELASTICSEARCH_DOCS}ilm-freeze.html`, @@ -612,7 +613,8 @@ export interface DocLinksStart { readonly settings: string; readonly elasticStackGetStarted: string; readonly upgrade: { - readonly upgradingElasticStack: string; + readonly upgradingStackOnPrem: string; + readonly upgradingStackOnCloud: string; }; readonly apm: { readonly kibanaSettings: string; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index a29b8d0b5cc68..4fb3e90e997d4 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -494,7 +494,8 @@ export interface DocLinksStart { readonly settings: string; readonly elasticStackGetStarted: string; readonly upgrade: { - readonly upgradingElasticStack: string; + readonly upgradingStackOnPrem: string; + readonly upgradingStackOnCloud: string; }; readonly apm: { readonly kibanaSettings: string; diff --git a/src/core/server/elasticsearch/client/client_config.test.ts b/src/core/server/elasticsearch/client/client_config.test.ts index 8158b7d116c4b..cf5a15ab9c19b 100644 --- a/src/core/server/elasticsearch/client/client_config.test.ts +++ b/src/core/server/elasticsearch/client/client_config.test.ts @@ -15,6 +15,7 @@ const createConfig = ( ): ElasticsearchClientConfig => { return { customHeaders: {}, + compression: false, sniffOnStart: false, sniffOnConnectionFault: false, sniffInterval: false, @@ -89,7 +90,7 @@ describe('parseClientOptions', () => { ); }); - describe('`keepAlive option`', () => { + describe('`keepAlive` option', () => { it('`keepAlive` is true', () => { const options = parseClientOptions(createConfig({ keepAlive: true }), false); expect(options.agent).toHaveProperty('keepAlive', true); @@ -106,6 +107,18 @@ describe('parseClientOptions', () => { }); }); + describe('`compression` option', () => { + it('`compression` is true', () => { + const options = parseClientOptions(createConfig({ compression: true }), false); + expect(options.compression).toBe(true); + }); + + it('`compression` is false', () => { + const options = parseClientOptions(createConfig({ compression: false }), false); + expect(options.compression).toBe(false); + }); + }); + it('`sniffOnStart` options', () => { expect( parseClientOptions( diff --git a/src/core/server/elasticsearch/client/client_config.ts b/src/core/server/elasticsearch/client/client_config.ts index 1cb81fd0a417a..8a1eacb78d923 100644 --- a/src/core/server/elasticsearch/client/client_config.ts +++ b/src/core/server/elasticsearch/client/client_config.ts @@ -22,6 +22,7 @@ import { DEFAULT_HEADERS } from '../default_headers'; export type ElasticsearchClientConfig = Pick< ElasticsearchConfig, | 'customHeaders' + | 'compression' | 'sniffOnStart' | 'sniffOnConnectionFault' | 'requestHeadersWhitelist' @@ -63,6 +64,7 @@ export function parseClientOptions( maxSockets: Infinity, keepAlive: config.keepAlive ?? true, }, + compression: config.compression, }; if (config.pingTimeout != null) { diff --git a/src/core/server/elasticsearch/client/cluster_client.test.ts b/src/core/server/elasticsearch/client/cluster_client.test.ts index 2f847f890638a..98ef7e8dfc4a4 100644 --- a/src/core/server/elasticsearch/client/cluster_client.test.ts +++ b/src/core/server/elasticsearch/client/cluster_client.test.ts @@ -26,6 +26,7 @@ const createConfig = ( sniffOnStart: false, sniffOnConnectionFault: false, sniffInterval: false, + compression: false, requestHeadersWhitelist: ['authorization'], customHeaders: {}, hosts: ['http://localhost'], diff --git a/src/core/server/elasticsearch/elasticsearch_config.test.ts b/src/core/server/elasticsearch/elasticsearch_config.test.ts index 17a028b7dd27e..5c6db10e8695a 100644 --- a/src/core/server/elasticsearch/elasticsearch_config.test.ts +++ b/src/core/server/elasticsearch/elasticsearch_config.test.ts @@ -29,6 +29,7 @@ test('set correct defaults', () => { expect(configValue).toMatchInlineSnapshot(` ElasticsearchConfig { "apiVersion": "master", + "compression": false, "customHeaders": Object {}, "healthCheckDelay": "PT2.5S", "hosts": Array [ diff --git a/src/core/server/elasticsearch/elasticsearch_config.ts b/src/core/server/elasticsearch/elasticsearch_config.ts index 74341ddd2c1ad..91b1a1f4475e1 100644 --- a/src/core/server/elasticsearch/elasticsearch_config.ts +++ b/src/core/server/elasticsearch/elasticsearch_config.ts @@ -36,6 +36,7 @@ export const configSchema = schema.object({ hosts: schema.oneOf([hostURISchema, schema.arrayOf(hostURISchema, { minSize: 1 })], { defaultValue: 'http://localhost:9200', }), + compression: schema.boolean({ defaultValue: false }), username: schema.maybe( schema.string({ validate: (rawConfig) => { @@ -297,6 +298,11 @@ export class ElasticsearchConfig { */ public readonly apiVersion: string; + /** + * Whether to use compression for communications with elasticsearch. + */ + public readonly compression: boolean; + /** * Hosts that the client will connect to. If sniffing is enabled, this list will * be used as seeds to discover the rest of your cluster. @@ -399,6 +405,7 @@ export class ElasticsearchConfig { this.password = rawConfig.password; this.serviceAccountToken = rawConfig.serviceAccountToken; this.customHeaders = rawConfig.customHeaders; + this.compression = rawConfig.compression; this.skipStartupConnectionCheck = rawConfig.skipStartupConnectionCheck; const { alwaysPresentCertificate, verificationMode } = rawConfig.ssl; diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 7230d986c1b88..f3eb6566f7a8e 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -232,6 +232,7 @@ export const config: { sniffInterval: Type; sniffOnConnectionFault: Type; hosts: Type; + compression: Type; username: Type; password: Type; serviceAccountToken: Type; @@ -878,7 +879,7 @@ export type ElasticsearchClient = Omit & { +export type ElasticsearchClientConfig = Pick & { pingTimeout?: ElasticsearchConfig['pingTimeout'] | ClientOptions['pingTimeout']; requestTimeout?: ElasticsearchConfig['requestTimeout'] | ClientOptions['requestTimeout']; ssl?: Partial; @@ -890,6 +891,7 @@ export type ElasticsearchClientConfig = Pick> { return { + [DISABLE_BFETCH]: { + name: i18n.translate('bfetch.disableBfetch', { + defaultMessage: 'Disable request batching', + }), + value: false, + description: i18n.translate('bfetch.disableBfetchDesc', { + defaultMessage: + 'Disables requests batching. This increases number of HTTP requests from Kibana, but allows to debug requests individually.', + }), + schema: schema.boolean(), + category: [], + }, [DISABLE_BFETCH_COMPRESSION]: { name: i18n.translate('bfetch.disableBfetchCompression', { - defaultMessage: 'Disable Batch Compression', + defaultMessage: 'Disable batch compression', }), value: false, description: i18n.translate('bfetch.disableBfetchCompressionDesc', { diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/components/chart_split.tsx b/src/plugins/chart_expressions/expression_partition_vis/public/components/chart_split.tsx index 64370828cea41..d6c0081853539 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/components/chart_split.tsx +++ b/src/plugins/chart_expressions/expression_partition_vis/public/components/chart_split.tsx @@ -7,9 +7,9 @@ */ import React from 'react'; -import { Accessor, AccessorFn, GroupBy, GroupBySort, SmallMultiples } from '@elastic/charts'; +import { Accessor, AccessorFn, GroupBy, SmallMultiples } from '@elastic/charts'; +import { Predicate } from '@elastic/charts/dist/common/predicate'; import { DatatableColumn } from '../../../../expressions/public'; -import { SplitDimensionParams } from '../../common/types'; interface ChartSplitProps { splitColumnAccessor?: Accessor | AccessorFn; @@ -20,17 +20,8 @@ interface ChartSplitProps { const CHART_SPLIT_ID = '__pie_chart_split__'; export const SMALL_MULTIPLES_ID = '__pie_chart_sm__'; -export const ChartSplit = ({ - splitColumnAccessor, - splitRowAccessor, - splitDimension, -}: ChartSplitProps) => { +export const ChartSplit = ({ splitColumnAccessor, splitRowAccessor }: ChartSplitProps) => { if (!splitColumnAccessor && !splitRowAccessor) return null; - let sort: GroupBySort = 'alphaDesc'; - if (splitDimension?.meta?.params?.id === 'terms') { - const params = splitDimension?.meta?.sourceParams?.params as SplitDimensionParams; - sort = params?.order === 'asc' ? 'alphaAsc' : 'alphaDesc'; - } return ( <> @@ -45,7 +36,7 @@ export const ChartSplit = ({ } return spec.id; }} - sort={sort} + sort={Predicate.DataIndex} /> { { ' "field": "something"\n' + ' },\n' + ' "facets": {},\n' + - ' "size": 20 \n' + + ' "size": 20\n' + '}', MAPPING, SEARCH_KB, @@ -357,31 +357,18 @@ describe('Integration', () => { autoCompleteSet: ['facets', 'query', 'size'], }, { - name: 'prefix comma, beginning of line', + name: 'prefix comma, end of line', cursor: { lineNumber: 7, column: 1 }, initialValue: '', addTemplate: true, - prefixToAdd: '', + prefixToAdd: ',\n', suffixToAdd: '', rangeToReplace: { - start: { lineNumber: 7, column: 1 }, + start: { lineNumber: 6, column: 14 }, end: { lineNumber: 7, column: 1 }, }, autoCompleteSet: ['facets', 'query', 'size'], }, - { - name: 'prefix comma, end of line', - cursor: { lineNumber: 6, column: 15 }, - initialValue: '', - addTemplate: true, - prefixToAdd: '', - suffixToAdd: '', - rangeToReplace: { - start: { lineNumber: 6, column: 15 }, - end: { lineNumber: 6, column: 15 }, - }, - autoCompleteSet: ['facets', 'query', 'size'], - }, ] ); diff --git a/src/plugins/console/public/lib/autocomplete/autocomplete.ts b/src/plugins/console/public/lib/autocomplete/autocomplete.ts index 43fdde3f02349..63d43a849a681 100644 --- a/src/plugins/console/public/lib/autocomplete/autocomplete.ts +++ b/src/plugins/console/public/lib/autocomplete/autocomplete.ts @@ -335,6 +335,20 @@ export default function ({ }); } + function replaceLinesWithPrefixPieces(prefixPieces: string[], startLineNumber: number) { + const middlePiecesCount = prefixPieces.length - 1; + prefixPieces.forEach((piece, index) => { + if (index >= middlePiecesCount) { + return; + } + const line = startLineNumber + index + 1; + const column = editor.getLineValue(line).length - 1; + const start = { lineNumber: line, column: 0 }; + const end = { lineNumber: line, column }; + editor.replace({ start, end }, piece); + }); + } + function applyTerm(term: { value?: string; context?: AutoCompleteContext; @@ -390,12 +404,36 @@ export default function ({ templateInserted = false; } } + const linesToMoveDown = (context.prefixToAdd ?? '').match(/\n|\r/g)?.length ?? 0; - valueToInsert = context.prefixToAdd + valueToInsert + context.suffixToAdd; + let prefix = context.prefixToAdd ?? ''; // disable listening to the changes we are making. editor.off('changeSelection', editorChangeListener); + // if should add chars on the previous not empty line + if (linesToMoveDown) { + const [firstPart = '', ...prefixPieces] = context.prefixToAdd?.split(/\n|\r/g) ?? []; + const lastPart = _.last(prefixPieces) ?? ''; + const { start } = context.rangeToReplace!; + const end = { ...start, column: start.column + firstPart.length }; + + // adding only the content of prefix before newlines + editor.replace({ start, end }, firstPart); + + // replacing prefix pieces without the last one, which is handled separately + if (prefixPieces.length - 1 > 0) { + replaceLinesWithPrefixPieces(prefixPieces, start.lineNumber); + } + + // and the last prefix line, keeping the editor's own newlines. + prefix = lastPart; + context.rangeToReplace!.start.lineNumber = context.rangeToReplace!.end.lineNumber; + context.rangeToReplace!.start.column = 0; + } + + valueToInsert = prefix + valueToInsert + context.suffixToAdd; + if (context.rangeToReplace!.start.column !== context.rangeToReplace!.end.column) { editor.replace(context.rangeToReplace!, valueToInsert); } else { @@ -410,7 +448,7 @@ export default function ({ column: context.rangeToReplace!.start.column + termAsString.length + - context.prefixToAdd!.length + + prefix.length + (templateInserted ? 0 : context.suffixToAdd!.length), }; @@ -671,6 +709,47 @@ export default function ({ } } + function addCommaToPrefixOnAutocomplete( + nonEmptyToken: Token | null, + context: AutoCompleteContext, + charsToSkipOnSameLine: number = 1 + ) { + if (nonEmptyToken && nonEmptyToken.type.indexOf('url') < 0) { + const { position } = nonEmptyToken; + // if not on the first line + if (context.rangeToReplace && context.rangeToReplace.start?.lineNumber > 1) { + const prevTokenLineNumber = position.lineNumber; + const line = context.editor?.getLineValue(prevTokenLineNumber) ?? ''; + const prevLineLength = line.length; + const linesToEnter = context.rangeToReplace.end.lineNumber - prevTokenLineNumber; + + const isTheSameLine = linesToEnter === 0; + let startColumn = prevLineLength + 1; + let spaces = context.rangeToReplace.start.column - 1; + + if (isTheSameLine) { + // prevent last char line from replacing + startColumn = position.column + charsToSkipOnSameLine; + // one char for pasted " and one for , + spaces = context.rangeToReplace.end.column - startColumn - 2; + } + + // go back to the end of the previous line + context.rangeToReplace = { + start: { lineNumber: prevTokenLineNumber, column: startColumn }, + end: { ...context.rangeToReplace.end }, + }; + + spaces = spaces >= 0 ? spaces : 0; + const spacesToEnter = isTheSameLine ? (spaces === 0 ? 1 : spaces) : spaces; + const newLineChars = `\n`.repeat(linesToEnter >= 0 ? linesToEnter : 0); + const whitespaceChars = ' '.repeat(spacesToEnter); + // add a comma at the end of the previous line, a new line and indentation + context.prefixToAdd = `,${newLineChars}${whitespaceChars}`; + } + } + } + function addBodyPrefixSuffixToContext(context: AutoCompleteContext) { // Figure out what happens next to the token to see whether it needs trailing commas etc. @@ -758,23 +837,19 @@ export default function ({ case 'paren.lparen': case 'punctuation.comma': case 'punctuation.colon': + case 'punctuation.start_triple_quote': case 'method': break; + case 'text': + case 'string': + case 'constant.numeric': + case 'constant.language.boolean': + case 'punctuation.end_triple_quote': + addCommaToPrefixOnAutocomplete(nonEmptyToken, context, nonEmptyToken?.value.length); + break; default: - if (nonEmptyToken && nonEmptyToken.type.indexOf('url') < 0) { - const { position, value } = nonEmptyToken; - - // We can not rely on prefixToAdd here, because it adds a comma at the beginning of the new token - // Since we have access to the position of the previous token here, this could be a good place to insert a comma manually - context.prefixToAdd = ''; - editor.insert( - { - column: position.column + value.length, - lineNumber: position.lineNumber, - }, - ', ' - ); - } + addCommaToPrefixOnAutocomplete(nonEmptyToken, context); + break; } return context; diff --git a/src/plugins/data/common/exports/escape_value.ts b/src/plugins/data/common/exports/escape_value.ts index 9277f792a4b86..393ce6043993a 100644 --- a/src/plugins/data/common/exports/escape_value.ts +++ b/src/plugins/data/common/exports/escape_value.ts @@ -10,6 +10,17 @@ import { cellHasFormulas } from './formula_checks'; type RawValue = string | object | null | undefined; +/** + * Create a function that will escape CSV values like "=", "@" and "+" with a + * "'". This will also place CSV values in "" if contain non-alphanumeric chars. + * + * For example: + * + * Given: =1+1 + * Returns: "'=1+1" + * + * See OWASP: https://www.owasp.org/index.php/CSV_Injection. + */ export function createEscapeValue( quoteValues: boolean, escapeFormulas: boolean diff --git a/src/plugins/data/public/search/search_interceptor/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor/search_interceptor.ts index 8c7bfe68fd54b..7dc1ce6dee078 100644 --- a/src/plugins/data/public/search/search_interceptor/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor/search_interceptor.ts @@ -21,9 +21,15 @@ import { tap, } from 'rxjs/operators'; import { PublicMethodsOf } from '@kbn/utility-types'; -import { CoreSetup, CoreStart, ThemeServiceSetup, ToastsSetup } from 'kibana/public'; +import { + CoreSetup, + CoreStart, + IHttpFetchError, + ThemeServiceSetup, + ToastsSetup, +} from 'kibana/public'; import { i18n } from '@kbn/i18n'; -import { BatchedFunc, BfetchPublicSetup } from 'src/plugins/bfetch/public'; +import { BatchedFunc, BfetchPublicSetup, DISABLE_BFETCH } from '../../../../bfetch/public'; import { ENHANCED_ES_SEARCH_STRATEGY, IAsyncSearchOptions, @@ -67,8 +73,9 @@ const MAX_CACHE_ITEMS = 50; const MAX_CACHE_SIZE_MB = 10; export class SearchInterceptor { - private uiSettingsSub: Subscription; + private uiSettingsSubs: Subscription[] = []; private searchTimeout: number; + private bFetchDisabled: boolean; private readonly responseCache: SearchResponseCache = new SearchResponseCache( MAX_CACHE_ITEMS, MAX_CACHE_SIZE_MB @@ -106,17 +113,21 @@ export class SearchInterceptor { }); this.searchTimeout = deps.uiSettings.get(UI_SETTINGS.SEARCH_TIMEOUT); + this.bFetchDisabled = deps.uiSettings.get(DISABLE_BFETCH); - this.uiSettingsSub = deps.uiSettings - .get$(UI_SETTINGS.SEARCH_TIMEOUT) - .subscribe((timeout: number) => { + this.uiSettingsSubs.push( + deps.uiSettings.get$(UI_SETTINGS.SEARCH_TIMEOUT).subscribe((timeout: number) => { this.searchTimeout = timeout; - }); + }), + deps.uiSettings.get$(DISABLE_BFETCH).subscribe((bFetchDisabled: boolean) => { + this.bFetchDisabled = bFetchDisabled; + }) + ); } public stop() { this.responseCache.clear(); - this.uiSettingsSub.unsubscribe(); + this.uiSettingsSubs.forEach((s) => s.unsubscribe()); } /* @@ -266,13 +277,34 @@ export class SearchInterceptor { options?: ISearchOptions ): Promise { const { abortSignal } = options || {}; - return this.batchedFetch( - { - request, - options: this.getSerializableOptions(options), - }, - abortSignal - ); + + if (this.bFetchDisabled) { + const { executionContext, strategy, ...searchOptions } = this.getSerializableOptions(options); + return this.deps.http + .post(`/internal/search/${strategy}${request.id ? `/${request.id}` : ''}`, { + signal: abortSignal, + context: executionContext, + body: JSON.stringify({ + ...request, + ...searchOptions, + }), + }) + .catch((e: IHttpFetchError) => { + if (e?.body) { + throw e.body; + } else { + throw e; + } + }) as Promise; + } else { + return this.batchedFetch( + { + request, + options: this.getSerializableOptions(options), + }, + abortSignal + ); + } } /** @@ -319,9 +351,12 @@ export class SearchInterceptor { */ public search({ id, ...request }: IKibanaSearchRequest, options: IAsyncSearchOptions = {}) { const searchOptions = { - strategy: ENHANCED_ES_SEARCH_STRATEGY, ...options, }; + if (!searchOptions.strategy) { + searchOptions.strategy = ENHANCED_ES_SEARCH_STRATEGY; + } + const { sessionId, abortSignal } = searchOptions; return this.createRequestHash$(request, searchOptions).pipe( diff --git a/src/plugins/discover/kibana.json b/src/plugins/discover/kibana.json index d0ff54290256e..015cb6ddaf285 100644 --- a/src/plugins/discover/kibana.json +++ b/src/plugins/discover/kibana.json @@ -13,7 +13,8 @@ "navigation", "uiActions", "savedObjects", - "dataViewFieldEditor" + "dataViewFieldEditor", + "dataViewEditor" ], "optionalPlugins": ["home", "share", "usageCollection", "spaces"], "requiredBundles": ["kibanaUtils", "home", "kibanaReact", "dataViews"], diff --git a/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx b/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx index b57c28355626f..f426aeed9cab8 100644 --- a/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx +++ b/src/plugins/discover/public/application/main/components/field_stats_table/field_stats_table.tsx @@ -21,7 +21,7 @@ import { import { FIELD_STATISTICS_LOADED } from './constants'; import type { SavedSearch } from '../../../../services/saved_searches'; import type { GetStateReturn } from '../../services/discover_state'; -import { DataRefetch$ } from '../../utils/use_saved_search'; +import { AvailableFields$, DataRefetch$ } from '../../utils/use_saved_search'; export interface DataVisualizerGridEmbeddableInput extends EmbeddableInput { indexPattern: DataView; @@ -35,6 +35,7 @@ export interface DataVisualizerGridEmbeddableInput extends EmbeddableInput { */ onAddFilter?: (field: DataViewField | string, value: string, type: '+' | '-') => void; sessionId?: string; + fieldsToFetch?: string[]; } export interface DataVisualizerGridEmbeddableOutput extends EmbeddableOutput { showDistributions?: boolean; @@ -84,11 +85,13 @@ export interface FieldStatisticsTableProps { */ trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void; savedSearchRefetch$?: DataRefetch$; + availableFields$?: AvailableFields$; searchSessionId?: string; } export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { const { + availableFields$, indexPattern, savedSearch, query, @@ -126,11 +129,19 @@ export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { embeddable.updateInput({ lastReloadRequestTime: Date.now() }); } }); + + const fields = availableFields$?.subscribe(() => { + if (embeddable && !isErrorEmbeddable(embeddable) && !availableFields$?.getValue().error) { + embeddable.updateInput({ fieldsToFetch: availableFields$?.getValue().fields }); + } + }); + return () => { sub?.unsubscribe(); refetch?.unsubscribe(); + fields?.unsubscribe(); }; - }, [embeddable, stateContainer, savedSearchRefetch$]); + }, [embeddable, stateContainer, savedSearchRefetch$, availableFields$]); useEffect(() => { if (embeddable && !isErrorEmbeddable(embeddable)) { @@ -143,6 +154,7 @@ export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { visibleFieldNames: columns, onAddFilter, sessionId: searchSessionId, + fieldsToFetch: availableFields$?.getValue().fields, }); embeddable.reload(); } @@ -155,6 +167,7 @@ export const FieldStatisticsTable = (props: FieldStatisticsTableProps) => { filters, onAddFilter, searchSessionId, + availableFields$, ]); useEffect(() => { diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx index b258987e3ea30..0791f98280268 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx @@ -21,6 +21,7 @@ import { indexPatternWithTimefieldMock } from '../../../../__mocks__/index_patte import { GetStateReturn } from '../../services/discover_state'; import { DiscoverLayoutProps } from './types'; import { + AvailableFields$, DataCharts$, DataDocuments$, DataMain$, @@ -72,6 +73,11 @@ function mountComponent(indexPattern: DataView, prevSidebarClosed?: boolean) { result: esHits as ElasticSearchHit[], }) as DataDocuments$; + const availableFields$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + fields: [] as string[], + }) as AvailableFields$; + const totalHits$ = new BehaviorSubject({ fetchStatus: FetchStatus.COMPLETE, result: Number(esHits.length), @@ -131,6 +137,7 @@ function mountComponent(indexPattern: DataView, prevSidebarClosed?: boolean) { documents$, totalHits$, charts$, + availableFields$, }; const props = { diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx index 5601596a4d73b..9a930f247a5ac 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx @@ -48,7 +48,7 @@ import { import { FieldStatisticsTable } from '../field_stats_table'; import { VIEW_MODE } from '../../../../components/view_mode_toggle'; import { DOCUMENTS_VIEW_CLICK, FIELD_STATISTICS_VIEW_CLICK } from '../field_stats_table/constants'; -import { DataViewType } from '../../../../../../data_views/common'; +import { DataViewType, DataView } from '../../../../../../data_views/common'; /** * Local storage key for sidebar persistence state @@ -204,6 +204,14 @@ export function DiscoverLayout({ }, [isSidebarClosed, storage]); const contentCentered = resultState === 'uninitialized' || resultState === 'none'; + const onDataViewCreated = useCallback( + (dataView: DataView) => { + if (dataView.id) { + onChangeIndexPattern(dataView.id); + } + }, + [onChangeIndexPattern] + ); return ( @@ -245,6 +253,8 @@ export function DiscoverLayout({ useNewFieldsApi={useNewFieldsApi} onEditRuntimeField={onEditRuntimeField} viewMode={viewMode} + onDataViewCreated={onDataViewCreated} + availableFields$={savedSearchData$.availableFields$} /> @@ -330,6 +340,7 @@ export function DiscoverLayout({ /> ) : (
{ const indexPattern = stubLogstashIndexPattern; const editField = jest.fn(); + const createNewDataView = jest.fn(); const mountComponent = () => { return mountWithIntl( @@ -62,6 +63,7 @@ describe('Discover DataView Management', () => { editField={editField} selectedIndexPattern={indexPattern} useNewFieldsApi={true} + createNewDataView={createNewDataView} /> ); @@ -81,7 +83,7 @@ describe('Discover DataView Management', () => { button.simulate('click'); expect(component.find(EuiContextMenuPanel).length).toBe(1); - expect(component.find(EuiContextMenuItem).length).toBe(2); + expect(component.find(EuiContextMenuItem).length).toBe(3); }); test('click on an add button executes editField callback', () => { @@ -103,4 +105,14 @@ describe('Discover DataView Management', () => { manageButton.simulate('click'); expect(mockServices.core.application.navigateToApp).toHaveBeenCalled(); }); + + test('click on add dataView button executes createNewDataView callback', () => { + const component = mountComponent(); + const button = findTestSubject(component, 'discoverIndexPatternActions'); + button.simulate('click'); + + const manageButton = findTestSubject(component, 'dataview-create-new'); + manageButton.simulate('click'); + expect(createNewDataView).toHaveBeenCalled(); + }); }); diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_index_pattern_management.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_index_pattern_management.tsx index 0655357d55983..b62e6e15c55af 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_index_pattern_management.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_index_pattern_management.tsx @@ -7,7 +7,13 @@ */ import React, { useState } from 'react'; -import { EuiButtonIcon, EuiContextMenuItem, EuiContextMenuPanel, EuiPopover } from '@elastic/eui'; +import { + EuiButtonIcon, + EuiContextMenuItem, + EuiContextMenuPanel, + EuiHorizontalRule, + EuiPopover, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useDiscoverServices } from '../../../../utils/use_discover_services'; import { DataView } from '../../../../../../data/common'; @@ -26,11 +32,16 @@ export interface DiscoverIndexPatternManagementProps { * @param fieldName */ editField: (fieldName?: string) => void; + + /** + * Callback to execute on create new data action + */ + createNewDataView: () => void; } export function DiscoverIndexPatternManagement(props: DiscoverIndexPatternManagementProps) { const { dataViewFieldEditor, core } = useDiscoverServices(); - const { useNewFieldsApi, selectedIndexPattern, editField } = props; + const { useNewFieldsApi, selectedIndexPattern, editField, createNewDataView } = props; const dataViewEditPermission = dataViewFieldEditor?.userPermissions.editIndexPattern(); const canEditDataViewField = !!dataViewEditPermission && useNewFieldsApi; const [isAddIndexPatternFieldPopoverOpen, setIsAddIndexPatternFieldPopoverOpen] = useState(false); @@ -45,7 +56,7 @@ export function DiscoverIndexPatternManagement(props: DiscoverIndexPatternManage return ( { setIsAddIndexPatternFieldPopoverOpen(false); @@ -67,7 +78,8 @@ export function DiscoverIndexPatternManagement(props: DiscoverIndexPatternManage } > {i18n.translate('discover.fieldChooser.indexPatterns.addFieldButton', { - defaultMessage: 'Add field to data view', + defaultMessage: 'Add field', })} , {i18n.translate('discover.fieldChooser.indexPatterns.manageFieldButton', { - defaultMessage: 'Manage data view fields', + defaultMessage: 'Manage settings', + })} + , + , + { + setIsAddIndexPatternFieldPopoverOpen(false); + createNewDataView(); + }} + > + {i18n.translate('discover.fieldChooser.dataViews.createNewDataView', { + defaultMessage: 'Create new data view', })} , ]} diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx index e236d7e8a1b89..b6dbf40cc7b3d 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx @@ -24,6 +24,9 @@ import { stubLogstashIndexPattern } from '../../../../../../data/common/stubs'; import { VIEW_MODE } from '../../../../components/view_mode_toggle'; import { ElasticSearchHit } from '../../../../types'; import { KibanaContextProvider } from '../../../../../../kibana_react/public'; +import { BehaviorSubject } from 'rxjs'; +import { FetchStatus } from '../../../types'; +import { AvailableFields$ } from '../../utils/use_saved_search'; function getCompProps(): DiscoverSidebarProps { const indexPattern = stubLogstashIndexPattern; @@ -46,6 +49,11 @@ function getCompProps(): DiscoverSidebarProps { fieldCounts[key] = (fieldCounts[key] || 0) + 1; } } + const availableFields$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + fields: [] as string[], + }) as AvailableFields$; + return { columns: ['extension'], fieldCounts, @@ -63,6 +71,9 @@ function getCompProps(): DiscoverSidebarProps { onEditRuntimeField: jest.fn(), editField: jest.fn(), viewMode: VIEW_MODE.DOCUMENT_LEVEL, + createNewDataView: jest.fn(), + onDataViewCreated: jest.fn(), + availableFields$, }; } diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx index 087a5a6ae312b..6569348f99038 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx @@ -69,6 +69,8 @@ export interface DiscoverSidebarProps extends Omit void; + createNewDataView: () => void; + /** * a statistics of the distribution of fields in the given hits */ @@ -104,6 +106,7 @@ export function DiscoverSidebarComponent({ closeFlyout, editField, viewMode, + createNewDataView, }: DiscoverSidebarProps) { const { uiSettings, dataViewFieldEditor } = useDiscoverServices(); const [fields, setFields] = useState(null); @@ -299,6 +302,7 @@ export function DiscoverSidebarComponent({ selectedIndexPattern={selectedIndexPattern} editField={editField} useNewFieldsApi={useNewFieldsApi} + createNewDataView={createNewDataView} /> @@ -336,6 +340,7 @@ export function DiscoverSidebarComponent({ selectedIndexPattern={selectedIndexPattern} useNewFieldsApi={useNewFieldsApi} editField={editField} + createNewDataView={createNewDataView} /> diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx index 1915f6707f94d..eee09f4ef481e 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx @@ -23,7 +23,7 @@ import { } from './discover_sidebar_responsive'; import { DiscoverServices } from '../../../../build_services'; import { FetchStatus } from '../../../types'; -import { DataDocuments$ } from '../../utils/use_saved_search'; +import { AvailableFields$, DataDocuments$ } from '../../utils/use_saved_search'; import { stubLogstashIndexPattern } from '../../../../../../data/common/stubs'; import { VIEW_MODE } from '../../../../components/view_mode_toggle'; import { ElasticSearchHit } from '../../../../types'; @@ -88,12 +88,17 @@ function getCompProps(): DiscoverSidebarResponsiveProps { mockfieldCounts[key] = (mockfieldCounts[key] || 0) + 1; } } + return { columns: ['extension'], documents$: new BehaviorSubject({ fetchStatus: FetchStatus.COMPLETE, result: hits as ElasticSearchHit[], }) as DataDocuments$, + availableFields$: new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + fields: [] as string[], + }) as AvailableFields$, indexPatternList, onChangeIndexPattern: jest.fn(), onAddFilter: jest.fn(), @@ -104,6 +109,7 @@ function getCompProps(): DiscoverSidebarResponsiveProps { trackUiMetric: jest.fn(), onEditRuntimeField: jest.fn(), viewMode: VIEW_MODE.DOCUMENT_LEVEL, + onDataViewCreated: jest.fn(), }; } diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx index abc59ff282863..ce23e0a8e18f8 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx @@ -34,9 +34,10 @@ import { getDefaultFieldFilter } from './lib/field_filter'; import { DiscoverSidebar } from './discover_sidebar'; import { AppState } from '../../services/discover_state'; import { DiscoverIndexPatternManagement } from './discover_index_pattern_management'; -import { DataDocuments$ } from '../../utils/use_saved_search'; +import { AvailableFields$, DataDocuments$ } from '../../utils/use_saved_search'; import { calcFieldCounts } from '../../utils/calc_field_counts'; import { VIEW_MODE } from '../../../../components/view_mode_toggle'; +import { FetchStatus } from '../../../types'; export interface DiscoverSidebarResponsiveProps { /** @@ -102,10 +103,18 @@ export interface DiscoverSidebarResponsiveProps { * callback to execute on edit runtime field */ onEditRuntimeField: () => void; + /** + * callback to execute on create dataview + */ + onDataViewCreated: (dataView: DataView) => void; /** * Discover view mode */ viewMode: VIEW_MODE; + /** + * list of available fields fetched from ES + */ + availableFields$: AvailableFields$; } /** @@ -115,7 +124,13 @@ export interface DiscoverSidebarResponsiveProps { */ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) { const services = useDiscoverServices(); - const { selectedIndexPattern, onEditRuntimeField, useNewFieldsApi, onChangeIndexPattern } = props; + const { + selectedIndexPattern, + onEditRuntimeField, + useNewFieldsApi, + onChangeIndexPattern, + onDataViewCreated, + } = props; const [fieldFilter, setFieldFilter] = useState(getDefaultFieldFilter()); const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); /** @@ -146,12 +161,16 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) }, [selectedIndexPattern]); const closeFieldEditor = useRef<() => void | undefined>(); + const closeDataViewEditor = useRef<() => void | undefined>(); useEffect(() => { const cleanup = () => { if (closeFieldEditor?.current) { closeFieldEditor?.current(); } + if (closeDataViewEditor?.current) { + closeDataViewEditor?.current(); + } }; return () => { // Make sure to close the editor when unmounting @@ -163,11 +182,41 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) closeFieldEditor.current = ref; }, []); + const setDataViewEditorRef = useCallback((ref: () => void | undefined) => { + closeDataViewEditor.current = ref; + }, []); + const closeFlyout = useCallback(() => { setIsFlyoutVisible(false); }, []); - const { dataViewFieldEditor } = services; + const { dataViewFieldEditor, dataViewEditor } = services; + const { availableFields$ } = props; + + useEffect( + () => { + // For an external embeddable like the Field stats + // it is useful to know what fields are populated in the docs fetched + // or what fields are selected by the user + + const fieldCnts = fieldCounts.current ?? {}; + + const availableFields = props.columns.length > 0 ? props.columns : Object.keys(fieldCnts); + availableFields$.next({ + fetchStatus: FetchStatus.COMPLETE, + fields: availableFields, + }); + }, + // Using columns.length here instead of columns to avoid array reference changing + // eslint-disable-next-line react-hooks/exhaustive-deps + [ + selectedIndexPattern, + availableFields$, + fieldCounts.current, + documentState.result, + props.columns.length, + ] + ); const editField = useCallback( (fieldName?: string) => { @@ -203,6 +252,24 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) ] ); + const createNewDataView = useCallback(() => { + const indexPatternFieldEditPermission = dataViewEditor.userPermissions.editDataView; + if (!indexPatternFieldEditPermission) { + return; + } + const ref = dataViewEditor.openEditor({ + onSave: async (dataView) => { + onDataViewCreated(dataView); + }, + }); + if (setDataViewEditorRef) { + setDataViewEditorRef(ref); + } + if (closeFlyout) { + closeFlyout(); + } + }, [dataViewEditor, setDataViewEditorRef, closeFlyout, onDataViewCreated]); + if (!selectedIndexPattern) { return null; } @@ -218,6 +285,7 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) fieldCounts={fieldCounts.current} setFieldFilter={setFieldFilter} editField={editField} + createNewDataView={createNewDataView} /> )} @@ -244,6 +312,7 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) selectedIndexPattern={selectedIndexPattern} editField={editField} useNewFieldsApi={useNewFieldsApi} + createNewDataView={createNewDataView} /> @@ -307,6 +376,7 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) setFieldEditorRef={setFieldEditorRef} closeFlyout={closeFlyout} editField={editField} + createNewDataView={createNewDataView} />
diff --git a/src/plugins/discover/public/application/main/components/sidebar/lib/group_fields.tsx b/src/plugins/discover/public/application/main/components/sidebar/lib/group_fields.tsx index e06ab4716c0af..41fd49bf92ec5 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/lib/group_fields.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/lib/group_fields.tsx @@ -54,6 +54,7 @@ export function groupFields( if (!isFieldFiltered(field, fieldFilterState, fieldCounts)) { continue; } + const subTypeMulti = getFieldSubtypeMulti(field?.spec); const isSubfield = useNewFieldsApi && subTypeMulti; if (columns.includes(field.name)) { diff --git a/src/plugins/discover/public/application/main/utils/fetch_all.test.ts b/src/plugins/discover/public/application/main/utils/fetch_all.test.ts index 1ea9ec0bb3582..8ac965838c166 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_all.test.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_all.test.ts @@ -16,6 +16,7 @@ import { AppState } from '../services/discover_state'; import { discoverServiceMock } from '../../../__mocks__/services'; import { fetchAll } from './fetch_all'; import { + DataAvailableFieldsMsg, DataChartsMessage, DataDocumentsMsg, DataMainMsg, @@ -64,6 +65,9 @@ describe('test fetchAll', () => { documents$: new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED }), totalHits$: new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED }), charts$: new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED }), + availableFields$: new BehaviorSubject({ + fetchStatus: FetchStatus.UNINITIALIZED, + }), }; deps = { appStateContainer: { diff --git a/src/plugins/discover/public/application/main/utils/use_saved_search.ts b/src/plugins/discover/public/application/main/utils/use_saved_search.ts index dadf4dec76452..ee44ac13e90b2 100644 --- a/src/plugins/discover/public/application/main/utils/use_saved_search.ts +++ b/src/plugins/discover/public/application/main/utils/use_saved_search.ts @@ -30,6 +30,7 @@ export interface SavedSearchData { documents$: DataDocuments$; totalHits$: DataTotalHits$; charts$: DataCharts$; + availableFields$: AvailableFields$; } export interface TimechartBucketInterval { @@ -42,6 +43,7 @@ export type DataMain$ = BehaviorSubject; export type DataDocuments$ = BehaviorSubject; export type DataTotalHits$ = BehaviorSubject; export type DataCharts$ = BehaviorSubject; +export type AvailableFields$ = BehaviorSubject; export type DataRefetch$ = Subject; @@ -78,6 +80,10 @@ export interface DataChartsMessage extends DataMsg { chartData?: Chart; } +export interface DataAvailableFieldsMsg extends DataMsg { + fields?: string[]; +} + /** * This hook return 2 observables, refetch$ allows to trigger data fetching, data$ to subscribe * to the data fetching @@ -116,14 +122,19 @@ export const useSavedSearch = ({ const charts$: DataCharts$ = useBehaviorSubject({ fetchStatus: initialFetchStatus }); + const availableFields$: AvailableFields$ = useBehaviorSubject({ + fetchStatus: initialFetchStatus, + }); + const dataSubjects = useMemo(() => { return { main$, documents$, totalHits$, charts$, + availableFields$, }; - }, [main$, charts$, documents$, totalHits$]); + }, [main$, charts$, documents$, totalHits$, availableFields$]); /** * The observable to trigger data fetching in UI diff --git a/src/plugins/discover/public/build_services.ts b/src/plugins/discover/public/build_services.ts index 393893432538b..f6492db6e8a42 100644 --- a/src/plugins/discover/public/build_services.ts +++ b/src/plugins/discover/public/build_services.ts @@ -40,6 +40,7 @@ import { FieldFormatsStart } from '../../field_formats/public'; import { EmbeddableStart } from '../../embeddable/public'; import type { SpacesApi } from '../../../../x-pack/plugins/spaces/public'; +import { DataViewEditorStart } from '../../../plugins/data_view_editor/public'; export interface HistoryLocationState { referrer: string; @@ -68,6 +69,7 @@ export interface DiscoverServices { uiSettings: IUiSettingsClient; trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void; dataViewFieldEditor: IndexPatternFieldEditorStart; + dataViewEditor: DataViewEditorStart; http: HttpStart; storage: Storage; spaces?: SpacesApi; @@ -109,5 +111,6 @@ export const buildServices = memoize(function ( dataViewFieldEditor: plugins.dataViewFieldEditor, http: core.http, spaces: plugins.spaces, + dataViewEditor: plugins.dataViewEditor, }; }); diff --git a/src/plugins/discover/public/plugin.tsx b/src/plugins/discover/public/plugin.tsx index 43c03a59b5b25..e55158b0dad5e 100644 --- a/src/plugins/discover/public/plugin.tsx +++ b/src/plugins/discover/public/plugin.tsx @@ -62,6 +62,7 @@ import type { SpacesPluginStart } from '../../../../x-pack/plugins/spaces/public import { FieldFormatsStart } from '../../field_formats/public'; import { injectTruncateStyles } from './utils/truncate_styles'; import { DOC_TABLE_LEGACY, TRUNCATE_MAX_HEIGHT } from '../common'; +import { DataViewEditorStart } from '../../../plugins/data_view_editor/public'; import { useDiscoverServices } from './utils/use_discover_services'; declare module '../../share/public' { @@ -176,6 +177,7 @@ export interface DiscoverSetupPlugins { * @internal */ export interface DiscoverStartPlugins { + dataViewEditor: DataViewEditorStart; uiActions: UiActionsStart; embeddable: EmbeddableStart; navigation: NavigationStart; diff --git a/src/plugins/discover/server/ui_settings.ts b/src/plugins/discover/server/ui_settings.ts index 45df73aca9022..be82d6cfb9760 100644 --- a/src/plugins/discover/server/ui_settings.ts +++ b/src/plugins/discover/server/ui_settings.ts @@ -211,7 +211,7 @@ export const getUiSettings: () => Record = () => ({ description: i18n.translate( 'discover.advancedSettings.discover.showFieldStatisticsDescription', { - defaultMessage: `Enable {fieldStatisticsDocs} in Discover to explore the fields in your data. This functionality is in beta and is subject to change. `, + defaultMessage: `Enable the {fieldStatisticsDocs} to show details such as the minimum and maximum values of a numeric field or a map of a geo field. This functionality is in beta and is subject to change.`, values: { fieldStatisticsDocs: ` Record = () => ({ }, } ), - value: false, + value: true, category: ['discover'], schema: schema.boolean(), metric: { diff --git a/src/plugins/discover/tsconfig.json b/src/plugins/discover/tsconfig.json index 4ff6f0598d7d8..6dad573a272fb 100644 --- a/src/plugins/discover/tsconfig.json +++ b/src/plugins/discover/tsconfig.json @@ -25,6 +25,7 @@ { "path": "../data_view_field_editor/tsconfig.json"}, { "path": "../field_formats/tsconfig.json" }, { "path": "../data_views/tsconfig.json" }, - { "path": "../../../x-pack/plugins/spaces/tsconfig.json" } + { "path": "../../../x-pack/plugins/spaces/tsconfig.json" }, + { "path": "../data_view_editor/tsconfig.json" } ] } diff --git a/src/plugins/home/kibana.json b/src/plugins/home/kibana.json index 3f1916f3142ff..d8c09ab5e80c6 100644 --- a/src/plugins/home/kibana.json +++ b/src/plugins/home/kibana.json @@ -7,7 +7,7 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": ["data", "share", "urlForwarding"], + "requiredPlugins": ["dataViews", "share", "urlForwarding"], "optionalPlugins": ["usageCollection", "telemetry", "customIntegrations"], "requiredBundles": ["kibanaReact"] } diff --git a/src/plugins/home/public/application/components/home_app.js b/src/plugins/home/public/application/components/home_app.js index ef8b80b18f9bf..62df479ecbfdf 100644 --- a/src/plugins/home/public/application/components/home_app.js +++ b/src/plugins/home/public/application/components/home_app.js @@ -27,7 +27,7 @@ export function HomeApp({ directories, solutions }) { addBasePath, environmentService, telemetry, - indexPatternService, + dataViewsService, } = getServices(); const environment = environmentService.getEnvironment(); const isCloudEnabled = environment.cloud; @@ -76,7 +76,7 @@ export function HomeApp({ directories, solutions }) { localStorage={localStorage} urlBasePath={getBasePath()} telemetry={telemetry} - hasUserDataView={() => indexPatternService.hasUserDataView()} + hasUserDataView={() => dataViewsService.hasUserDataView()} /> diff --git a/src/plugins/home/public/application/kibana_services.ts b/src/plugins/home/public/application/kibana_services.ts index 8a2fbaea39ca1..fdd325df96ac5 100644 --- a/src/plugins/home/public/application/kibana_services.ts +++ b/src/plugins/home/public/application/kibana_services.ts @@ -19,6 +19,7 @@ import { import { UiCounterMetricType } from '@kbn/analytics'; import { TelemetryPluginStart } from '../../../telemetry/public'; import { UrlForwardingStart } from '../../../url_forwarding/public'; +import { DataViewsContract } from '../../../data_views/public'; import { TutorialService } from '../services/tutorials'; import { AddDataService } from '../services/add_data'; import { FeatureCatalogueRegistry } from '../services/feature_catalogue'; @@ -27,7 +28,7 @@ import { ConfigSchema } from '../../config'; import { SharePluginSetup } from '../../../share/public'; export interface HomeKibanaServices { - indexPatternService: any; + dataViewsService: DataViewsContract; kibanaVersion: string; share: SharePluginSetup; chrome: ChromeStart; diff --git a/src/plugins/home/public/application/sample_data_client.js b/src/plugins/home/public/application/sample_data_client.ts similarity index 83% rename from src/plugins/home/public/application/sample_data_client.js rename to src/plugins/home/public/application/sample_data_client.ts index c074c1fc71cdd..6783f7440fefb 100644 --- a/src/plugins/home/public/application/sample_data_client.js +++ b/src/plugins/home/public/application/sample_data_client.ts @@ -11,14 +11,14 @@ import { getServices } from './kibana_services'; const sampleDataUrl = '/api/sample_data'; function clearIndexPatternsCache() { - getServices().indexPatternService.clearCache(); + getServices().dataViewsService.clearCache(); } export async function listSampleDataSets() { return await getServices().http.get(sampleDataUrl); } -export async function installSampleDataSet(id, sampleDataDefaultIndex) { +export async function installSampleDataSet(id: string, sampleDataDefaultIndex: string) { await getServices().http.post(`${sampleDataUrl}/${id}`); if (getServices().uiSettings.isDefault('defaultIndex')) { @@ -28,7 +28,7 @@ export async function installSampleDataSet(id, sampleDataDefaultIndex) { clearIndexPatternsCache(); } -export async function uninstallSampleDataSet(id, sampleDataDefaultIndex) { +export async function uninstallSampleDataSet(id: string, sampleDataDefaultIndex: string) { await getServices().http.delete(`${sampleDataUrl}/${id}`); const uiSettings = getServices().uiSettings; diff --git a/src/plugins/home/public/plugin.ts b/src/plugins/home/public/plugin.ts index ac680c78f31eb..1ece73e71f393 100644 --- a/src/plugins/home/public/plugin.ts +++ b/src/plugins/home/public/plugin.ts @@ -28,7 +28,7 @@ import { } from './services'; import { ConfigSchema } from '../config'; import { setServices } from './application/kibana_services'; -import { DataPublicPluginStart } from '../../data/public'; +import { DataViewsPublicPluginStart } from '../../data_views/public'; import { TelemetryPluginStart } from '../../telemetry/public'; import { UsageCollectionSetup } from '../../usage_collection/public'; import { UrlForwardingSetup, UrlForwardingStart } from '../../url_forwarding/public'; @@ -37,7 +37,7 @@ import { PLUGIN_ID, HOME_APP_BASE_PATH } from '../common/constants'; import { SharePluginSetup } from '../../share/public'; export interface HomePluginStartDependencies { - data: DataPublicPluginStart; + dataViews: DataViewsPublicPluginStart; telemetry?: TelemetryPluginStart; urlForwarding: UrlForwardingStart; } @@ -76,7 +76,7 @@ export class HomePublicPlugin const trackUiMetric = usageCollection ? usageCollection.reportUiCounter.bind(usageCollection, 'Kibana_home') : () => {}; - const [coreStart, { telemetry, data, urlForwarding: urlForwardingStart }] = + const [coreStart, { telemetry, dataViews, urlForwarding: urlForwardingStart }] = await core.getStartServices(); setServices({ share, @@ -93,7 +93,7 @@ export class HomePublicPlugin uiSettings: core.uiSettings, addBasePath: core.http.basePath.prepend, getBasePath: core.http.basePath.get, - indexPatternService: data.indexPatterns, + dataViewsService: dataViews, environmentService: this.environmentService, urlForwarding: urlForwardingStart, homeConfig: this.initializerContext.config.get(), @@ -167,6 +167,7 @@ export interface HomePublicPluginSetup { environment: EnvironmentSetup; } + export interface HomePublicPluginStart { featureCatalogue: FeatureCatalogueRegistry; } diff --git a/src/plugins/kibana_overview/kibana.json b/src/plugins/kibana_overview/kibana.json index 2924e71ed8282..ee646689226b6 100644 --- a/src/plugins/kibana_overview/kibana.json +++ b/src/plugins/kibana_overview/kibana.json @@ -7,7 +7,7 @@ "version": "kibana", "server": false, "ui": true, - "requiredPlugins": ["navigation", "data", "home", "share"], + "requiredPlugins": ["navigation", "dataViews", "home", "share"], "optionalPlugins": ["newsfeed", "usageCollection"], "requiredBundles": ["kibanaReact", "newsfeed"] } diff --git a/src/plugins/kibana_overview/public/components/overview/overview.test.mocks.ts b/src/plugins/kibana_overview/public/components/overview/overview.test.mocks.ts index 889fa35eb79a5..7f1e7f7d7ac52 100644 --- a/src/plugins/kibana_overview/public/components/overview/overview.test.mocks.ts +++ b/src/plugins/kibana_overview/public/components/overview/overview.test.mocks.ts @@ -14,10 +14,8 @@ jest.doMock('../../../../../../src/plugins/kibana_react/public', () => ({ useKibana: jest.fn().mockReturnValue({ services: { http: { basePath: { prepend: jest.fn((path: string) => (path ? path : 'path')) } }, - data: { - indexPatterns: { - hasUserDataView: hasUserDataViewMock, - }, + dataViews: { + hasUserDataView: hasUserDataViewMock, }, share: { url: { locators: { get: () => ({ useUrl: () => '' }) } } }, uiSettings: { get: jest.fn() }, diff --git a/src/plugins/kibana_overview/public/components/overview/overview.tsx b/src/plugins/kibana_overview/public/components/overview/overview.tsx index 398ce4d60a605..b387715710ce4 100644 --- a/src/plugins/kibana_overview/public/components/overview/overview.tsx +++ b/src/plugins/kibana_overview/public/components/overview/overview.tsx @@ -56,10 +56,9 @@ export const Overview: FC = ({ newsFetchResult, solutions, features }) => const [isNewKibanaInstance, setNewKibanaInstance] = useState(false); const [isLoading, setIsLoading] = useState(true); const { - services: { http, docLinks, data, share, uiSettings, application }, + services: { http, docLinks, dataViews, share, uiSettings, application }, } = useKibana(); const addBasePath = http.basePath.prepend; - const indexPatternService = data.indexPatterns; const IS_DARK_THEME = uiSettings.get('theme:darkMode'); // Home does not have a locator implemented, so hard-code it here. @@ -111,14 +110,14 @@ export const Overview: FC = ({ newsFetchResult, solutions, features }) => useEffect(() => { const fetchIsNewKibanaInstance = async () => { - const hasUserIndexPattern = await indexPatternService.hasUserDataView().catch(() => true); + const hasUserIndexPattern = await dataViews.hasUserDataView().catch(() => true); setNewKibanaInstance(!hasUserIndexPattern); setIsLoading(false); }; fetchIsNewKibanaInstance(); - }, [indexPatternService]); + }, [dataViews]); const renderAppCard = (appId: string) => { const app = kibanaApps.find(({ id }) => id === appId); diff --git a/src/plugins/kibana_overview/public/types.ts b/src/plugins/kibana_overview/public/types.ts index 032706c9e76a0..43c9746a6abbe 100644 --- a/src/plugins/kibana_overview/public/types.ts +++ b/src/plugins/kibana_overview/public/types.ts @@ -8,7 +8,7 @@ import { HomePublicPluginSetup, HomePublicPluginStart } from 'src/plugins/home/public'; import { NavigationPublicPluginStart } from 'src/plugins/navigation/public'; -import { DataPublicPluginStart } from 'src/plugins/data/public'; +import { DataViewsPublicPluginStart } from 'src/plugins/data_views/public'; import { NewsfeedPublicPluginStart } from 'src/plugins/newsfeed/public'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; import { SharePluginStart } from '../../share/public'; @@ -26,7 +26,7 @@ export interface AppPluginSetupDependencies { export interface AppPluginStartDependencies { home: HomePublicPluginStart; - data: DataPublicPluginStart; + dataViews: DataViewsPublicPluginStart; navigation: NavigationPublicPluginStart; newsfeed?: NewsfeedPublicPluginStart; share: SharePluginStart; diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts index 27e44cba1094f..bde8a10e4dd2e 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -392,6 +392,10 @@ export const stackManagementSchema: MakeSchemaFrom = { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, }, + 'bfetch:disable': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, 'visualization:visualize:legacyPieChartsLibrary': { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts index 8776bad89f8a6..47656c568bf4c 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts @@ -23,6 +23,7 @@ export interface UsageStats { /** * non-sensitive settings */ + 'bfetch:disable': boolean; 'bfetch:disableCompression': boolean; 'autocomplete:useTimeRange': boolean; 'autocomplete:valueSuggestionMethod': string; diff --git a/src/plugins/saved_objects/kibana.json b/src/plugins/saved_objects/kibana.json index 27fd92a219d8d..b0ab3c26a35cf 100644 --- a/src/plugins/saved_objects/kibana.json +++ b/src/plugins/saved_objects/kibana.json @@ -7,7 +7,7 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": ["data"], + "requiredPlugins": ["data", "dataViews"], "requiredBundles": [ "kibanaUtils", "kibanaReact" diff --git a/src/plugins/saved_objects/public/plugin.ts b/src/plugins/saved_objects/public/plugin.ts index d1b9f0f57fcfc..b75ff043cee8d 100644 --- a/src/plugins/saved_objects/public/plugin.ts +++ b/src/plugins/saved_objects/public/plugin.ts @@ -15,6 +15,7 @@ import { SavedObjectDecoratorConfig, } from './saved_object'; import { DataPublicPluginStart } from '../../data/public'; +import { DataViewsPublicPluginStart } from '../../data_views/public'; import { PER_PAGE_SETTING, LISTING_LIMIT_SETTING } from '../common'; import { SavedObject } from './types'; @@ -36,6 +37,7 @@ export interface SavedObjectsStart { export interface SavedObjectsStartDeps { data: DataPublicPluginStart; + dataViews: DataViewsPublicPluginStart; } export class SavedObjectsPublicPlugin @@ -48,11 +50,11 @@ export class SavedObjectsPublicPlugin registerDecorator: (config) => this.decoratorRegistry.register(config), }; } - public start(core: CoreStart, { data }: SavedObjectsStartDeps) { + public start(core: CoreStart, { data, dataViews }: SavedObjectsStartDeps) { return { SavedObjectClass: createSavedObjectClass( { - indexPatterns: data.indexPatterns, + dataViews, savedObjectsClient: core.savedObjects.client, search: data.search, chrome: core.chrome, diff --git a/src/plugins/saved_objects/public/saved_object/helpers/build_saved_object.ts b/src/plugins/saved_objects/public/saved_object/helpers/build_saved_object.ts index 04f629c5596a7..647eece25752a 100644 --- a/src/plugins/saved_objects/public/saved_object/helpers/build_saved_object.ts +++ b/src/plugins/saved_objects/public/saved_object/helpers/build_saved_object.ts @@ -41,7 +41,7 @@ export function buildSavedObject( ) { applyDecorators(savedObject, config, decorators); - const { indexPatterns, savedObjectsClient } = services; + const { dataViews, savedObjectsClient } = services; // type name for this object, used as the ES-type const esType = config.type || ''; @@ -77,7 +77,7 @@ export function buildSavedObject( * @return {Promise} */ savedObject.hydrateIndexPattern = (id?: string) => - hydrateIndexPattern(id || '', savedObject, indexPatterns, config); + hydrateIndexPattern(id || '', savedObject, dataViews, config); /** * Asynchronously initialize this object - will only run * once even if called multiple times. diff --git a/src/plugins/saved_objects/public/saved_object/helpers/hydrate_index_pattern.ts b/src/plugins/saved_objects/public/saved_object/helpers/hydrate_index_pattern.ts index 6f3a2f4db7da8..64843ce9260d2 100644 --- a/src/plugins/saved_objects/public/saved_object/helpers/hydrate_index_pattern.ts +++ b/src/plugins/saved_objects/public/saved_object/helpers/hydrate_index_pattern.ts @@ -7,7 +7,7 @@ */ import { SavedObject, SavedObjectConfig } from '../../types'; -import { IndexPatternsContract } from '../../../../data/public'; +import { DataViewsContract } from '../../../../data_views/public'; /** * After creation or fetching from ES, ensure that the searchSources index indexPattern @@ -18,7 +18,7 @@ import { IndexPatternsContract } from '../../../../data/public'; export async function hydrateIndexPattern( id: string, savedObject: SavedObject, - indexPatterns: IndexPatternsContract, + dataViews: DataViewsContract, config: SavedObjectConfig ) { const indexPattern = config.indexPattern; @@ -33,7 +33,7 @@ export async function hydrateIndexPattern( return null; } - const indexObj = await indexPatterns.get(index); + const indexObj = await dataViews.get(index); savedObject.searchSource.setField('index', indexObj); return indexObj; } diff --git a/src/plugins/saved_objects/public/types.ts b/src/plugins/saved_objects/public/types.ts index 3b1c5f82ea925..46797c07b9565 100644 --- a/src/plugins/saved_objects/public/types.ts +++ b/src/plugins/saved_objects/public/types.ts @@ -14,12 +14,12 @@ import { SavedObjectReference, } from 'kibana/public'; import { - DataPublicPluginStart, IndexPattern, - IndexPatternsContract, ISearchSource, + ISearchStart, SerializedSearchSourceFields, } from '../../data/public'; +import { DataViewsContract } from '../../data_views/public'; /** @deprecated */ export interface SavedObject { @@ -63,8 +63,8 @@ export interface SavedObjectCreationOpts { export interface SavedObjectKibanaServices { savedObjectsClient: SavedObjectsClientContract; - indexPatterns: IndexPatternsContract; - search: DataPublicPluginStart['search']; + dataViews: DataViewsContract; + search: ISearchStart; chrome: ChromeStart; overlays: OverlayStart; } diff --git a/src/plugins/saved_objects_management/kibana.json b/src/plugins/saved_objects_management/kibana.json index 3043a7cb67fe2..4e9977915f5cd 100644 --- a/src/plugins/saved_objects_management/kibana.json +++ b/src/plugins/saved_objects_management/kibana.json @@ -7,7 +7,7 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": ["management", "data"], + "requiredPlugins": ["management", "data", "dataViews"], "optionalPlugins": ["home", "savedObjectsTaggingOss", "spaces"], "extraPublicDirs": ["public/lib"], "requiredBundles": ["kibanaReact", "home"] diff --git a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx index 778a42d408728..bca3741bf2741 100644 --- a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx +++ b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx @@ -33,7 +33,7 @@ const title = i18n.translate('savedObjectsManagement.objects.savedObjectsTitle', const SavedObjectsEditionPage = lazy(() => import('./saved_objects_edition_page')); const SavedObjectsTablePage = lazy(() => import('./saved_objects_table_page')); export const mountManagementSection = async ({ core, mountParams }: MountParams) => { - const [coreStart, { data, savedObjectsTaggingOss, spaces: spacesApi }, pluginStart] = + const [coreStart, { data, dataViews, savedObjectsTaggingOss, spaces: spacesApi }, pluginStart] = await core.getStartServices(); const { capabilities } = coreStart.application; const { element, history, setBreadcrumbs } = mountParams; @@ -79,6 +79,7 @@ export const mountManagementSection = async ({ core, mountParams }: MountParams) taggingApi={savedObjectsTaggingOss?.getTaggingApi()} spacesApi={spacesApi} dataStart={data} + dataViewsApi={dataViews} actionRegistry={pluginStart.actions} columnRegistry={pluginStart.columns} allowedTypes={allowedObjectTypes} diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx index 4cdacd30e83d1..a084c26b04d2d 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx @@ -40,7 +40,7 @@ describe('Flyout', () => { close: jest.fn(), done: jest.fn(), newIndexPatternUrl: '', - indexPatterns: { + dataViews: { getCache: jest.fn().mockImplementation(() => [ { id: '1', attributes: {} }, { id: '2', attributes: {} }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx index 04ad32c1df551..ca23452e875ec 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx @@ -32,11 +32,8 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { HttpStart, IBasePath } from 'src/core/public'; -import { - IndexPatternsContract, - IndexPattern, - DataPublicPluginStart, -} from '../../../../../data/public'; +import { ISearchStart } from '../../../../../data/public'; +import type { DataViewsContract, DataView } from '../../../../../data_views/public'; import type { SavedObjectManagementTypeInfo } from '../../../../common/types'; import { importFile, @@ -56,10 +53,10 @@ export interface FlyoutProps { close: () => void; done: () => void; newIndexPatternUrl: string; - indexPatterns: IndexPatternsContract; + dataViews: DataViewsContract; http: HttpStart; basePath: IBasePath; - search: DataPublicPluginStart['search']; + search: ISearchStart; allowedTypes: SavedObjectManagementTypeInfo[]; } @@ -73,7 +70,7 @@ export interface FlyoutState { error?: string; file?: File; importCount: number; - indexPatterns?: IndexPattern[]; + indexPatterns?: DataView[]; importMode: ImportMode; loadingMessage?: string; status: string; @@ -121,7 +118,7 @@ export class Flyout extends Component { } fetchIndexPatterns = async () => { - const indexPatterns = (await this.props.indexPatterns.getCache())?.map((savedObject) => ({ + const indexPatterns = (await this.props.dataViews.getCache())?.map((savedObject) => ({ id: savedObject.id, title: savedObject.attributes.title, })); diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx index 6a98fada416f0..173d8af0de04d 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx @@ -28,6 +28,7 @@ import { applicationServiceMock, } from '../../../../../core/public/mocks'; import { dataPluginMock } from '../../../../data/public/mocks'; +import { dataViewPluginMocks } from '../../../../data_views/public/mocks'; import type { SavedObjectManagementTypeInfo } from '../../../common/types'; import { actionServiceMock } from '../../services/action_service.mock'; import { columnServiceMock } from '../../services/column_service.mock'; @@ -132,7 +133,7 @@ describe('SavedObjectsTable', () => { actionRegistry: actionServiceMock.createStart(), columnRegistry: columnServiceMock.createStart(), savedObjectsClient: savedObjects.client, - indexPatterns: dataPluginMock.createStartContract().indexPatterns, + dataViews: dataViewPluginMocks.createStartContract(), http, overlays, notifications, @@ -580,7 +581,7 @@ describe('SavedObjectsTable', () => { await component.instance().delete(); - expect(defaultProps.indexPatterns.clearCache).toHaveBeenCalled(); + expect(defaultProps.dataViews.clearCache).toHaveBeenCalled(); expect(mockSavedObjectsClient.delete).toHaveBeenCalledWith( mockSavedObjects[0].type, mockSavedObjects[0].id, @@ -626,7 +627,7 @@ describe('SavedObjectsTable', () => { await component.instance().delete(); - expect(defaultProps.indexPatterns.clearCache).toHaveBeenCalled(); + expect(defaultProps.dataViews.clearCache).toHaveBeenCalled(); expect(mockSavedObjectsClient.delete).toHaveBeenCalledTimes(1); expect(mockSavedObjectsClient.delete).toHaveBeenCalledWith('index-pattern', '1', { force: true, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index d4b3ecac5b8db..12ef7ba075cdb 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -22,7 +22,7 @@ import { } from 'src/core/public'; import { RedirectAppLinks } from '../../../../kibana_react/public'; import { SavedObjectsTaggingApi } from '../../../../saved_objects_tagging_oss/public'; -import { IndexPatternsContract } from '../../../../data/public'; +import { DataViewsContract } from '../../../../data_views/public'; import type { SavedObjectManagementTypeInfo } from '../../../common/types'; import { parseQuery, @@ -61,7 +61,7 @@ export interface SavedObjectsTableProps { actionRegistry: SavedObjectsManagementActionServiceStart; columnRegistry: SavedObjectsManagementColumnServiceStart; savedObjectsClient: SavedObjectsClientContract; - indexPatterns: IndexPatternsContract; + dataViews: DataViewsContract; taggingApi?: SavedObjectsTaggingApi; http: HttpStart; search: DataPublicPluginStart['search']; @@ -513,7 +513,7 @@ export class SavedObjectsTable extends Component object.type === 'index-pattern'); if (indexPatterns.length) { - await this.props.indexPatterns.clearCache(); + await this.props.dataViews.clearCache(); } const deletes = selectedSavedObjects @@ -557,7 +557,7 @@ export class SavedObjectsTable extends Component = ({ children }) = const SavedObjectsTablePage = ({ coreStart, dataStart, + dataViewsApi, taggingApi, spacesApi, allowedTypes, @@ -37,6 +39,7 @@ const SavedObjectsTablePage = ({ }: { coreStart: CoreStart; dataStart: DataPublicPluginStart; + dataViewsApi: DataViewsContract; taggingApi?: SavedObjectsTaggingApi; spacesApi?: SpacesApi; allowedTypes: SavedObjectManagementTypeInfo[]; @@ -81,7 +84,7 @@ const SavedObjectsTablePage = ({ columnRegistry={columnRegistry} taggingApi={taggingApi} savedObjectsClient={coreStart.savedObjects.client} - indexPatterns={dataStart.indexPatterns} + dataViews={dataViewsApi} search={dataStart.search} http={coreStart.http} overlays={coreStart.overlays} diff --git a/src/plugins/saved_objects_management/public/plugin.test.ts b/src/plugins/saved_objects_management/public/plugin.test.ts index c2340d62986f0..311cd811c455a 100644 --- a/src/plugins/saved_objects_management/public/plugin.test.ts +++ b/src/plugins/saved_objects_management/public/plugin.test.ts @@ -9,6 +9,7 @@ import { coreMock } from '../../../core/public/mocks'; import { homePluginMock } from '../../home/public/mocks'; import { managementPluginMock } from '../../management/public/mocks'; +import { dataViewPluginMocks } from '../../data_views/public/mocks'; import { dataPluginMock } from '../../data/public/mocks'; import { SavedObjectsManagementPlugin } from './plugin'; @@ -22,7 +23,10 @@ describe('SavedObjectsManagementPlugin', () => { describe('#setup', () => { it('registers the saved_objects feature to the home plugin', async () => { const coreSetup = coreMock.createSetup({ - pluginStartDeps: { data: dataPluginMock.createStartContract() }, + pluginStartDeps: { + dataViews: dataViewPluginMocks.createStartContract(), + data: dataPluginMock.createStartContract(), + }, }); const homeSetup = homePluginMock.createSetupContract(); const managementSetup = managementPluginMock.createSetupContract(); diff --git a/src/plugins/saved_objects_management/public/plugin.ts b/src/plugins/saved_objects_management/public/plugin.ts index f8806f14ab7f7..97093fc9f4b77 100644 --- a/src/plugins/saved_objects_management/public/plugin.ts +++ b/src/plugins/saved_objects_management/public/plugin.ts @@ -11,6 +11,7 @@ import { CoreSetup, CoreStart, Plugin } from 'src/core/public'; import type { SpacesPluginStart } from '../../../../x-pack/plugins/spaces/public'; import { ManagementSetup } from '../../management/public'; import { DataPublicPluginStart } from '../../data/public'; +import { DataViewsPublicPluginStart } from '../../data_views/public'; import { HomePublicPluginSetup, FeatureCatalogueCategory } from '../../home/public'; import { SavedObjectTaggingOssPluginStart } from '../../saved_objects_tagging_oss/public'; import { @@ -39,6 +40,7 @@ export interface SetupDependencies { export interface StartDependencies { data: DataPublicPluginStart; + dataViews: DataViewsPublicPluginStart; savedObjectsTaggingOss?: SavedObjectTaggingOssPluginStart; spaces?: SpacesPluginStart; } diff --git a/src/plugins/telemetry/public/plugin.ts b/src/plugins/telemetry/public/plugin.ts index 73dc07d7a4fb9..3072ff67703d7 100644 --- a/src/plugins/telemetry/public/plugin.ts +++ b/src/plugins/telemetry/public/plugin.ts @@ -186,6 +186,10 @@ export class TelemetryPlugin implements Plugin { }); describe('shouldSendReport', () => { + let hasFocus: jest.SpyInstance; + + beforeEach(() => { + hasFocus = jest.spyOn(document, 'hasFocus'); + hasFocus.mockReturnValue(true); // Return true by default for all tests; + }); + + afterEach(() => { + hasFocus.mockRestore(); + }); + + it('returns false if the page is not visible', async () => { + hasFocus.mockReturnValue(false); + const telemetryService = mockTelemetryService(); + telemetryService.getIsOptedIn = jest.fn().mockReturnValue(true); + telemetryService.fetchLastReported = jest.fn().mockResolvedValue(Date.now()); + const telemetrySender = new TelemetrySender(telemetryService); + const shouldSendReport = await telemetrySender['shouldSendReport'](); + expect(shouldSendReport).toBe(false); + expect(telemetryService.getIsOptedIn).toBeCalledTimes(0); + expect(telemetryService.fetchLastReported).toBeCalledTimes(0); + }); + it('returns false whenever optIn is false', async () => { const telemetryService = mockTelemetryService(); telemetryService.getIsOptedIn = jest.fn().mockReturnValue(false); @@ -372,9 +395,11 @@ describe('TelemetrySender', () => { it('calls sendIfDue every 60000 ms', () => { const telemetryService = mockTelemetryService(); const telemetrySender = new TelemetrySender(telemetryService); + telemetrySender['sendIfDue'] = jest.fn().mockResolvedValue(void 0); telemetrySender.startChecking(); - expect(setInterval).toBeCalledTimes(1); - expect(setInterval).toBeCalledWith(telemetrySender['sendIfDue'], 60000); + expect(telemetrySender['sendIfDue']).toHaveBeenCalledTimes(0); + jest.advanceTimersByTime(60000); + expect(telemetrySender['sendIfDue']).toHaveBeenCalledTimes(1); }); }); }); diff --git a/src/plugins/telemetry/public/services/telemetry_sender.ts b/src/plugins/telemetry/public/services/telemetry_sender.ts index d0eb9142e724a..8fa2a015ef119 100644 --- a/src/plugins/telemetry/public/services/telemetry_sender.ts +++ b/src/plugins/telemetry/public/services/telemetry_sender.ts @@ -6,6 +6,9 @@ * Side Public License, v 1. */ +import type { Subscription } from 'rxjs'; +import { fromEvent, interval, merge } from 'rxjs'; +import { exhaustMap } from 'rxjs/operators'; import { LOCALSTORAGE_KEY, PAYLOAD_CONTENT_ENCODING } from '../../common/constants'; import { TelemetryService } from './telemetry_service'; import { Storage } from '../../../kibana_utils/public'; @@ -16,7 +19,7 @@ export class TelemetrySender { private readonly telemetryService: TelemetryService; private lastReported?: number; private readonly storage: Storage; - private intervalId: number = 0; // setInterval returns a positive integer, 0 means no interval is set + private sendIfDue$?: Subscription; private retryCount: number = 0; static getRetryDelay(retryCount: number) { @@ -62,11 +65,21 @@ export class TelemetrySender { }; /** - * Using configuration and the lastReported dates, it decides whether a new telemetry report should be sent. + * Returns `true` when the page is visible and active in the browser. + */ + private isActiveWindow = () => { + // Using `document.hasFocus()` instead of `document.visibilityState` because the latter may return "visible" + // if 2 windows are open side-by-side because they are "technically" visible. + return document.hasFocus(); + }; + + /** + * Using configuration, page visibility state and the lastReported dates, + * it decides whether a new telemetry report should be sent. * @returns `true` if a new report should be sent. `false` otherwise. */ private shouldSendReport = async (): Promise => { - if (this.telemetryService.canSendTelemetry()) { + if (this.isActiveWindow() && this.telemetryService.canSendTelemetry()) { return await this.isReportDue(); } @@ -122,8 +135,20 @@ export class TelemetrySender { }; public startChecking = () => { - if (this.intervalId === 0) { - this.intervalId = window.setInterval(this.sendIfDue, 60000); + if (!this.sendIfDue$) { + // Trigger sendIfDue... + this.sendIfDue$ = merge( + // ... periodically + interval(60000), + // ... when it regains `focus` + fromEvent(window, 'focus') // Using `window` instead of `document` because Chrome only emits on the first one. + ) + .pipe(exhaustMap(this.sendIfDue)) + .subscribe(); } }; + + public stop = () => { + this.sendIfDue$?.unsubscribe(); + }; } diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index 9c2c71898dee7..3269452ca8cc3 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -7736,6 +7736,12 @@ "description": "Non-default value of setting." } }, + "bfetch:disable": { + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } + }, "visualization:visualize:legacyPieChartsLibrary": { "type": "boolean", "_meta": { diff --git a/src/plugins/telemetry/schema/oss_root.json b/src/plugins/telemetry/schema/oss_root.json index e526dc6413916..cf9b881facef2 100644 --- a/src/plugins/telemetry/schema/oss_root.json +++ b/src/plugins/telemetry/schema/oss_root.json @@ -194,6 +194,62 @@ "properties": { "kibana_config_usage": { "type": "pass_through" + }, + "usage_collector_stats": { + "properties": { + "not_ready": { + "properties": { + "count": { + "type": "short" + }, + "names": { + "type": "array", + "items": { + "type": "keyword" + } + } + } + }, + "not_ready_timeout": { + "properties": { + "count": { + "type": "short" + }, + "names": { + "type": "array", + "items": { + "type": "keyword" + } + } + } + }, + "succeeded": { + "properties": { + "count": { + "type": "short" + }, + "names": { + "type": "array", + "items": { + "type": "keyword" + } + } + } + }, + "failed": { + "properties": { + "count": { + "type": "short" + }, + "names": { + "type": "array", + "items": { + "type": "keyword" + } + } + } + } + } } } } diff --git a/src/plugins/usage_collection/server/collector/collector_set.test.ts b/src/plugins/usage_collection/server/collector/collector_set.test.ts index 491937bc29fcb..f6d667f2959d9 100644 --- a/src/plugins/usage_collection/server/collector/collector_set.test.ts +++ b/src/plugins/usage_collection/server/collector/collector_set.test.ts @@ -95,6 +95,15 @@ describe('CollectorSet', () => { type: 'MY_TEST_COLLECTOR', result: { passTest: 1000 }, }, + { + type: 'usage_collector_stats', + result: { + not_ready: { count: 0, names: [] }, + not_ready_timeout: { count: 0, names: [] }, + succeeded: { count: 1, names: ['MY_TEST_COLLECTOR'] }, + failed: { count: 0, names: [] }, + }, + }, ]); }); @@ -115,7 +124,17 @@ describe('CollectorSet', () => { // Do nothing } // This must return an empty object instead of null/undefined - expect(result).toStrictEqual([]); + expect(result).toStrictEqual([ + { + type: 'usage_collector_stats', + result: { + not_ready: { count: 0, names: [] }, + not_ready_timeout: { count: 0, names: [] }, + succeeded: { count: 0, names: [] }, + failed: { count: 1, names: ['MY_TEST_COLLECTOR'] }, + }, + }, + ]); }); it('should not break if isReady is not a function', async () => { @@ -135,6 +154,15 @@ describe('CollectorSet', () => { type: 'MY_TEST_COLLECTOR', result: { test: 1 }, }, + { + type: 'usage_collector_stats', + result: { + not_ready: { count: 0, names: [] }, + not_ready_timeout: { count: 0, names: [] }, + succeeded: { count: 1, names: ['MY_TEST_COLLECTOR'] }, + failed: { count: 0, names: [] }, + }, + }, ]); }); @@ -154,6 +182,15 @@ describe('CollectorSet', () => { type: 'MY_TEST_COLLECTOR', result: { test: 1 }, }, + { + type: 'usage_collector_stats', + result: { + not_ready: { count: 0, names: [] }, + not_ready_timeout: { count: 0, names: [] }, + succeeded: { count: 1, names: ['MY_TEST_COLLECTOR'] }, + failed: { count: 0, names: [] }, + }, + }, ]); }); }); @@ -535,6 +572,31 @@ describe('CollectorSet', () => { "result": Object {}, "type": "ready_col", }, + Object { + "result": Object { + "failed": Object { + "count": 0, + "names": Array [], + }, + "not_ready": Object { + "count": 1, + "names": Array [ + "not_ready_col", + ], + }, + "not_ready_timeout": Object { + "count": 0, + "names": Array [], + }, + "succeeded": Object { + "count": 1, + "names": Array [ + "ready_col", + ], + }, + }, + "type": "usage_collector_stats", + }, ] `); }); @@ -584,6 +646,31 @@ describe('CollectorSet', () => { "result": Object {}, "type": "ready_col", }, + Object { + "result": Object { + "failed": Object { + "count": 0, + "names": Array [], + }, + "not_ready": Object { + "count": 0, + "names": Array [], + }, + "not_ready_timeout": Object { + "count": 1, + "names": Array [ + "timeout_col", + ], + }, + "succeeded": Object { + "count": 1, + "names": Array [ + "ready_col", + ], + }, + }, + "type": "usage_collector_stats", + }, ] `); }); @@ -608,7 +695,7 @@ describe('CollectorSet', () => { esClient: mockEsClient, soClient: mockSoClient, }); - expect(results).toHaveLength(1); + expect(results).toHaveLength(2); }); it('adds extra context to collectors with extendFetchContext config', async () => { @@ -634,7 +721,7 @@ describe('CollectorSet', () => { soClient: mockSoClient, kibanaRequest: request, }); - expect(results).toHaveLength(1); + expect(results).toHaveLength(2); }); }); }); diff --git a/src/plugins/usage_collection/server/collector/collector_set.ts b/src/plugins/usage_collection/server/collector/collector_set.ts index 05ebb2a34202c..79fb0a39c7801 100644 --- a/src/plugins/usage_collection/server/collector/collector_set.ts +++ b/src/plugins/usage_collection/server/collector/collector_set.ts @@ -31,6 +31,15 @@ interface CollectorSetConfig { maximumWaitTimeForAllCollectorsInS?: number; collectors?: AnyCollector[]; } + +// Schema manually added in src/plugins/telemetry/schema/oss_root.json under `stack_stats.kibana.plugins.usage_collector_stats` +interface CollectorStats { + not_ready: { count: number; names: string[] }; + not_ready_timeout: { count: number; names: string[] }; + succeeded: { count: number; names: string[] }; + failed: { count: number; names: string[] }; +} + export class CollectorSet { private readonly logger: Logger; private readonly maximumWaitTimeForAllCollectorsInS: number; @@ -101,7 +110,11 @@ export class CollectorSet { private getReadyCollectors = async ( collectors: Map = this.collectors - ): Promise => { + ): Promise<{ + readyCollectors: AnyCollector[]; + nonReadyCollectorTypes: string[]; + timedOutCollectorsTypes: string[]; + }> => { if (!(collectors instanceof Map)) { throw new Error( `getReadyCollectors method given bad Map of collectors: ` + typeof collectors @@ -162,7 +175,11 @@ export class CollectorSet { .filter(({ isReadyWithTimeout }) => isReadyWithTimeout.value === true) .map(({ collector }) => collector); - return readyCollectors; + return { + readyCollectors, + nonReadyCollectorTypes: collectorsTypesNotReady, + timedOutCollectorsTypes, + }; }; public bulkFetch = async ( @@ -172,7 +189,16 @@ export class CollectorSet { collectors: Map = this.collectors ) => { this.logger.debug(`Getting ready collectors`); - const readyCollectors = await this.getReadyCollectors(collectors); + const { readyCollectors, nonReadyCollectorTypes, timedOutCollectorsTypes } = + await this.getReadyCollectors(collectors); + + const collectorStats: CollectorStats = { + not_ready: { count: nonReadyCollectorTypes.length, names: nonReadyCollectorTypes }, + not_ready_timeout: { count: timedOutCollectorsTypes.length, names: timedOutCollectorsTypes }, + succeeded: { count: 0, names: [] }, + failed: { count: 0, names: [] }, + }; + const responses = await Promise.all( readyCollectors.map(async (collector) => { this.logger.debug(`Fetching data from ${collector.type} collector`); @@ -182,17 +208,23 @@ export class CollectorSet { soClient, ...(collector.extendFetchContext.kibanaRequest && { kibanaRequest }), }; - return { - type: collector.type, - result: await collector.fetch(context), - }; + const result = await collector.fetch(context); + collectorStats.succeeded.names.push(collector.type); + return { type: collector.type, result }; } catch (err) { this.logger.warn(err); this.logger.warn(`Unable to fetch data from ${collector.type} collector`); + collectorStats.failed.names.push(collector.type); } }) ); + collectorStats.succeeded.count = collectorStats.succeeded.names.length; + collectorStats.failed.count = collectorStats.failed.names.length; + + // Treat it as just another "collector" + responses.push({ type: 'usage_collector_stats', result: collectorStats }); + return responses.filter( (response): response is { type: string; result: unknown } => typeof response !== 'undefined' ); diff --git a/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx b/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx index f1eebbbdf2116..5fcf3d4ecf133 100644 --- a/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx +++ b/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx @@ -104,7 +104,7 @@ function DefaultEditorSideBarComponent({ ...vis.serialize(), params: state.params, data: { - aggs: state.data.aggs ? (state.data.aggs.aggs.map((agg) => agg.toJSON()) as any) : [], + aggs: state.data.aggs ? (state.data.aggs.aggs.map((agg) => agg.serialize()) as any) : [], }, }); embeddableHandler.reload(); diff --git a/src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts b/src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts index ee2b715fad25f..54012b9d89590 100644 --- a/src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts +++ b/src/plugins/vis_default_editor/public/components/sidebar/state/reducers.ts @@ -58,7 +58,7 @@ const createEditorStateReducer = if (agg.id === aggId) { agg.type = value; - return agg.toJSON(); + return agg.serialize(); } return agg; @@ -78,7 +78,7 @@ const createEditorStateReducer = const newAggs = state.data.aggs!.aggs.map((agg) => { if (agg.id === aggId) { - const parsedAgg = agg.toJSON(); + const parsedAgg = agg.serialize(); return { ...parsedAgg, @@ -169,7 +169,7 @@ const createEditorStateReducer = const newAggs = state.data.aggs!.aggs.map((agg) => { if (agg.id === aggId) { - const parsedAgg = agg.toJSON(); + const parsedAgg = agg.serialize(); return { ...parsedAgg, diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.js b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.js index 429050fab36cc..6936ea7e1c5d7 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.js +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.js @@ -27,28 +27,32 @@ export function timeShift( const offsetValue = matches[1]; const offsetUnit = matches[2]; - let defaultTimezone; - if (!panel.ignore_daylight_time) { - // the datemath plugin always parses dates by using the current default moment time zone. - // to use the configured time zone, we are switching just for the bounds calculation. - defaultTimezone = moment().zoneName(); - moment.tz.setDefault(timezone); - } + const defaultTimezone = moment().zoneName(); + try { + if (!panel.ignore_daylight_time) { + // the datemath plugin always parses dates by using the current default moment time zone. + // to use the configured time zone, we are switching just for the bounds calculation. - results.forEach((item) => { - if (startsWith(item.id, series.id)) { - item.data = item.data.map((row) => [ - (panel.ignore_daylight_time ? moment.utc : moment)(row[0]) - .add(offsetValue, offsetUnit) - .valueOf(), - row[1], - ]); + // The code between this call and the reset in the finally block is not allowed to get async, + // otherwise the timezone setting can leak out of this function. + moment.tz.setDefault(timezone); } - }); - if (!panel.ignore_daylight_time) { - // reset default moment timezone - moment.tz.setDefault(defaultTimezone); + results.forEach((item) => { + if (startsWith(item.id, series.id)) { + item.data = item.data.map((row) => [ + (panel.ignore_daylight_time ? moment.utc : moment)(row[0]) + .add(offsetValue, offsetUnit) + .valueOf(), + row[1], + ]); + } + }); + } finally { + if (!panel.ignore_daylight_time) { + // reset default moment timezone + moment.tz.setDefault(defaultTimezone); + } } } } diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js index 7fff2603cf47a..f3000e5589b6d 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js @@ -128,4 +128,9 @@ describe('timeShift(resp, panel, series)', () => { [dateAfterDST + 1000 * 60 * 60 * 24, 2], ]); }); + + test('processor is sync to avoid timezone setting leakage', () => { + const result = timeShift(resp, panel, series, {})((results) => results)([]); + expect(Array.isArray(result)).toBe(true); + }); }); diff --git a/src/plugins/vis_types/vega/public/components/vega_vis_component.tsx b/src/plugins/vis_types/vega/public/components/vega_vis_component.tsx index d01e6425aa24b..66cb87d0d6138 100644 --- a/src/plugins/vis_types/vega/public/components/vega_vis_component.tsx +++ b/src/plugins/vis_types/vega/public/components/vega_vis_component.tsx @@ -55,13 +55,13 @@ export const VegaVisComponent = ({ } }, [visData, renderComplete]); + /* eslint-disable-next-line react-hooks/exhaustive-deps */ const updateChartSize = useCallback( - () => - throttle(() => { - if (visController.current) { - visController.current.render(visData).then(renderComplete); - } - }, 300), + throttle(() => { + if (visController.current) { + visController.current.render(visData).then(renderComplete); + } + }, 300), [renderComplete, visData] ); diff --git a/src/plugins/vis_types/vega/public/data_model/vega_parser.test.js b/src/plugins/vis_types/vega/public/data_model/vega_parser.test.js index bdab3b45a00f6..5b9213c4dc583 100644 --- a/src/plugins/vis_types/vega/public/data_model/vega_parser.test.js +++ b/src/plugins/vis_types/vega/public/data_model/vega_parser.test.js @@ -8,6 +8,7 @@ import { cloneDeep } from 'lodash'; import 'jest-canvas-mock'; import { euiThemeVars } from '@kbn/ui-theme'; +import { TimeCache } from './time_cache'; import { VegaParser } from './vega_parser'; import { bypassExternalUrlCheck } from '../vega_view/vega_base_view'; @@ -226,7 +227,12 @@ describe('VegaParser._resolveEsQueries', () => { }, }; }; - const vp = new VegaParser(spec, searchApiStub, 0, 0, mockGetServiceSettings); + const tc = new (class extends TimeCache { + getTimeBounds() { + return { min: 123456, max: 654321 }; + } + })(); + const vp = new VegaParser(spec, searchApiStub, tc, 0, mockGetServiceSettings); await vp._resolveDataUrls(); expect(vp.spec).toEqual(expected); @@ -265,6 +271,20 @@ describe('VegaParser._resolveEsQueries', () => { { data: { url: bypassExternalUrlCheck('url1') } } ) ); + test( + 'timefilter_min', + check( + { data: { url: 'http://example.com?min=%timefilter_min%' } }, + { data: { url: 'http://example.com?min=123456' } } + ) + ); + test( + 'timefilter_max', + check( + { data: { url: 'http://example.com?min=%timefilter_max%' } }, + { data: { url: 'http://example.com?min=654321' } } + ) + ); }); describe('VegaParser.parseSchema', () => { diff --git a/src/plugins/vis_types/vega/public/data_model/vega_parser.ts b/src/plugins/vis_types/vega/public/data_model/vega_parser.ts index bcaf8afd4fd0c..f752813128224 100644 --- a/src/plugins/vis_types/vega/public/data_model/vega_parser.ts +++ b/src/plugins/vis_types/vega/public/data_model/vega_parser.ts @@ -676,6 +676,11 @@ The URL is an identifier only. Kibana and your browser will never access this UR ); } onFind(obj as Data); + } else if (key === 'data' && typeof obj.url === 'string') { + const bounds = this.timeCache.getTimeBounds(); + obj.url = obj.url + .replaceAll('%timefilter_min%', bounds.min.toString()) + .replaceAll('%timefilter_max%', bounds.max.toString()); } else { for (const k of Object.keys(obj)) { this._findObjectDataUrls(obj[k], onFind, k); 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 997c3142992c2..be68abaebc638 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 @@ -176,7 +176,7 @@ export class VegaMapView extends VegaBaseView { map: mapBoxInstance, context: { vegaView, - vegaControls: this._$controls.get(0), + vegaControls: this._$controls?.get(0), updateVegaView, }, }); diff --git a/src/plugins/vis_types/xy/public/utils/compute_percentage_data.test.ts b/src/plugins/vis_types/xy/public/utils/compute_percentage_data.test.ts index 835b6918f196f..0429bb5253b6f 100644 --- a/src/plugins/vis_types/xy/public/utils/compute_percentage_data.test.ts +++ b/src/plugins/vis_types/xy/public/utils/compute_percentage_data.test.ts @@ -112,7 +112,7 @@ describe('computePercentageData', () => { }, { 'col-0-4': 'ES-Air', - 'col-1-5': 0.08653846153846152, + 'col-1-5': 0.08653846153846154, 'col-2-1': 0.1346153846153846, 'col-3-1': 1, }, @@ -130,7 +130,7 @@ describe('computePercentageData', () => { }, { 'col-0-4': 'JetBeats', - 'col-1-5': 0.10576923076923078, + 'col-1-5': 0.10576923076923077, 'col-2-1': 0.6923076923076923, 'col-3-1': 0, }, @@ -142,14 +142,14 @@ describe('computePercentageData', () => { }, { 'col-0-4': 'Logstash Airways', - 'col-1-5': 0.05376344086021506, - 'col-2-1': 0.7634408602150539, + 'col-1-5': 0.053763440860215055, + 'col-2-1': 0.7634408602150538, 'col-3-1': 1, }, { 'col-0-4': 'Logstash Airways', 'col-1-5': 0.07526881720430108, - 'col-2-1': 0.10752688172043012, + 'col-2-1': 0.10752688172043011, 'col-3-1': 0, }, ]); @@ -171,7 +171,7 @@ describe('computePercentageData', () => { }, { 'col-0-4': 'ES-Air', - 'col-1-5': 0.08653846153846152, + 'col-1-5': 0.08653846153846154, 'col-2-1': 0.1346153846153846, 'col-3-1': 1, }, @@ -184,12 +184,12 @@ describe('computePercentageData', () => { { 'col-0-4': 'Kibana Airlines', 'col-1-5': 0.38095238095238093, - 'col-2-1': 0.619047619047619, + 'col-2-1': 0.6190476190476191, 'col-3-1': 1, }, { 'col-0-4': 'JetBeats', - 'col-1-5': 0.10576923076923078, + 'col-1-5': 0.10576923076923077, 'col-2-1': 0.6923076923076923, 'col-3-1': 0, }, @@ -202,13 +202,13 @@ describe('computePercentageData', () => { { 'col-0-4': 'Logstash Airways', 'col-1-5': 0.06578947368421052, - 'col-2-1': 0.9342105263157894, + 'col-2-1': 0.9342105263157895, 'col-3-1': 1, }, { 'col-0-4': 'Logstash Airways', - 'col-1-5': 0.411764705882353, - 'col-2-1': 0.5882352941176472, + 'col-1-5': 0.4117647058823529, + 'col-2-1': 0.5882352941176471, 'col-3-1': 0, }, ]); diff --git a/src/plugins/vis_types/xy/public/utils/compute_percentage_data.ts b/src/plugins/vis_types/xy/public/utils/compute_percentage_data.ts index 67e04a980d3c9..78457c2fd56cd 100644 --- a/src/plugins/vis_types/xy/public/utils/compute_percentage_data.ts +++ b/src/plugins/vis_types/xy/public/utils/compute_percentage_data.ts @@ -5,9 +5,9 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { groupBy } from 'lodash'; -import { Accessor, AccessorFn } from '@elastic/charts'; -import { DatatableRow } from '../../../../expressions/public'; +import type { Accessor, AccessorFn } from '@elastic/charts'; +import { computeRatioByGroups } from '@elastic/charts'; +import type { DatatableRow } from '../../../../expressions/public'; export const computePercentageData = ( rows: DatatableRow[], @@ -15,52 +15,17 @@ export const computePercentageData = ( yAccessors: string[], splitChartAccessor?: string | null ) => { - // Group by xAccessor - const groupedData = groupBy(rows, function (row) { - return row[String(xAccessor)]; - }); - // In case of small multiples, I need to group by xAccessor and splitChartAccessor + // compute percentage mode data + const groupAccessors = [String(xAccessor)]; if (splitChartAccessor) { - for (const key in groupedData) { - if (Object.prototype.hasOwnProperty.call(groupedData, key)) { - const groupedBySplitData = groupBy(groupedData[key], splitChartAccessor); - for (const newGroupKey in groupedBySplitData) { - if (Object.prototype.hasOwnProperty.call(groupedBySplitData, newGroupKey)) { - groupedData[`${key}-${newGroupKey}`] = groupedBySplitData[newGroupKey]; - } - } - } - } + groupAccessors.push(splitChartAccessor); } - // sum up all the yAccessors per group - const sums: Record = {}; - for (const key in groupedData) { - if (Object.prototype.hasOwnProperty.call(groupedData, key)) { - let sum = 0; - const array = groupedData[key]; - array.forEach((row) => { - for (const yAccessor of yAccessors) { - sum += row[yAccessor]; - } - }); - sums[key] = sum; - } - } - // compute the ratio of each group - rows.forEach((row) => { - const groupValue = splitChartAccessor - ? `${row[String(xAccessor)]}-${row[splitChartAccessor]}` - : row[String(xAccessor)]; - const sum = sums[groupValue] ?? 0; - let metricsSum = 0; - for (const yAccessor of yAccessors) { - metricsSum += row[yAccessor]; - } - const computedMetric = metricsSum / sum; - for (const yAccessor of yAccessors) { - row[yAccessor] = (computedMetric / metricsSum) * row[yAccessor]; - } - }); - return rows; + return computeRatioByGroups( + rows, + groupAccessors, + yAccessors.map((accessor) => { + return [(d) => d[accessor], (d, v) => ({ ...d, [accessor]: v })]; + }) + ); }; diff --git a/src/plugins/visualizations/common/locator.ts b/src/plugins/visualizations/common/locator.ts index b294019e83392..a1d15ee5188d3 100644 --- a/src/plugins/visualizations/common/locator.ts +++ b/src/plugins/visualizations/common/locator.ts @@ -11,10 +11,9 @@ import { omitBy } from 'lodash'; import type { ParsedQuery } from 'query-string'; import { stringify } from 'query-string'; import rison from 'rison-node'; -import { Filter } from '@kbn/es-query'; +import { Filter, isFilterPinned } from '@kbn/es-query'; import type { Query, RefreshInterval, TimeRange } from 'src/plugins/data/common'; import type { LocatorDefinition, LocatorPublic } from 'src/plugins/share/common'; -import { isFilterPinned } from '../../data/common'; import { url } from '../../kibana_utils/common'; import { GLOBAL_STATE_STORAGE_KEY, STATE_STORAGE_KEY, VisualizeConstants } from './constants'; import type { SavedVisState } from './types'; diff --git a/src/plugins/visualizations/public/vis.test.ts b/src/plugins/visualizations/public/vis.test.ts index bfe69f9c59a36..a3fb8abf76bcd 100644 --- a/src/plugins/visualizations/public/vis.test.ts +++ b/src/plugins/visualizations/public/vis.test.ts @@ -38,7 +38,7 @@ jest.mock('./services', () => { getTypes: () => ({ get: () => visType }), getAggs: () => ({ createAggConfigs: (indexPattern: any, cfg: any) => ({ - aggs: cfg.map((aggConfig: any) => ({ ...aggConfig, toJSON: () => aggConfig })), + aggs: cfg.map((aggConfig: any) => ({ ...aggConfig, serialize: () => aggConfig })), }), }), getSearch: () => ({ diff --git a/src/plugins/visualizations/public/vis.ts b/src/plugins/visualizations/public/vis.ts index fd9bb434a7cf0..821becf3da9c1 100644 --- a/src/plugins/visualizations/public/vis.ts +++ b/src/plugins/visualizations/public/vis.ts @@ -189,7 +189,7 @@ export class Vis { } serialize(): SerializedVis { - const aggs = this.data.aggs ? this.data.aggs.aggs.map((agg) => agg.toJSON()) : []; + const aggs = this.data.aggs ? this.data.aggs.aggs.map((agg) => agg.serialize()) : []; return { id: this.id, title: this.title, diff --git a/test/functional/apps/console/_console.ts b/test/functional/apps/console/_console.ts index 7a8a36bec56d7..12d3663ebecbb 100644 --- a/test/functional/apps/console/_console.ts +++ b/test/functional/apps/console/_console.ts @@ -27,7 +27,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'console']); const toasts = getService('toasts'); - describe('console app', function describeIndexTests() { + // FLAKY: https://github.com/elastic/kibana/issues/124104 + describe.skip('console app', function describeIndexTests() { this.tags('includeFirefox'); before(async () => { log.debug('navigateTo console'); @@ -92,24 +93,24 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); }); - // Flaky, see https://github.com/elastic/kibana/issues/123556 - it.skip('should add comma after previous non empty line on autocomplete', async () => { - const LINE_NUMBER = 2; + it('should add comma after previous non empty line on autocomplete', async () => { + const LINE_NUMBER = 4; await PageObjects.console.dismissTutorial(); await PageObjects.console.clearTextArea(); + await PageObjects.console.enterRequest(); + await PageObjects.console.enterText(`{\n\t"query": {\n\t\t"match": {}`); await PageObjects.console.pressEnter(); await PageObjects.console.pressEnter(); await PageObjects.console.pressEnter(); await PageObjects.console.promptAutocomplete(); + await PageObjects.console.pressEnter(); - await retry.try(async () => { - const textOfPreviousNonEmptyLine = await PageObjects.console.getVisibleTextAt(LINE_NUMBER); - log.debug(textOfPreviousNonEmptyLine); - const lastChar = textOfPreviousNonEmptyLine.charAt(textOfPreviousNonEmptyLine.length - 1); - expect(lastChar).to.be.equal(','); - }); + const textOfPreviousNonEmptyLine = await PageObjects.console.getVisibleTextAt(LINE_NUMBER); + log.debug(textOfPreviousNonEmptyLine); + const lastChar = textOfPreviousNonEmptyLine.charAt(textOfPreviousNonEmptyLine.length - 1); + expect(lastChar).to.be.equal(','); }); describe('with a data URI in the load_from query', () => { diff --git a/test/functional/apps/console/index.js b/test/functional/apps/console/index.js index dc3f60570b495..55f9dffdedb06 100644 --- a/test/functional/apps/console/index.js +++ b/test/functional/apps/console/index.js @@ -9,7 +9,8 @@ export default function ({ getService, loadTestFile }) { const browser = getService('browser'); - describe('console app', function () { + // FLAKY: https://github.com/elastic/kibana/issues/123556 + describe.skip('console app', function () { this.tags('ciGroup1'); before(async function () { diff --git a/test/functional/apps/discover/_data_view_editor.ts b/test/functional/apps/discover/_data_view_editor.ts new file mode 100644 index 0000000000000..c67964fddf93b --- /dev/null +++ b/test/functional/apps/discover/_data_view_editor.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from './ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const testSubjects = getService('testSubjects'); + const kibanaServer = getService('kibanaServer'); + const esArchiver = getService('esArchiver'); + const security = getService('security'); + const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']); + const defaultSettings = { + defaultIndex: 'logstash-*', + }; + + const createDataView = async (dataViewName: string) => { + await PageObjects.discover.clickIndexPatternActions(); + await PageObjects.discover.clickCreateNewDataView(); + await testSubjects.setValue('createIndexPatternNameInput', dataViewName, { + clearWithKeyboard: true, + typeCharByChar: true, + }); + await testSubjects.click('saveIndexPatternButton'); + }; + + describe('discover integration with data view editor', function describeIndexTests() { + before(async function () { + await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await kibanaServer.savedObjects.clean({ types: ['saved-search', 'index-pattern'] }); + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover'); + await kibanaServer.uiSettings.replace(defaultSettings); + await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); + await PageObjects.common.navigateToApp('discover'); + }); + + after(async () => { + await security.testUser.restoreDefaults(); + await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover'); + await kibanaServer.savedObjects.clean({ types: ['saved-search', 'index-pattern'] }); + }); + + it('allows creating a new data view', async function () { + const dataViewToCreate = 'logstash'; + await createDataView(dataViewToCreate); + await PageObjects.header.waitUntilLoadingHasFinished(); + await retry.waitForWithTimeout( + 'data view selector to include a newly created dataview', + 5000, + async () => { + const dataViewTitle = await PageObjects.discover.getCurrentlySelectedDataView(); + // data view editor will add wildcard symbol by default + // so we need to include it in our original title when comparing + return dataViewTitle === `${dataViewToCreate}*`; + } + ); + }); + }); +} diff --git a/test/functional/apps/discover/index.ts b/test/functional/apps/discover/index.ts index b5eb160526876..d2b627c175fcc 100644 --- a/test/functional/apps/discover/index.ts +++ b/test/functional/apps/discover/index.ts @@ -54,6 +54,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./_search_on_page_load')); loadTestFile(require.resolve('./_chart_hidden')); loadTestFile(require.resolve('./_context_encoded_url_param')); + loadTestFile(require.resolve('./_data_view_editor')); loadTestFile(require.resolve('./_empty_state')); }); } diff --git a/test/functional/page_objects/console_page.ts b/test/functional/page_objects/console_page.ts index f8a64c0032bb2..4fdc47756e710 100644 --- a/test/functional/page_objects/console_page.ts +++ b/test/functional/page_objects/console_page.ts @@ -110,9 +110,11 @@ export class ConsolePageObject extends FtrService { private async getEditorTextArea() { // This focusses the cursor on the bottom of the text area - const editor = await this.getEditor(); - const content = await editor.findByCssSelector('.ace_content'); - await content.click(); + await this.retry.try(async () => { + const editor = await this.getEditor(); + const content = await editor.findByCssSelector('.ace_content'); + await content.click(); + }); return await this.testSubjects.find('console-textarea'); } @@ -137,6 +139,8 @@ export class ConsolePageObject extends FtrService { public async clearTextArea() { const textArea = await this.getEditorTextArea(); - await textArea.clearValueWithKeyboard(); + await this.retry.try(async () => { + await textArea.clearValueWithKeyboard(); + }); } } diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index f9328e89cd19e..effacb30bdc89 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -363,6 +363,13 @@ export class DiscoverPageObject extends FtrService { }); } + public async clickCreateNewDataView() { + await this.retry.try(async () => { + await this.testSubjects.click('dataview-create-new'); + await this.find.byClassName('indexPatternEditor__form'); + }); + } + public async hasNoResults() { return await this.testSubjects.exists('discoverNoResults'); } @@ -598,4 +605,10 @@ export class DiscoverPageObject extends FtrService { await this.testSubjects.existOrFail('dscFieldStatsEmbeddedContent'); }); } + + public async getCurrentlySelectedDataView() { + await this.testSubjects.existOrFail('discover-sidebar'); + const button = await this.testSubjects.find('indexPattern-switch-link'); + return button.getAttribute('title'); + } } diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/create_jwt_assertion.test.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/create_jwt_assertion.test.ts index abeb14de4c43b..ed6497573a362 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/create_jwt_assertion.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/create_jwt_assertion.test.ts @@ -8,7 +8,7 @@ jest.mock('jsonwebtoken', () => ({ sign: jest.fn(), })); -// eslint-disable-next-line import/no-extraneous-dependencies + import jwt from 'jsonwebtoken'; import { Logger } from '../../../../../../src/core/server'; import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/create_jwt_assertion.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/create_jwt_assertion.ts index 9f5102b336eda..79230a99a3822 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/create_jwt_assertion.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/create_jwt_assertion.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -// eslint-disable-next-line import/no-extraneous-dependencies + import jwt, { Algorithm } from 'jsonwebtoken'; import { Logger } from '../../../../../../src/core/server'; diff --git a/x-pack/plugins/alerting/common/alert.ts b/x-pack/plugins/alerting/common/alert.ts index 6f07d4b795063..933e51d6a8174 100644 --- a/x-pack/plugins/alerting/common/alert.ts +++ b/x-pack/plugins/alerting/common/alert.ts @@ -36,6 +36,7 @@ export enum AlertExecutionStatusErrorReasons { export interface AlertExecutionStatus { status: AlertExecutionStatuses; + numberOfTriggeredActions?: number; lastExecutionDate: Date; lastDuration?: number; error?: { @@ -137,13 +138,19 @@ export interface ActionVariable { useWithTripleBracesInTemplates?: boolean; } +export interface RuleMonitoringHistory extends SavedObjectAttributes { + success: boolean; + timestamp: number; + duration?: number; +} + export interface RuleMonitoring extends SavedObjectAttributes { execution: { - history: Array<{ - success: boolean; - timestamp: number; - }>; + history: RuleMonitoringHistory[]; calculated_metrics: { + p50?: number; + p95?: number; + p99?: number; success_ratio: number; }; }; diff --git a/x-pack/plugins/alerting/common/index.ts b/x-pack/plugins/alerting/common/index.ts index d76a79358198f..8a6fec74fb619 100644 --- a/x-pack/plugins/alerting/common/index.ts +++ b/x-pack/plugins/alerting/common/index.ts @@ -31,3 +31,4 @@ export const LEGACY_BASE_ALERT_API_PATH = '/api/alerts'; export const BASE_ALERTING_API_PATH = '/api/alerting'; export const INTERNAL_BASE_ALERTING_API_PATH = '/internal/alerting'; export const ALERTS_FEATURE_ID = 'alerts'; +export const MONITORING_HISTORY_LIMIT = 200; diff --git a/x-pack/plugins/alerting/common/rule_task_instance.ts b/x-pack/plugins/alerting/common/rule_task_instance.ts index fdd308a6395a1..10d71591e6448 100644 --- a/x-pack/plugins/alerting/common/rule_task_instance.ts +++ b/x-pack/plugins/alerting/common/rule_task_instance.ts @@ -9,6 +9,13 @@ import * as t from 'io-ts'; import { rawAlertInstance } from './alert_instance'; import { DateFromString } from './date_from_string'; +const actionSchema = t.partial({ + group: t.string, + id: t.string, + actionTypeId: t.string, + params: t.record(t.string, t.unknown), +}); + export const ruleStateSchema = t.partial({ alertTypeState: t.record(t.string, t.unknown), alertInstances: t.record(t.string, rawAlertInstance), @@ -16,6 +23,9 @@ export const ruleStateSchema = t.partial({ }); export type RuleTaskState = t.TypeOf; +export type RuleTaskStateWithActions = RuleTaskState & { + triggeredActions: Array>; +}; export const ruleParamsSchema = t.intersection([ t.type({ diff --git a/x-pack/plugins/alerting/server/lib/monitoring.test.ts b/x-pack/plugins/alerting/server/lib/monitoring.test.ts new file mode 100644 index 0000000000000..eeafdfcff1cbe --- /dev/null +++ b/x-pack/plugins/alerting/server/lib/monitoring.test.ts @@ -0,0 +1,78 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getExecutionDurationPercentiles } from './monitoring'; +import { RuleMonitoring } from '../types'; + +const mockHistory = [ + { + success: true, + duration: 100, + }, + { + success: true, + duration: 200, + }, + { + success: false, + duration: 300, + }, + { + success: false, + duration: 100, + }, + { + success: false, + }, + { + success: true, + }, + { + success: true, + duration: 400, + }, + { + success: true, + duration: 500, + }, +]; + +const mockRuleMonitoring = { + execution: { + history: mockHistory, + calculated_metrics: { + success_ratio: 0, + }, + }, +} as RuleMonitoring; + +describe('getExecutionDurationPercentiles', () => { + it('Calculates the percentile given partly undefined durations', () => { + const percentiles = getExecutionDurationPercentiles(mockRuleMonitoring); + expect(percentiles.p50).toEqual(250); + expect(percentiles.p95).toEqual(500); + expect(percentiles.p99).toEqual(500); + }); + + it('Returns empty object when given all undefined durations', () => { + // remove all duration fields + const nullDurationHistory = mockHistory.map((history) => ({ + success: history.success, + })); + + const newMockRuleMonitoring = { + ...mockRuleMonitoring, + execution: { + ...mockRuleMonitoring.execution, + history: nullDurationHistory, + }, + } as RuleMonitoring; + + const percentiles = getExecutionDurationPercentiles(newMockRuleMonitoring); + expect(Object.keys(percentiles).length).toEqual(0); + }); +}); diff --git a/x-pack/plugins/alerting/server/lib/monitoring.ts b/x-pack/plugins/alerting/server/lib/monitoring.ts new file mode 100644 index 0000000000000..d817b10225ee0 --- /dev/null +++ b/x-pack/plugins/alerting/server/lib/monitoring.ts @@ -0,0 +1,33 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import stats from 'stats-lite'; +import { RuleMonitoring } from '../types'; + +export const getExecutionSuccessRatio = (ruleMonitoring: RuleMonitoring) => { + const { history } = ruleMonitoring.execution; + return history.filter(({ success }) => success).length / history.length; +}; + +export const getExecutionDurationPercentiles = (ruleMonitoring: RuleMonitoring) => { + const durationSamples = ruleMonitoring.execution.history.reduce((duration, history) => { + if (typeof history.duration === 'number') { + return [...duration, history.duration]; + } + return duration; + }, []); + + if (durationSamples.length) { + return { + p50: stats.percentile(durationSamples as number[], 0.5), + p95: stats.percentile(durationSamples as number[], 0.95), + p99: stats.percentile(durationSamples as number[], 0.99), + }; + } + + return {}; +}; 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 4ee5bbe48c162..2251d9b0b2561 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 @@ -6,7 +6,7 @@ */ import { loggingSystemMock } from '../../../../../src/core/server/mocks'; -import { AlertExecutionStatusErrorReasons } from '../types'; +import { AlertAction, AlertExecutionStatusErrorReasons, RuleTaskStateWithActions } from '../types'; import { executionStatusFromState, executionStatusFromError, @@ -24,22 +24,36 @@ describe('RuleExecutionStatus', () => { describe('executionStatusFromState()', () => { test('empty task state', () => { - const status = executionStatusFromState({}); + const status = executionStatusFromState({} as RuleTaskStateWithActions); checkDateIsNearNow(status.lastExecutionDate); + expect(status.numberOfTriggeredActions).toBe(0); expect(status.status).toBe('ok'); expect(status.error).toBe(undefined); }); test('task state with no instances', () => { - const status = executionStatusFromState({ alertInstances: {} }); + const status = executionStatusFromState({ alertInstances: {}, triggeredActions: [] }); checkDateIsNearNow(status.lastExecutionDate); + expect(status.numberOfTriggeredActions).toBe(0); expect(status.status).toBe('ok'); expect(status.error).toBe(undefined); }); test('task state with one instance', () => { - const status = executionStatusFromState({ alertInstances: { a: {} } }); + const status = executionStatusFromState({ alertInstances: { a: {} }, triggeredActions: [] }); checkDateIsNearNow(status.lastExecutionDate); + expect(status.numberOfTriggeredActions).toBe(0); + expect(status.status).toBe('active'); + expect(status.error).toBe(undefined); + }); + + test('task state with numberOfTriggeredActions', () => { + const status = executionStatusFromState({ + triggeredActions: [{ group: '1' } as AlertAction], + alertInstances: { a: {} }, + }); + checkDateIsNearNow(status.lastExecutionDate); + expect(status.numberOfTriggeredActions).toBe(1); expect(status.status).toBe('active'); expect(status.error).toBe(undefined); }); @@ -114,6 +128,19 @@ describe('RuleExecutionStatus', () => { } `); }); + + test('status with a numberOfTriggeredActions', () => { + expect( + ruleExecutionStatusToRaw({ lastExecutionDate: date, status, numberOfTriggeredActions: 5 }) + ).toMatchInlineSnapshot(` + Object { + "error": null, + "lastDuration": 0, + "lastExecutionDate": "2020-09-03T16:26:58.000Z", + "status": "ok", + } + `); + }); }); describe('ruleExecutionStatusFromRaw()', () => { @@ -226,6 +253,28 @@ describe('RuleExecutionStatus', () => { } `); }); + + test('valid status, date, error, duration and triggeredActions', () => { + const result = ruleExecutionStatusFromRaw(MockLogger, 'rule-id', { + status, + lastExecutionDate: date, + numberOfTriggeredActions: 5, + error, + lastDuration: 1234, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "error": Object { + "message": "wops", + "reason": "execute", + }, + "lastDuration": 1234, + "lastExecutionDate": 2020-09-03T16:26:58.000Z, + "numberOfTriggeredActions": 5, + "status": "active", + } + `); + }); }); }); 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 f631884de12c5..5de59dd517229 100644 --- a/x-pack/plugins/alerting/server/lib/rule_execution_status.ts +++ b/x-pack/plugins/alerting/server/lib/rule_execution_status.ts @@ -6,14 +6,15 @@ */ import { Logger } from 'src/core/server'; -import { RuleTaskState, AlertExecutionStatus, RawRuleExecutionStatus } from '../types'; +import { AlertExecutionStatus, RawRuleExecutionStatus, RuleTaskStateWithActions } from '../types'; import { getReasonFromError } from './error_with_reason'; import { getEsErrorMessage } from './errors'; import { AlertExecutionStatuses } from '../../common'; -export function executionStatusFromState(state: RuleTaskState): AlertExecutionStatus { +export function executionStatusFromState(state: RuleTaskStateWithActions): AlertExecutionStatus { const alertIds = Object.keys(state.alertInstances ?? {}); return { + numberOfTriggeredActions: state.triggeredActions?.length ?? 0, lastExecutionDate: new Date(), status: alertIds.length === 0 ? 'ok' : 'active', }; @@ -52,7 +53,13 @@ export function ruleExecutionStatusFromRaw( ): AlertExecutionStatus | undefined { if (!rawRuleExecutionStatus) return undefined; - const { lastExecutionDate, lastDuration, status = 'unknown', error } = rawRuleExecutionStatus; + const { + lastExecutionDate, + lastDuration, + numberOfTriggeredActions, + status = 'unknown', + error, + } = rawRuleExecutionStatus; let parsedDateMillis = lastExecutionDate ? Date.parse(lastExecutionDate) : Date.now(); if (isNaN(parsedDateMillis)) { @@ -71,6 +78,10 @@ export function ruleExecutionStatusFromRaw( executionStatus.lastDuration = lastDuration; } + if (null != numberOfTriggeredActions) { + executionStatus.numberOfTriggeredActions = numberOfTriggeredActions; + } + if (error) { executionStatus.error = error; } diff --git a/x-pack/plugins/alerting/server/saved_objects/mappings.json b/x-pack/plugins/alerting/server/saved_objects/mappings.json index 6923c94ec60a0..d6ebd25d4af37 100644 --- a/x-pack/plugins/alerting/server/saved_objects/mappings.json +++ b/x-pack/plugins/alerting/server/saved_objects/mappings.json @@ -99,6 +99,9 @@ "properties": { "history": { "properties": { + "duration": { + "type": "long" + }, "success": { "type": "boolean" }, @@ -109,6 +112,15 @@ }, "calculated_metrics": { "properties": { + "p50": { + "type": "long" + }, + "p95": { + "type": "long" + }, + "p99": { + "type": "long" + }, "success_ratio": { "type": "float" } @@ -120,6 +132,9 @@ }, "executionStatus": { "properties": { + "numberOfTriggeredActions": { + "type": "long" + }, "status": { "type": "keyword" }, 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 3442216a2f1fd..5ef1d67298b4e 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 @@ -103,34 +103,36 @@ const createExecutionHandlerParams: jest.Mocked< maxEphemeralActionsPerRule: 10, }; -beforeEach(() => { - jest.resetAllMocks(); - jest - .requireMock('./inject_action_params') - .injectActionParams.mockImplementation( - ({ actionParams }: InjectActionParamsOpts) => actionParams +describe('Create Execution Handler', () => { + beforeEach(() => { + jest.resetAllMocks(); + jest + .requireMock('./inject_action_params') + .injectActionParams.mockImplementation( + ({ actionParams }: InjectActionParamsOpts) => actionParams + ); + mockActionsPlugin.isActionTypeEnabled.mockReturnValue(true); + mockActionsPlugin.isActionExecutable.mockReturnValue(true); + mockActionsPlugin.getActionsClientWithRequest.mockResolvedValue(actionsClient); + mockActionsPlugin.renderActionParameterTemplates.mockImplementation( + renderActionParameterTemplatesDefault ); - mockActionsPlugin.isActionTypeEnabled.mockReturnValue(true); - mockActionsPlugin.isActionExecutable.mockReturnValue(true); - mockActionsPlugin.getActionsClientWithRequest.mockResolvedValue(actionsClient); - mockActionsPlugin.renderActionParameterTemplates.mockImplementation( - renderActionParameterTemplatesDefault - ); -}); - -test('enqueues execution per selected action', async () => { - const executionHandler = createExecutionHandler(createExecutionHandlerParams); - await executionHandler({ - actionGroup: 'default', - state: {}, - context: {}, - alertId: '2', }); - expect(mockActionsPlugin.getActionsClientWithRequest).toHaveBeenCalledWith( - createExecutionHandlerParams.request - ); - expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); - expect(actionsClient.enqueueExecution.mock.calls[0]).toMatchInlineSnapshot(` + + test('enqueues execution per selected action', async () => { + const executionHandler = createExecutionHandler(createExecutionHandlerParams); + const result = await executionHandler({ + actionGroup: 'default', + state: {}, + context: {}, + alertId: '2', + }); + expect(result).toHaveLength(1); + expect(mockActionsPlugin.getActionsClientWithRequest).toHaveBeenCalledWith( + createExecutionHandlerParams.request + ); + expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); + expect(actionsClient.enqueueExecution.mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { "apiKey": "MTIzOmFiYw==", @@ -162,8 +164,8 @@ test('enqueues execution per selected action', async () => { ] `); - expect(mockEventLogger.logEvent).toHaveBeenCalledTimes(1); - expect(mockEventLogger.logEvent.mock.calls).toMatchInlineSnapshot(` + expect(mockEventLogger.logEvent).toHaveBeenCalledTimes(1); + expect(mockEventLogger.logEvent.mock.calls).toMatchInlineSnapshot(` Array [ Array [ Object { @@ -215,137 +217,139 @@ test('enqueues execution per selected action', async () => { ] `); - expect(jest.requireMock('./inject_action_params').injectActionParams).toHaveBeenCalledWith({ - ruleId: '1', - spaceId: 'test1', - actionTypeId: 'test', - actionParams: { - alertVal: 'My 1 name-of-alert test1 tag-A,tag-B 2 goes here', - contextVal: 'My goes here', - foo: true, - stateVal: 'My goes here', - }, + expect(jest.requireMock('./inject_action_params').injectActionParams).toHaveBeenCalledWith({ + ruleId: '1', + spaceId: 'test1', + actionTypeId: 'test', + actionParams: { + alertVal: 'My 1 name-of-alert test1 tag-A,tag-B 2 goes here', + contextVal: 'My goes here', + foo: true, + stateVal: 'My goes here', + }, + }); }); -}); -test(`doesn't call actionsPlugin.execute for disabled actionTypes`, async () => { - // Mock two calls, one for check against actions[0] and the second for actions[1] - mockActionsPlugin.isActionExecutable.mockReturnValueOnce(false); - mockActionsPlugin.isActionTypeEnabled.mockReturnValueOnce(false); - mockActionsPlugin.isActionTypeEnabled.mockReturnValueOnce(true); - const executionHandler = createExecutionHandler({ - ...createExecutionHandlerParams, - actions: [ - ...createExecutionHandlerParams.actions, - { - id: '2', - group: 'default', - actionTypeId: 'test2', - params: { - foo: true, - contextVal: 'My other {{context.value}} goes here', - stateVal: 'My other {{state.value}} goes here', + test(`doesn't call actionsPlugin.execute for disabled actionTypes`, async () => { + // Mock two calls, one for check against actions[0] and the second for actions[1] + mockActionsPlugin.isActionExecutable.mockReturnValueOnce(false); + mockActionsPlugin.isActionTypeEnabled.mockReturnValueOnce(false); + mockActionsPlugin.isActionTypeEnabled.mockReturnValueOnce(true); + const executionHandler = createExecutionHandler({ + ...createExecutionHandlerParams, + actions: [ + ...createExecutionHandlerParams.actions, + { + id: '2', + group: 'default', + actionTypeId: 'test2', + params: { + foo: true, + contextVal: 'My other {{context.value}} goes here', + stateVal: 'My other {{state.value}} goes here', + }, }, + ], + }); + await executionHandler({ + actionGroup: 'default', + state: {}, + context: {}, + alertId: '2', + }); + expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); + expect(actionsClient.enqueueExecution).toHaveBeenCalledWith({ + id: '2', + params: { + foo: true, + contextVal: 'My other goes here', + stateVal: 'My other goes here', }, - ], - }); - await executionHandler({ - actionGroup: 'default', - state: {}, - context: {}, - alertId: '2', - }); - expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); - expect(actionsClient.enqueueExecution).toHaveBeenCalledWith({ - id: '2', - params: { - foo: true, - contextVal: 'My other goes here', - stateVal: 'My other goes here', - }, - source: asSavedObjectExecutionSource({ - id: '1', - type: 'alert', - }), - relatedSavedObjects: [ - { + source: asSavedObjectExecutionSource({ id: '1', - namespace: 'test1', type: 'alert', - typeId: 'test', - }, - ], - spaceId: 'test1', - apiKey: createExecutionHandlerParams.apiKey, - executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }); -}); - -test('trow error error message when action type is disabled', async () => { - mockActionsPlugin.preconfiguredActions = []; - mockActionsPlugin.isActionExecutable.mockReturnValue(false); - mockActionsPlugin.isActionTypeEnabled.mockReturnValue(false); - const executionHandler = createExecutionHandler({ - ...createExecutionHandlerParams, - actions: [ - ...createExecutionHandlerParams.actions, - { - id: '2', - group: 'default', - actionTypeId: '.slack', - params: { - foo: true, - contextVal: 'My other {{context.value}} goes here', - stateVal: 'My other {{state.value}} goes here', + }), + relatedSavedObjects: [ + { + id: '1', + namespace: 'test1', + type: 'alert', + typeId: 'test', }, - }, - ], + ], + spaceId: 'test1', + apiKey: createExecutionHandlerParams.apiKey, + executionId: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }); }); - await executionHandler({ - actionGroup: 'default', - state: {}, - context: {}, - alertId: '2', - }); + test('trow error error message when action type is disabled', async () => { + mockActionsPlugin.preconfiguredActions = []; + mockActionsPlugin.isActionExecutable.mockReturnValue(false); + mockActionsPlugin.isActionTypeEnabled.mockReturnValue(false); + const executionHandler = createExecutionHandler({ + ...createExecutionHandlerParams, + actions: [ + ...createExecutionHandlerParams.actions, + { + id: '2', + group: 'default', + actionTypeId: '.slack', + params: { + foo: true, + contextVal: 'My other {{context.value}} goes here', + stateVal: 'My other {{state.value}} goes here', + }, + }, + ], + }); - expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(0); + const result = await executionHandler({ + actionGroup: 'default', + state: {}, + context: {}, + alertId: '2', + }); + expect(result).toEqual([]); + expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(0); - mockActionsPlugin.isActionExecutable.mockImplementation(() => true); - const executionHandlerForPreconfiguredAction = createExecutionHandler({ - ...createExecutionHandlerParams, - actions: [...createExecutionHandlerParams.actions], - }); - await executionHandlerForPreconfiguredAction({ - actionGroup: 'default', - state: {}, - context: {}, - alertId: '2', + mockActionsPlugin.isActionExecutable.mockImplementation(() => true); + const executionHandlerForPreconfiguredAction = createExecutionHandler({ + ...createExecutionHandlerParams, + actions: [...createExecutionHandlerParams.actions], + }); + await executionHandlerForPreconfiguredAction({ + actionGroup: 'default', + state: {}, + context: {}, + alertId: '2', + }); + expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); }); - expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); -}); -test('limits actionsPlugin.execute per action group', async () => { - const executionHandler = createExecutionHandler(createExecutionHandlerParams); - await executionHandler({ - actionGroup: 'other-group', - state: {}, - context: {}, - alertId: '2', + test('limits actionsPlugin.execute per action group', async () => { + const executionHandler = createExecutionHandler(createExecutionHandlerParams); + const result = await executionHandler({ + actionGroup: 'other-group', + state: {}, + context: {}, + alertId: '2', + }); + expect(result).toEqual([]); + expect(actionsClient.enqueueExecution).not.toHaveBeenCalled(); }); - expect(actionsClient.enqueueExecution).not.toHaveBeenCalled(); -}); -test('context attribute gets parameterized', async () => { - const executionHandler = createExecutionHandler(createExecutionHandlerParams); - await executionHandler({ - actionGroup: 'default', - context: { value: 'context-val' }, - state: {}, - alertId: '2', - }); - expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); - expect(actionsClient.enqueueExecution.mock.calls[0]).toMatchInlineSnapshot(` + test('context attribute gets parameterized', async () => { + const executionHandler = createExecutionHandler(createExecutionHandlerParams); + const result = await executionHandler({ + actionGroup: 'default', + context: { value: 'context-val' }, + state: {}, + alertId: '2', + }); + expect(result).toHaveLength(1); + expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); + expect(actionsClient.enqueueExecution.mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { "apiKey": "MTIzOmFiYw==", @@ -376,18 +380,19 @@ test('context attribute gets parameterized', async () => { }, ] `); -}); - -test('state attribute gets parameterized', async () => { - const executionHandler = createExecutionHandler(createExecutionHandlerParams); - await executionHandler({ - actionGroup: 'default', - context: {}, - state: { value: 'state-val' }, - alertId: '2', }); - expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); - expect(actionsClient.enqueueExecution.mock.calls[0]).toMatchInlineSnapshot(` + + test('state attribute gets parameterized', async () => { + const executionHandler = createExecutionHandler(createExecutionHandlerParams); + const result = await executionHandler({ + actionGroup: 'default', + context: {}, + state: { value: 'state-val' }, + alertId: '2', + }); + expect(result).toHaveLength(1); + expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); + expect(actionsClient.enqueueExecution.mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { "apiKey": "MTIzOmFiYw==", @@ -418,20 +423,21 @@ test('state attribute gets parameterized', async () => { }, ] `); -}); + }); -test(`logs an error when action group isn't part of actionGroups available for the ruleType`, async () => { - const executionHandler = createExecutionHandler(createExecutionHandlerParams); - const result = await executionHandler({ - // we have to trick the compiler as this is an invalid type and this test checks whether we - // enforce this at runtime as well as compile time - actionGroup: 'invalid-group' as 'default' | 'other-group', - context: {}, - state: {}, - alertId: '2', + test(`logs an error when action group isn't part of actionGroups available for the ruleType`, async () => { + const executionHandler = createExecutionHandler(createExecutionHandlerParams); + const result = await executionHandler({ + // we have to trick the compiler as this is an invalid type and this test checks whether we + // enforce this at runtime as well as compile time + actionGroup: 'invalid-group' as 'default' | 'other-group', + context: {}, + state: {}, + alertId: '2', + }); + expect(result).toEqual([]); + expect(createExecutionHandlerParams.logger.error).toHaveBeenCalledWith( + 'Invalid action group "invalid-group" for rule "test".' + ); }); - expect(result).toBeUndefined(); - expect(createExecutionHandlerParams.logger.error).toHaveBeenCalledWith( - 'Invalid action group "invalid-group" for rule "test".' - ); }); 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 84f044f4041ba..febae5a092a32 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 @@ -70,7 +70,7 @@ interface ExecutionHandlerOptions { export type ExecutionHandler = ( options: ExecutionHandlerOptions -) => Promise; +) => Promise; export function createExecutionHandler< Params extends AlertTypeParams, @@ -116,9 +116,10 @@ export function createExecutionHandler< state, alertId, }: ExecutionHandlerOptions) => { + const triggeredActions: AlertAction[] = []; if (!ruleTypeActionGroups.has(actionGroup)) { logger.error(`Invalid action group "${actionGroup}" for rule "${ruleType.id}".`); - return; + return triggeredActions; } const actions = ruleActions .filter(({ group }) => group === actionGroup) @@ -160,6 +161,7 @@ export function createExecutionHandler< const actionsClient = await actionsPlugin.getActionsClientWithRequest(request); let ephemeralActionsToSchedule = maxEphemeralActionsPerRule; + for (const action of actions) { if ( !actionsPlugin.isActionExecutable(action.id, action.actionTypeId, { notifyUsage: true }) @@ -196,13 +198,18 @@ export function createExecutionHandler< const actionLabel = `${action.actionTypeId}:${action.id}`; if (supportsEphemeralTasks && ephemeralActionsToSchedule > 0) { ephemeralActionsToSchedule--; - actionsClient.ephemeralEnqueuedExecution(enqueueOptions).catch(async (err) => { + try { + await actionsClient.ephemeralEnqueuedExecution(enqueueOptions); + } catch (err) { if (isEphemeralTaskRejectedDueToCapacityError(err)) { await actionsClient.enqueueExecution(enqueueOptions); } - }); + } finally { + triggeredActions.push(action); + } } else { await actionsClient.enqueueExecution(enqueueOptions); + triggeredActions.push(action); } const event = createAlertEventLogRecordObject({ @@ -237,5 +244,6 @@ export function createExecutionHandler< eventLogger.logEvent(event); } + return triggeredActions; }; } 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 c4fc6b0171be0..402cc3951d39b 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 @@ -101,6 +101,8 @@ describe('Task Runner', () => { executionContext: ReturnType; }; + type EnqueueFunction = (options: ExecuteOptions) => Promise; + const taskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType = { getServices: jest.fn().mockReturnValue(services), actionsPlugin: actionsMock.createStart(), @@ -120,28 +122,7 @@ describe('Task Runner', () => { usageCounter: mockUsageCounter, }; - function testAgainstEphemeralSupport( - name: string, - fn: ( - params: TaskRunnerFactoryInitializerParamsType, - enqueueFunction: (options: ExecuteOptions) => Promise - ) => jest.ProvidesCallback - ) { - test(name, fn(taskRunnerFactoryInitializerParams, actionsClient.enqueueExecution)); - test( - `${name} (with ephemeral support)`, - fn( - { - ...taskRunnerFactoryInitializerParams, - supportsEphemeralTasks: true, - }, - actionsClient.ephemeralEnqueuedExecution - ) - ); - } - const mockDate = new Date('2019-02-12T21:01:22.479Z'); - const mockedRuleTypeSavedObject: Alert = { id: '1', consumer: 'bar', @@ -187,6 +168,27 @@ describe('Task Runner', () => { }, monitoring: getDefaultRuleMonitoring(), }; + const mockRunNowResponse = { + id: 1, + } as jest.ResolvedValue; + + const ephemeralTestParams: Array< + [ + nameExtension: string, + customTaskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType, + enqueueFunction: EnqueueFunction + ] + > = [ + ['', taskRunnerFactoryInitializerParams, actionsClient.enqueueExecution], + [ + ' (with ephemeral support)', + { + ...taskRunnerFactoryInitializerParams, + supportsEphemeralTasks: true, + }, + actionsClient.ephemeralEnqueuedExecution, + ], + ]; beforeEach(() => { jest.resetAllMocks(); @@ -316,7 +318,7 @@ describe('Task Runner', () => { expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); expect(logger.debug).nthCalledWith( 2, - 'ruleExecutionStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"ok"}' + 'ruleExecutionStatus for test:1: {"numberOfTriggeredActions":0,"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"ok"}' ); const eventLogger = taskRunnerFactoryInitializerParams.eventLogger; @@ -405,53 +407,49 @@ describe('Task Runner', () => { expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); }); - testAgainstEphemeralSupport( - 'actionsPlugin.execute is called per alert alert that is scheduled', - ( - customTaskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType, - enqueueFunction: (options: ExecuteOptions) => Promise - ) => - async () => { - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( - true - ); - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( - true - ); - actionsClient.ephemeralEnqueuedExecution.mockResolvedValue(new Promise(() => {})); - ruleType.executor.mockImplementation( - async ({ - services: executorServices, - }: AlertExecutorOptions< - AlertTypeParams, - AlertTypeState, - AlertInstanceState, - AlertInstanceContext, - string - >) => { - executorServices - .alertInstanceFactory('1') - .scheduleActionsWithSubGroup('default', 'subDefault'); - } - ); - const taskRunner = new TaskRunner( - ruleType, - mockedTaskInstance, - customTaskRunnerFactoryInitializerParams - ); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ - id: '1', - type: 'alert', - attributes: { - apiKey: Buffer.from('123:abc').toString('base64'), - enabled: true, - }, - references: [], - }); - await taskRunner.run(); - expect(enqueueFunction).toHaveBeenCalledTimes(1); - expect((enqueueFunction as jest.Mock).mock.calls[0]).toMatchInlineSnapshot(` + test.each(ephemeralTestParams)( + 'actionsPlugin.execute is called per alert alert that is scheduled %s', + async (nameExtension, customTaskRunnerFactoryInitializerParams, enqueueFunction) => { + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( + true + ); + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( + true + ); + actionsClient.ephemeralEnqueuedExecution.mockResolvedValue(mockRunNowResponse); + ruleType.executor.mockImplementation( + async ({ + services: executorServices, + }: AlertExecutorOptions< + AlertTypeParams, + AlertTypeState, + AlertInstanceState, + AlertInstanceContext, + string + >) => { + executorServices + .alertInstanceFactory('1') + .scheduleActionsWithSubGroup('default', 'subDefault'); + } + ); + const taskRunner = new TaskRunner( + ruleType, + mockedTaskInstance, + customTaskRunnerFactoryInitializerParams + ); + rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ + id: '1', + type: 'alert', + attributes: { + apiKey: Buffer.from('123:abc').toString('base64'), + enabled: true, + }, + references: [], + }); + await taskRunner.run(); + expect(enqueueFunction).toHaveBeenCalledTimes(1); + expect((enqueueFunction as jest.Mock).mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { "apiKey": "MTIzOmFiYw==", @@ -480,218 +478,221 @@ describe('Task Runner', () => { ] `); - const logger = customTaskRunnerFactoryInitializerParams.logger; - expect(logger.debug).toHaveBeenCalledTimes(4); - expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); - expect(logger.debug).nthCalledWith( - 2, - `rule test:1: 'rule-name' has 1 active alerts: [{\"instanceId\":\"1\",\"actionGroup\":\"default\"}]` - ); - expect(logger.debug).nthCalledWith( - 3, - 'ruleExecutionStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}' - ); - // ruleExecutionStatus for test:1: {\"lastExecutionDate\":\"1970-01-01T00:00:00.000Z\",\"status\":\"error\",\"error\":{\"reason\":\"unknown\",\"message\":\"Cannot read property 'catch' of undefined\"}} - - const eventLogger = customTaskRunnerFactoryInitializerParams.eventLogger; - expect(eventLogger.logEvent).toHaveBeenCalledTimes(5); - expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, { - event: { - action: 'execute-start', - category: ['alerts'], - kind: 'alert', - }, - kibana: { - alert: { - rule: { - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, + const logger = customTaskRunnerFactoryInitializerParams.logger; + expect(logger.debug).toHaveBeenCalledTimes(4); + expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); + expect(logger.debug).nthCalledWith( + 2, + `rule test:1: 'rule-name' has 1 active alerts: [{\"instanceId\":\"1\",\"actionGroup\":\"default\"}]` + ); + expect(logger.debug).nthCalledWith( + 3, + 'ruleExecutionStatus for test:1: {"numberOfTriggeredActions":1,"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}' + ); + // ruleExecutionStatus for test:1: {\"lastExecutionDate\":\"1970-01-01T00:00:00.000Z\",\"status\":\"error\",\"error\":{\"reason\":\"unknown\",\"message\":\"Cannot read property 'catch' of undefined\"}} + + const eventLogger = customTaskRunnerFactoryInitializerParams.eventLogger; + expect(eventLogger.logEvent).toHaveBeenCalledTimes(5); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(1, { + event: { + action: 'execute-start', + category: ['alerts'], + kind: 'alert', + }, + kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, - task: { - schedule_delay: 0, - scheduled: '1970-01-01T00:00:00.000Z', - }, - saved_objects: [ - { - id: '1', - namespace: undefined, - rel: 'primary', - type: 'alert', - type_id: 'test', - }, - ], }, - message: `rule execution start: "1"`, - rule: { - category: 'test', - id: '1', - license: 'basic', - ruleset: 'alerts', + task: { + schedule_delay: 0, + scheduled: '1970-01-01T00:00:00.000Z', }, - }); - expect(eventLogger.logEvent).toHaveBeenNthCalledWith(2, { - event: { - action: 'new-instance', - category: ['alerts'], - kind: 'alert', - duration: 0, - start: '1970-01-01T00:00:00.000Z', - }, - kibana: { - alert: { - rule: { - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - }, - }, - alerting: { - action_group_id: 'default', - action_subgroup: 'subDefault', - instance_id: '1', + saved_objects: [ + { + id: '1', + namespace: undefined, + rel: 'primary', + type: 'alert', + type_id: 'test', }, - saved_objects: [ - { - id: '1', - namespace: undefined, - rel: 'primary', - type: 'alert', - type_id: 'test', + ], + }, + message: `rule execution start: "1"`, + rule: { + category: 'test', + id: '1', + license: 'basic', + ruleset: 'alerts', + }, + }); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(2, { + event: { + action: 'new-instance', + category: ['alerts'], + kind: 'alert', + duration: 0, + start: '1970-01-01T00:00:00.000Z', + }, + kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, - ], - }, - message: "test:1: 'rule-name' created new alert: '1'", - rule: { - category: 'test', - id: '1', - license: 'basic', - name: 'rule-name', - namespace: undefined, - ruleset: 'alerts', + }, }, - }); - expect(eventLogger.logEvent).toHaveBeenNthCalledWith(3, { - event: { - action: 'active-instance', - category: ['alerts'], - duration: 0, - kind: 'alert', - start: '1970-01-01T00:00:00.000Z', + alerting: { + action_group_id: 'default', + action_subgroup: 'subDefault', + instance_id: '1', }, - kibana: { - alert: { - rule: { - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - }, + saved_objects: [ + { + id: '1', + namespace: undefined, + rel: 'primary', + type: 'alert', + type_id: 'test', }, - alerting: { - action_group_id: 'default', - action_subgroup: 'subDefault', - instance_id: '1', + ], + }, + message: "test:1: 'rule-name' created new alert: '1'", + rule: { + category: 'test', + id: '1', + license: 'basic', + name: 'rule-name', + namespace: undefined, + ruleset: 'alerts', + }, + }); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(3, { + event: { + action: 'active-instance', + category: ['alerts'], + duration: 0, + kind: 'alert', + start: '1970-01-01T00:00:00.000Z', + }, + kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + }, }, - saved_objects: [ - { id: '1', namespace: undefined, rel: 'primary', type: 'alert', type_id: 'test' }, - ], }, - message: - "test:1: 'rule-name' active alert: '1' in actionGroup(subgroup): 'default(subDefault)'", - rule: { - category: 'test', - id: '1', - license: 'basic', - name: 'rule-name', - namespace: undefined, - ruleset: 'alerts', - }, - }); - expect(eventLogger.logEvent).toHaveBeenNthCalledWith(4, { - event: { - action: 'execute-action', - category: ['alerts'], - kind: 'alert', + alerting: { + action_group_id: 'default', + action_subgroup: 'subDefault', + instance_id: '1', }, - kibana: { - alert: { - rule: { - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, + saved_objects: [ + { id: '1', namespace: undefined, rel: 'primary', type: 'alert', type_id: 'test' }, + ], + }, + message: + "test:1: 'rule-name' active alert: '1' in actionGroup(subgroup): 'default(subDefault)'", + rule: { + category: 'test', + id: '1', + license: 'basic', + name: 'rule-name', + namespace: undefined, + ruleset: 'alerts', + }, + }); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(4, { + event: { + action: 'execute-action', + category: ['alerts'], + kind: 'alert', + }, + kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, - alerting: { - instance_id: '1', - action_group_id: 'default', - action_subgroup: 'subDefault', - }, - saved_objects: [ - { - id: '1', - namespace: undefined, - rel: 'primary', - type: 'alert', - type_id: 'test', - }, - { - id: '1', - namespace: undefined, - type: 'action', - type_id: 'action', - }, - ], }, - message: - "alert: test:1: 'rule-name' instanceId: '1' scheduled actionGroup(subgroup): 'default(subDefault)' action: action:1", - rule: { - category: 'test', - id: '1', - license: 'basic', - name: 'rule-name', - namespace: undefined, - ruleset: 'alerts', + alerting: { + instance_id: '1', + action_group_id: 'default', + action_subgroup: 'subDefault', }, - }); - expect(eventLogger.logEvent).toHaveBeenNthCalledWith(5, { - event: { action: 'execute', category: ['alerts'], kind: 'alert', outcome: 'success' }, - kibana: { - alert: { - rule: { - execution: { - uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', - }, - }, - }, - alerting: { - status: 'active', + saved_objects: [ + { + id: '1', + namespace: undefined, + rel: 'primary', + type: 'alert', + type_id: 'test', }, - task: { - schedule_delay: 0, - scheduled: '1970-01-01T00:00:00.000Z', + { + id: '1', + namespace: undefined, + type: 'action', + type_id: 'action', }, - saved_objects: [ - { - id: '1', - namespace: undefined, - rel: 'primary', - type: 'alert', - type_id: 'test', + ], + }, + message: + "alert: test:1: 'rule-name' instanceId: '1' scheduled actionGroup(subgroup): 'default(subDefault)' action: action:1", + rule: { + category: 'test', + id: '1', + license: 'basic', + name: 'rule-name', + namespace: undefined, + ruleset: 'alerts', + }, + }); + expect(eventLogger.logEvent).toHaveBeenNthCalledWith(5, { + event: { action: 'execute', category: ['alerts'], kind: 'alert', outcome: 'success' }, + kibana: { + alert: { + rule: { + execution: { + uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + metrics: { + number_of_triggered_actions: 1, + }, }, - ], + }, }, - message: "rule executed: test:1: 'rule-name'", - rule: { - category: 'test', - id: '1', - license: 'basic', - name: 'rule-name', - ruleset: 'alerts', + task: { + schedule_delay: 0, + scheduled: '1970-01-01T00:00:00.000Z', }, - }); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - } + alerting: { + status: 'active', + }, + saved_objects: [ + { + id: '1', + namespace: undefined, + rel: 'primary', + type: 'alert', + type_id: 'test', + }, + ], + }, + message: "rule executed: test:1: 'rule-name'", + rule: { + category: 'test', + id: '1', + license: 'basic', + name: 'rule-name', + ruleset: 'alerts', + }, + }); + expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); + } ); test('actionsPlugin.execute is skipped if muteAll is true', async () => { @@ -744,7 +745,7 @@ describe('Task Runner', () => { ); expect(logger.debug).nthCalledWith( 4, - 'ruleExecutionStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}' + 'ruleExecutionStatus for test:1: {"numberOfTriggeredActions":0,"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}' ); const eventLogger = taskRunnerFactoryInitializerParams.eventLogger; @@ -878,6 +879,9 @@ describe('Task Runner', () => { rule: { execution: { uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', + metrics: { + number_of_triggered_actions: 0, + }, }, }, }, @@ -910,72 +914,68 @@ describe('Task Runner', () => { expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); }); - testAgainstEphemeralSupport( - 'skips firing actions for active alert if alert is muted', - ( - customTaskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType, - enqueueFunction: (options: ExecuteOptions) => Promise - ) => - async () => { - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( - true - ); - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( - true - ); - actionsClient.ephemeralEnqueuedExecution.mockResolvedValue(new Promise(() => {})); - ruleType.executor.mockImplementation( - async ({ - services: executorServices, - }: AlertExecutorOptions< - AlertTypeParams, - AlertTypeState, - AlertInstanceState, - AlertInstanceContext, - string - >) => { - executorServices.alertInstanceFactory('1').scheduleActions('default'); - executorServices.alertInstanceFactory('2').scheduleActions('default'); - } - ); - const taskRunner = new TaskRunner( - ruleType, - mockedTaskInstance, - customTaskRunnerFactoryInitializerParams - ); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, - mutedInstanceIds: ['2'], - }); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ - id: '1', - type: 'alert', - attributes: { - apiKey: Buffer.from('123:abc').toString('base64'), - enabled: true, - }, - references: [], - }); - await taskRunner.run(); - expect(enqueueFunction).toHaveBeenCalledTimes(1); - - const logger = customTaskRunnerFactoryInitializerParams.logger; - expect(logger.debug).toHaveBeenCalledTimes(5); - expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); - expect(logger.debug).nthCalledWith( - 2, - `rule test:1: 'rule-name' has 2 active alerts: [{\"instanceId\":\"1\",\"actionGroup\":\"default\"},{\"instanceId\":\"2\",\"actionGroup\":\"default\"}]` - ); - expect(logger.debug).nthCalledWith( - 3, - `skipping scheduling of actions for '2' in rule test:1: 'rule-name': rule is muted` - ); - expect(logger.debug).nthCalledWith( - 4, - 'ruleExecutionStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}' - ); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - } + test.each(ephemeralTestParams)( + 'skips firing actions for active alert if alert is muted %s', + async (nameExtension, customTaskRunnerFactoryInitializerParams, enqueueFunction) => { + ( + customTaskRunnerFactoryInitializerParams as TaskRunnerFactoryInitializerParamsType + ).actionsPlugin.isActionTypeEnabled.mockReturnValue(true); + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( + true + ); + actionsClient.ephemeralEnqueuedExecution.mockResolvedValue(mockRunNowResponse); + ruleType.executor.mockImplementation( + async ({ + services: executorServices, + }: AlertExecutorOptions< + AlertTypeParams, + AlertTypeState, + AlertInstanceState, + AlertInstanceContext, + string + >) => { + executorServices.alertInstanceFactory('1').scheduleActions('default'); + executorServices.alertInstanceFactory('2').scheduleActions('default'); + } + ); + const taskRunner = new TaskRunner( + ruleType, + mockedTaskInstance, + customTaskRunnerFactoryInitializerParams + ); + rulesClient.get.mockResolvedValue({ + ...mockedRuleTypeSavedObject, + mutedInstanceIds: ['2'], + }); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ + id: '1', + type: 'alert', + attributes: { + apiKey: Buffer.from('123:abc').toString('base64'), + enabled: true, + }, + references: [], + }); + await taskRunner.run(); + expect(enqueueFunction).toHaveBeenCalledTimes(1); + + const logger = customTaskRunnerFactoryInitializerParams.logger; + expect(logger.debug).toHaveBeenCalledTimes(5); + expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); + expect(logger.debug).nthCalledWith( + 2, + `rule test:1: 'rule-name' has 2 active alerts: [{\"instanceId\":\"1\",\"actionGroup\":\"default\"},{\"instanceId\":\"2\",\"actionGroup\":\"default\"}]` + ); + expect(logger.debug).nthCalledWith( + 3, + `skipping scheduling of actions for '2' in rule test:1: 'rule-name': rule is muted` + ); + expect(logger.debug).nthCalledWith( + 4, + 'ruleExecutionStatus for test:1: {"numberOfTriggeredActions":1,"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}' + ); + expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); + } ); test('actionsPlugin.execute is not called when notifyWhen=onActionGroupChange and alert alert state does not change', async () => { @@ -1134,6 +1134,9 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { + "metrics": Object { + "number_of_triggered_actions": 0, + }, "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, @@ -1170,204 +1173,224 @@ describe('Task Runner', () => { expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); }); - testAgainstEphemeralSupport( - 'actionsPlugin.execute is called when notifyWhen=onActionGroupChange and alert alert state has changed', - ( - customTaskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType, - enqueueFunction: (options: ExecuteOptions) => Promise - ) => - async () => { - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( - true - ); - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( - true - ); - ruleType.executor.mockImplementation( - async ({ - services: executorServices, - }: AlertExecutorOptions< - AlertTypeParams, - AlertTypeState, - AlertInstanceState, - AlertInstanceContext, - string - >) => { - executorServices.alertInstanceFactory('1').scheduleActions('default'); - } - ); - const taskRunner = new TaskRunner( - ruleType, - { - ...mockedTaskInstance, - state: { - ...mockedTaskInstance.state, - alertInstances: { - '1': { - meta: { - lastScheduledActions: { group: 'newGroup', date: new Date().toISOString() }, - }, - state: { bar: false }, + test.each(ephemeralTestParams)( + 'actionsPlugin.execute is called when notifyWhen=onActionGroupChange and alert alert state has changed %s', + async (nameExtension, customTaskRunnerFactoryInitializerParams, enqueueFunction) => { + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( + true + ); + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( + true + ); + ruleType.executor.mockImplementation( + async ({ + services: executorServices, + }: AlertExecutorOptions< + AlertTypeParams, + AlertTypeState, + AlertInstanceState, + AlertInstanceContext, + string + >) => { + executorServices.alertInstanceFactory('1').scheduleActions('default'); + } + ); + const taskRunner = new TaskRunner( + ruleType, + { + ...mockedTaskInstance, + state: { + ...mockedTaskInstance.state, + alertInstances: { + '1': { + meta: { + lastScheduledActions: { group: 'newGroup', date: new Date().toISOString() }, }, + state: { bar: false }, }, }, }, - customTaskRunnerFactoryInitializerParams - ); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, - notifyWhen: 'onActionGroupChange', - }); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ - id: '1', - type: 'alert', - attributes: { - apiKey: Buffer.from('123:abc').toString('base64'), - enabled: true, - }, - references: [], - }); - await taskRunner.run(); - expect(enqueueFunction).toHaveBeenCalledTimes(1); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - } + }, + customTaskRunnerFactoryInitializerParams + ); + rulesClient.get.mockResolvedValue({ + ...mockedRuleTypeSavedObject, + notifyWhen: 'onActionGroupChange', + }); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ + id: '1', + type: 'alert', + attributes: { + apiKey: Buffer.from('123:abc').toString('base64'), + enabled: true, + }, + references: [], + }); + const eventLogger = customTaskRunnerFactoryInitializerParams.eventLogger; + + await taskRunner.run(); + + expect(eventLogger.logEvent.mock.calls[3][0]).toEqual( + expect.objectContaining({ + kibana: expect.objectContaining({ + alert: expect.objectContaining({ + rule: expect.objectContaining({ + execution: expect.objectContaining({ + metrics: expect.objectContaining({ number_of_triggered_actions: 1 }), + }), + }), + }), + }), + }) + ); + expect(enqueueFunction).toHaveBeenCalledTimes(1); + expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); + } ); - testAgainstEphemeralSupport( - 'actionsPlugin.execute is called when notifyWhen=onActionGroupChange and alert state subgroup has changed', - ( - customTaskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType, - enqueueFunction: (options: ExecuteOptions) => Promise - ) => - async () => { - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( - true - ); - - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( - true - ); - ruleType.executor.mockImplementation( - async ({ - services: executorServices, - }: AlertExecutorOptions< - AlertTypeParams, - AlertTypeState, - AlertInstanceState, - AlertInstanceContext, - string - >) => { - executorServices - .alertInstanceFactory('1') - .scheduleActionsWithSubGroup('default', 'subgroup1'); - } - ); - const taskRunner = new TaskRunner( - ruleType, - { - ...mockedTaskInstance, - state: { - ...mockedTaskInstance.state, - alertInstances: { - '1': { - meta: { - lastScheduledActions: { - group: 'default', - subgroup: 'newSubgroup', - date: new Date().toISOString(), - }, + test.each(ephemeralTestParams)( + 'actionsPlugin.execute is called when notifyWhen=onActionGroupChange and alert state subgroup has changed %s', + async (nameExtension, customTaskRunnerFactoryInitializerParams, enqueueFunction) => { + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( + true + ); + + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( + true + ); + ruleType.executor.mockImplementation( + async ({ + services: executorServices, + }: AlertExecutorOptions< + AlertTypeParams, + AlertTypeState, + AlertInstanceState, + AlertInstanceContext, + string + >) => { + executorServices + .alertInstanceFactory('1') + .scheduleActionsWithSubGroup('default', 'subgroup1'); + } + ); + const taskRunner = new TaskRunner( + ruleType, + { + ...mockedTaskInstance, + state: { + ...mockedTaskInstance.state, + alertInstances: { + '1': { + meta: { + lastScheduledActions: { + group: 'default', + subgroup: 'newSubgroup', + date: new Date().toISOString(), }, - state: { bar: false }, }, + state: { bar: false }, }, }, }, - customTaskRunnerFactoryInitializerParams - ); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, - notifyWhen: 'onActionGroupChange', - }); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ - id: '1', - type: 'alert', - attributes: { - apiKey: Buffer.from('123:abc').toString('base64'), - enabled: true, - }, - references: [], - }); - await taskRunner.run(); - expect(enqueueFunction).toHaveBeenCalledTimes(1); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - } + }, + customTaskRunnerFactoryInitializerParams + ); + rulesClient.get.mockResolvedValue({ + ...mockedRuleTypeSavedObject, + notifyWhen: 'onActionGroupChange', + }); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ + id: '1', + type: 'alert', + attributes: { + apiKey: Buffer.from('123:abc').toString('base64'), + enabled: true, + }, + references: [], + }); + await taskRunner.run(); + + const eventLogger = customTaskRunnerFactoryInitializerParams.eventLogger; + + expect(eventLogger.logEvent.mock.calls[3][0]).toEqual( + expect.objectContaining({ + kibana: expect.objectContaining({ + alert: expect.objectContaining({ + rule: expect.objectContaining({ + execution: expect.objectContaining({ + metrics: expect.objectContaining({ number_of_triggered_actions: 1 }), + }), + }), + }), + }), + }) + ); + expect(enqueueFunction).toHaveBeenCalledTimes(1); + expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); + } ); - testAgainstEphemeralSupport( - 'includes the apiKey in the request used to initialize the actionsClient', - ( - customTaskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType, - enqueueFunction: (options: ExecuteOptions) => Promise - ) => - async () => { - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( - true - ); - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( - true - ); - actionsClient.ephemeralEnqueuedExecution.mockResolvedValue(new Promise(() => {})); - ruleType.executor.mockImplementation( - async ({ - services: executorServices, - }: AlertExecutorOptions< - AlertTypeParams, - AlertTypeState, - AlertInstanceState, - AlertInstanceContext, - string - >) => { - executorServices.alertInstanceFactory('1').scheduleActions('default'); - } - ); - const taskRunner = new TaskRunner( - ruleType, - mockedTaskInstance, - customTaskRunnerFactoryInitializerParams - ); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce({ - id: '1', - type: 'alert', - attributes: { - apiKey: Buffer.from('123:abc').toString('base64'), - enabled: true, + test.each(ephemeralTestParams)( + 'includes the apiKey in the request used to initialize the actionsClient %s', + async (nameExtension, customTaskRunnerFactoryInitializerParams, enqueueFunction) => { + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( + true + ); + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( + true + ); + actionsClient.ephemeralEnqueuedExecution.mockResolvedValue(mockRunNowResponse); + ruleType.executor.mockImplementation( + async ({ + services: executorServices, + }: AlertExecutorOptions< + AlertTypeParams, + AlertTypeState, + AlertInstanceState, + AlertInstanceContext, + string + >) => { + executorServices.alertInstanceFactory('1').scheduleActions('default'); + } + ); + const taskRunner = new TaskRunner( + ruleType, + mockedTaskInstance, + customTaskRunnerFactoryInitializerParams + ); + rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce({ + id: '1', + type: 'alert', + attributes: { + apiKey: Buffer.from('123:abc').toString('base64'), + enabled: true, + }, + references: [], + }); + await taskRunner.run(); + expect( + customTaskRunnerFactoryInitializerParams.actionsPlugin.getActionsClientWithRequest + ).toHaveBeenCalledWith( + expect.objectContaining({ + headers: { + // base64 encoded "123:abc" + authorization: 'ApiKey MTIzOmFiYw==', }, - references: [], - }); - await taskRunner.run(); - expect( - customTaskRunnerFactoryInitializerParams.actionsPlugin.getActionsClientWithRequest - ).toHaveBeenCalledWith( - expect.objectContaining({ - headers: { - // base64 encoded "123:abc" - authorization: 'ApiKey MTIzOmFiYw==', - }, - }) - ); - - const [request] = - customTaskRunnerFactoryInitializerParams.actionsPlugin.getActionsClientWithRequest.mock - .calls[0]; - - expect(customTaskRunnerFactoryInitializerParams.basePathService.set).toHaveBeenCalledWith( - request, - '/' - ); - - expect(enqueueFunction).toHaveBeenCalledTimes(1); - expect((enqueueFunction as jest.Mock).mock.calls[0]).toMatchInlineSnapshot(` + }) + ); + + const [request] = + customTaskRunnerFactoryInitializerParams.actionsPlugin.getActionsClientWithRequest.mock + .calls[0]; + + expect(customTaskRunnerFactoryInitializerParams.basePathService.set).toHaveBeenCalledWith( + request, + '/' + ); + + expect(enqueueFunction).toHaveBeenCalledTimes(1); + expect((enqueueFunction as jest.Mock).mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { "apiKey": "MTIzOmFiYw==", @@ -1396,10 +1419,10 @@ describe('Task Runner', () => { ] `); - const eventLogger = customTaskRunnerFactoryInitializerParams.eventLogger; - expect(eventLogger.logEvent).toHaveBeenCalledTimes(5); - expect(eventLogger.startTiming).toHaveBeenCalledTimes(1); - expect(eventLogger.logEvent.mock.calls).toMatchInlineSnapshot(` + const eventLogger = customTaskRunnerFactoryInitializerParams.eventLogger; + expect(eventLogger.logEvent).toHaveBeenCalledTimes(5); + expect(eventLogger.startTiming).toHaveBeenCalledTimes(1); + expect(eventLogger.logEvent.mock.calls).toMatchInlineSnapshot(` Array [ Array [ Object { @@ -1588,6 +1611,9 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { + "metrics": Object { + "number_of_triggered_actions": 1, + }, "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, @@ -1621,78 +1647,74 @@ describe('Task Runner', () => { ], ] `); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - } + expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); + } ); - testAgainstEphemeralSupport( - 'fire recovered actions for execution for the alertInstances which is in the recovered state', - ( - customTaskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType, - enqueueFunction: (options: ExecuteOptions) => Promise - ) => - async () => { - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( - true - ); - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( - true - ); - actionsClient.ephemeralEnqueuedExecution.mockResolvedValue(new Promise(() => {})); - - ruleType.executor.mockImplementation( - async ({ - services: executorServices, - }: AlertExecutorOptions< - AlertTypeParams, - AlertTypeState, - AlertInstanceState, - AlertInstanceContext, - string - >) => { - executorServices.alertInstanceFactory('1').scheduleActions('default'); - } - ); - const taskRunner = new TaskRunner( - ruleType, - { - ...mockedTaskInstance, - state: { - ...mockedTaskInstance.state, - alertInstances: { - '1': { - meta: {}, - state: { - bar: false, - start: '1969-12-31T00:00:00.000Z', - duration: 80000000000, - }, + test.each(ephemeralTestParams)( + 'fire recovered actions for execution for the alertInstances which is in the recovered state %s', + async (nameExtension, customTaskRunnerFactoryInitializerParams, enqueueFunction) => { + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( + true + ); + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( + true + ); + actionsClient.ephemeralEnqueuedExecution.mockResolvedValue(mockRunNowResponse); + + ruleType.executor.mockImplementation( + async ({ + services: executorServices, + }: AlertExecutorOptions< + AlertTypeParams, + AlertTypeState, + AlertInstanceState, + AlertInstanceContext, + string + >) => { + executorServices.alertInstanceFactory('1').scheduleActions('default'); + } + ); + const taskRunner = new TaskRunner( + ruleType, + { + ...mockedTaskInstance, + state: { + ...mockedTaskInstance.state, + alertInstances: { + '1': { + meta: {}, + state: { + bar: false, + start: '1969-12-31T00:00:00.000Z', + duration: 80000000000, }, - '2': { - meta: {}, - state: { - bar: false, - start: '1969-12-31T06:00:00.000Z', - duration: 70000000000, - }, + }, + '2': { + meta: {}, + state: { + bar: false, + start: '1969-12-31T06:00:00.000Z', + duration: 70000000000, }, }, }, }, - customTaskRunnerFactoryInitializerParams - ); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ - id: '1', - type: 'alert', - attributes: { - apiKey: Buffer.from('123:abc').toString('base64'), - enabled: true, - }, - references: [], - }); - const runnerResult = await taskRunner.run(); - expect(runnerResult.state.alertInstances).toMatchInlineSnapshot(` + }, + customTaskRunnerFactoryInitializerParams + ); + rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ + id: '1', + type: 'alert', + attributes: { + apiKey: Buffer.from('123:abc').toString('base64'), + enabled: true, + }, + references: [], + }); + const runnerResult = await taskRunner.run(); + expect(runnerResult.state.alertInstances).toMatchInlineSnapshot(` Object { "1": Object { "meta": Object { @@ -1711,26 +1733,26 @@ describe('Task Runner', () => { } `); - const logger = customTaskRunnerFactoryInitializerParams.logger; - expect(logger.debug).toHaveBeenCalledTimes(5); - expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); - expect(logger.debug).nthCalledWith( - 2, - `rule test:1: 'rule-name' has 1 active alerts: [{\"instanceId\":\"1\",\"actionGroup\":\"default\"}]` - ); - expect(logger.debug).nthCalledWith( - 3, - `rule test:1: 'rule-name' has 1 recovered alerts: [\"2\"]` - ); - expect(logger.debug).nthCalledWith( - 4, - 'ruleExecutionStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}' - ); - - const eventLogger = customTaskRunnerFactoryInitializerParams.eventLogger; - expect(eventLogger.logEvent).toHaveBeenCalledTimes(6); - expect(eventLogger.startTiming).toHaveBeenCalledTimes(1); - expect(eventLogger.logEvent.mock.calls).toMatchInlineSnapshot(` + const logger = customTaskRunnerFactoryInitializerParams.logger; + expect(logger.debug).toHaveBeenCalledTimes(5); + expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); + expect(logger.debug).nthCalledWith( + 2, + `rule test:1: 'rule-name' has 1 active alerts: [{\"instanceId\":\"1\",\"actionGroup\":\"default\"}]` + ); + expect(logger.debug).nthCalledWith( + 3, + `rule test:1: 'rule-name' has 1 recovered alerts: [\"2\"]` + ); + expect(logger.debug).nthCalledWith( + 4, + 'ruleExecutionStatus for test:1: {"numberOfTriggeredActions":2,"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}' + ); + + const eventLogger = customTaskRunnerFactoryInitializerParams.eventLogger; + expect(eventLogger.logEvent).toHaveBeenCalledTimes(6); + expect(eventLogger.startTiming).toHaveBeenCalledTimes(1); + expect(eventLogger.logEvent.mock.calls).toMatchInlineSnapshot(` Array [ Array [ Object { @@ -1966,6 +1988,9 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { + "metrics": Object { + "number_of_triggered_actions": 2, + }, "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, @@ -2000,8 +2025,8 @@ describe('Task Runner', () => { ] `); - expect(enqueueFunction).toHaveBeenCalledTimes(2); - expect((enqueueFunction as jest.Mock).mock.calls[0]).toMatchInlineSnapshot(` + expect(enqueueFunction).toHaveBeenCalledTimes(2); + expect((enqueueFunction as jest.Mock).mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { "apiKey": "MTIzOmFiYw==", @@ -2029,71 +2054,67 @@ describe('Task Runner', () => { }, ] `); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - } + expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); + } ); - testAgainstEphemeralSupport( - 'should skip alertInstances which werent active on the previous execution', - ( - customTaskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType, - enqueueFunction: (options: ExecuteOptions) => Promise - ) => - async () => { - const alertId = 'e558aaad-fd81-46d2-96fc-3bd8fc3dc03f'; - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( - true - ); - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( - true - ); - actionsClient.ephemeralEnqueuedExecution.mockResolvedValue(new Promise(() => {})); - - ruleType.executor.mockImplementation( - async ({ - services: executorServices, - }: AlertExecutorOptions< - AlertTypeParams, - AlertTypeState, - AlertInstanceState, - AlertInstanceContext, - string - >) => { - executorServices.alertInstanceFactory('1').scheduleActions('default'); - - // create an instance, but don't schedule any actions, so it doesn't go active - executorServices.alertInstanceFactory('3'); - } - ); - const taskRunner = new TaskRunner( - ruleType, - { - ...mockedTaskInstance, - state: { - ...mockedTaskInstance.state, - alertInstances: { - '1': { meta: {}, state: { bar: false } }, - '2': { meta: {}, state: { bar: false } }, - }, - }, - params: { - alertId, + test.each(ephemeralTestParams)( + "should skip alertInstances which weren't active on the previous execution %s", + async (nameExtension, customTaskRunnerFactoryInitializerParams, enqueueFunction) => { + const alertId = 'e558aaad-fd81-46d2-96fc-3bd8fc3dc03f'; + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( + true + ); + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( + true + ); + actionsClient.ephemeralEnqueuedExecution.mockResolvedValue(mockRunNowResponse); + + ruleType.executor.mockImplementation( + async ({ + services: executorServices, + }: AlertExecutorOptions< + AlertTypeParams, + AlertTypeState, + AlertInstanceState, + AlertInstanceContext, + string + >) => { + executorServices.alertInstanceFactory('1').scheduleActions('default'); + + // create an instance, but don't schedule any actions, so it doesn't go active + executorServices.alertInstanceFactory('3'); + } + ); + const taskRunner = new TaskRunner( + ruleType, + { + ...mockedTaskInstance, + state: { + ...mockedTaskInstance.state, + alertInstances: { + '1': { meta: {}, state: { bar: false } }, + '2': { meta: {}, state: { bar: false } }, }, }, - customTaskRunnerFactoryInitializerParams - ); - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ - id: alertId, - type: 'alert', - attributes: { - apiKey: Buffer.from('123:abc').toString('base64'), - enabled: true, + params: { + alertId, }, - references: [], - }); - const runnerResult = await taskRunner.run(); - expect(runnerResult.state.alertInstances).toMatchInlineSnapshot(` + }, + customTaskRunnerFactoryInitializerParams + ); + rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ + id: alertId, + type: 'alert', + attributes: { + apiKey: Buffer.from('123:abc').toString('base64'), + enabled: true, + }, + references: [], + }); + const runnerResult = await taskRunner.run(); + expect(runnerResult.state.alertInstances).toMatchInlineSnapshot(` Object { "1": Object { "meta": Object { @@ -2110,114 +2131,110 @@ describe('Task Runner', () => { } `); - const logger = customTaskRunnerFactoryInitializerParams.logger; - expect(logger.debug).toHaveBeenCalledWith( - `rule test:${alertId}: 'rule-name' has 1 active alerts: [{\"instanceId\":\"1\",\"actionGroup\":\"default\"}]` - ); - - expect(logger.debug).nthCalledWith( - 3, - `rule test:${alertId}: 'rule-name' has 1 recovered alerts: [\"2\"]` - ); - expect(logger.debug).nthCalledWith( - 4, - `ruleExecutionStatus for test:${alertId}: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}` - ); - - const eventLogger = customTaskRunnerFactoryInitializerParams.eventLogger; - expect(eventLogger.logEvent).toHaveBeenCalledTimes(6); - expect(enqueueFunction).toHaveBeenCalledTimes(2); - expect((enqueueFunction as jest.Mock).mock.calls[1][0].id).toEqual('1'); - expect((enqueueFunction as jest.Mock).mock.calls[0][0].id).toEqual('2'); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - } + const logger = customTaskRunnerFactoryInitializerParams.logger; + expect(logger.debug).toHaveBeenCalledWith( + `rule test:${alertId}: 'rule-name' has 1 active alerts: [{\"instanceId\":\"1\",\"actionGroup\":\"default\"}]` + ); + + expect(logger.debug).nthCalledWith( + 3, + `rule test:${alertId}: 'rule-name' has 1 recovered alerts: [\"2\"]` + ); + expect(logger.debug).nthCalledWith( + 4, + `ruleExecutionStatus for test:${alertId}: {"numberOfTriggeredActions":2,"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}` + ); + + const eventLogger = customTaskRunnerFactoryInitializerParams.eventLogger; + expect(eventLogger.logEvent).toHaveBeenCalledTimes(6); + expect(enqueueFunction).toHaveBeenCalledTimes(2); + expect((enqueueFunction as jest.Mock).mock.calls[1][0].id).toEqual('1'); + expect((enqueueFunction as jest.Mock).mock.calls[0][0].id).toEqual('2'); + expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); + } ); - testAgainstEphemeralSupport( - 'fire actions under a custom recovery group when specified on an alert type for alertInstances which are in the recovered state', - ( - customTaskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType, - enqueueFunction: (options: ExecuteOptions) => Promise - ) => - async () => { - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( - true - ); - customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( - true - ); - - actionsClient.ephemeralEnqueuedExecution.mockResolvedValue(new Promise(() => {})); - - const recoveryActionGroup = { - id: 'customRecovered', - name: 'Custom Recovered', - }; - const ruleTypeWithCustomRecovery = { - ...ruleType, - recoveryActionGroup, - actionGroups: [{ id: 'default', name: 'Default' }, recoveryActionGroup], - }; - - ruleTypeWithCustomRecovery.executor.mockImplementation( - async ({ - services: executorServices, - }: AlertExecutorOptions< - AlertTypeParams, - AlertTypeState, - AlertInstanceState, - AlertInstanceContext, - string - >) => { - executorServices.alertInstanceFactory('1').scheduleActions('default'); - } - ); - const taskRunner = new TaskRunner( - ruleTypeWithCustomRecovery, - { - ...mockedTaskInstance, - state: { - ...mockedTaskInstance.state, - alertInstances: { - '1': { meta: {}, state: { bar: false } }, - '2': { meta: {}, state: { bar: false } }, - }, + test.each(ephemeralTestParams)( + 'fire actions under a custom recovery group when specified on an alert type for alertInstances which are in the recovered state %s', + async (nameExtension, customTaskRunnerFactoryInitializerParams, enqueueFunction) => { + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionTypeEnabled.mockReturnValue( + true + ); + customTaskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue( + true + ); + + actionsClient.ephemeralEnqueuedExecution.mockResolvedValue(mockRunNowResponse); + + const recoveryActionGroup = { + id: 'customRecovered', + name: 'Custom Recovered', + }; + const ruleTypeWithCustomRecovery = { + ...ruleType, + recoveryActionGroup, + actionGroups: [{ id: 'default', name: 'Default' }, recoveryActionGroup], + }; + + ruleTypeWithCustomRecovery.executor.mockImplementation( + async ({ + services: executorServices, + }: AlertExecutorOptions< + AlertTypeParams, + AlertTypeState, + AlertInstanceState, + AlertInstanceContext, + string + >) => { + executorServices.alertInstanceFactory('1').scheduleActions('default'); + } + ); + const taskRunner = new TaskRunner( + ruleTypeWithCustomRecovery, + { + ...mockedTaskInstance, + state: { + ...mockedTaskInstance.state, + alertInstances: { + '1': { meta: {}, state: { bar: false } }, + '2': { meta: {}, state: { bar: false } }, }, }, - customTaskRunnerFactoryInitializerParams - ); - rulesClient.get.mockResolvedValue({ - ...mockedRuleTypeSavedObject, - actions: [ - { - group: 'default', - id: '1', - actionTypeId: 'action', - params: { - foo: true, - }, + }, + customTaskRunnerFactoryInitializerParams + ); + rulesClient.get.mockResolvedValue({ + ...mockedRuleTypeSavedObject, + actions: [ + { + group: 'default', + id: '1', + actionTypeId: 'action', + params: { + foo: true, }, - { - group: recoveryActionGroup.id, - id: '2', - actionTypeId: 'action', - params: { - isResolved: true, - }, + }, + { + group: recoveryActionGroup.id, + id: '2', + actionTypeId: 'action', + params: { + isResolved: true, }, - ], - }); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ - id: '1', - type: 'alert', - attributes: { - apiKey: Buffer.from('123:abc').toString('base64'), - enabled: true, }, - references: [], - }); - const runnerResult = await taskRunner.run(); - expect(runnerResult.state.alertInstances).toMatchInlineSnapshot(` + ], + }); + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ + id: '1', + type: 'alert', + attributes: { + apiKey: Buffer.from('123:abc').toString('base64'), + enabled: true, + }, + references: [], + }); + const runnerResult = await taskRunner.run(); + expect(runnerResult.state.alertInstances).toMatchInlineSnapshot(` Object { "1": Object { "meta": Object { @@ -2234,10 +2251,10 @@ describe('Task Runner', () => { } `); - const eventLogger = customTaskRunnerFactoryInitializerParams.eventLogger; - expect(eventLogger.logEvent).toHaveBeenCalledTimes(6); - expect(enqueueFunction).toHaveBeenCalledTimes(2); - expect((enqueueFunction as jest.Mock).mock.calls[0]).toMatchInlineSnapshot(` + const eventLogger = customTaskRunnerFactoryInitializerParams.eventLogger; + expect(eventLogger.logEvent).toHaveBeenCalledTimes(6); + expect(enqueueFunction).toHaveBeenCalledTimes(2); + expect((enqueueFunction as jest.Mock).mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { "apiKey": "MTIzOmFiYw==", @@ -2265,8 +2282,8 @@ describe('Task Runner', () => { }, ] `); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - } + expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); + } ); test('persists alertInstances passed in from state, only if they are scheduled for execution', async () => { @@ -2488,6 +2505,9 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { + "metrics": Object { + "number_of_triggered_actions": 0, + }, "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, @@ -3934,6 +3954,9 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { + "metrics": Object { + "number_of_triggered_actions": 0, + }, "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, @@ -4176,6 +4199,9 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { + "metrics": Object { + "number_of_triggered_actions": 0, + }, "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, @@ -4406,6 +4432,9 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { + "metrics": Object { + "number_of_triggered_actions": 0, + }, "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, @@ -4635,6 +4664,9 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { + "metrics": Object { + "number_of_triggered_actions": 0, + }, "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, @@ -4860,6 +4892,9 @@ describe('Task Runner', () => { "alert": Object { "rule": Object { "execution": Object { + "metrics": Object { + "number_of_triggered_actions": 0, + }, "uuid": "5f6aa57d-3e22-484e-bae8-cbed868f4d28", }, }, @@ -5009,7 +5044,7 @@ describe('Task Runner', () => { expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); expect(logger.debug).nthCalledWith( 2, - 'ruleExecutionStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"ok"}' + 'ruleExecutionStatus for test:1: {"numberOfTriggeredActions":0,"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"ok"}' ); const eventLogger = taskRunnerFactoryInitializerParams.eventLogger; 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 d8b4ea04a0184..785a68e1a24b9 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -6,7 +6,7 @@ */ import apm from 'elastic-apm-node'; import type { PublicMethodsOf } from '@kbn/utility-types'; -import { Dictionary, pickBy, mapValues, without, cloneDeep } from 'lodash'; +import { Dictionary, pickBy, mapValues, without, cloneDeep, concat, set, omit } from 'lodash'; import type { Request } from '@hapi/hapi'; import { UsageCounter } from 'src/plugins/usage_collection/server'; import uuid from 'uuid'; @@ -36,9 +36,13 @@ import { AlertExecutionStatusErrorReasons, RuleTypeRegistry, RuleMonitoring, + RuleMonitoringHistory, RawRuleExecutionStatus, + AlertAction, + RuleTaskStateWithActions, } from '../types'; import { promiseResult, map, Resultable, asOk, asErr, resolveErr } from '../lib/result_type'; +import { getExecutionSuccessRatio, getExecutionDurationPercentiles } from '../lib/monitoring'; import { taskInstanceToAlertTaskInstance } from './alert_task_instance'; import { EVENT_LOG_ACTIONS } from '../plugin'; import { IEvent, IEventLogger, SAVED_OBJECT_REL_PRIMARY } from '../../../event_log/server'; @@ -53,6 +57,7 @@ import { AlertInstanceContext, WithoutReservedActionGroups, parseDuration, + MONITORING_HISTORY_LIMIT, } from '../../common'; import { NormalizedRuleType, UntypedNormalizedRuleType } from '../rule_type_registry'; import { getEsErrorMessage } from '../lib/errors'; @@ -64,7 +69,6 @@ import { createAbortableEsClientFactory } from '../lib/create_abortable_es_clien const FALLBACK_RETRY_INTERVAL = '5m'; const CONNECTIVITY_RETRY_INTERVAL = '5m'; -const MONITORING_HISTORY_LIMIT = 200; // 1,000,000 nanoseconds in 1 millisecond const Millis2Nanos = 1000 * 1000; @@ -78,6 +82,12 @@ export const getDefaultRuleMonitoring = (): RuleMonitoring => ({ }, }); +interface RuleTaskRunResultWithActions { + state: RuleTaskStateWithActions; + monitoring: RuleMonitoring | undefined; + schedule: IntervalSchedule | undefined; +} + interface RuleTaskRunResult { state: RuleTaskState; monitoring: RuleMonitoring | undefined; @@ -296,7 +306,7 @@ export class TaskRunner< executionHandler: ExecutionHandler, spaceId: string, event: Event - ): Promise { + ): Promise { const { alertTypeId, consumer, @@ -446,10 +456,15 @@ export class TaskRunner< }); } + let triggeredActions: AlertAction[] = []; if (!muteAll && this.shouldLogAndScheduleActionsForAlerts()) { const mutedAlertIdsSet = new Set(mutedInstanceIds); - scheduleActionsForRecoveredAlerts({ + const scheduledActionsForRecoveredAlerts = await scheduleActionsForRecoveredAlerts< + InstanceState, + InstanceContext, + RecoveryActionGroupId + >({ recoveryActionGroup: this.ruleType.recoveryActionGroup, recoveredAlerts, executionHandler, @@ -458,6 +473,8 @@ export class TaskRunner< ruleLabel, }); + triggeredActions = concat(triggeredActions, scheduledActionsForRecoveredAlerts); + const alertsToExecute = notifyWhen === 'onActionGroupChange' ? Object.entries(alertsWithScheduledActions).filter( @@ -487,12 +504,14 @@ export class TaskRunner< } ); - await Promise.all( + const allTriggeredActions = await Promise.all( alertsToExecute.map( ([alertId, alert]: [string, AlertInstance]) => this.executeAlert(alertId, alert, executionHandler) ) ); + + triggeredActions = concat(triggeredActions, ...allTriggeredActions); } else { if (muteAll) { this.logger.debug(`no scheduling of actions for rule ${ruleLabel}: rule is muted.`); @@ -511,6 +530,7 @@ export class TaskRunner< } return { + triggeredActions, alertTypeState: updatedRuleTypeState || undefined, alertInstances: mapValues< Record>, @@ -544,7 +564,9 @@ export class TaskRunner< return this.executeAlerts(services, rule, validatedParams, executionHandler, spaceId, event); } - async loadRuleAttributesAndRun(event: Event): Promise> { + async loadRuleAttributesAndRun( + event: Event + ): Promise> { const { params: { alertId: ruleId, spaceId }, } = this.taskInstance; @@ -603,7 +625,7 @@ export class TaskRunner< } return { monitoring: asOk(rule.monitoring), - state: await promiseResult( + state: await promiseResult( this.validateAndExecuteRule(services, apiKey, rule, event) ), schedule: asOk( @@ -677,9 +699,10 @@ export class TaskRunner< resolveErr(monitoring, () => { return getDefaultRuleMonitoring(); }) ?? getDefaultRuleMonitoring(); - const executionStatus: AlertExecutionStatus = map( + + const executionStatus = map( state, - (ruleTaskState: RuleTaskState) => executionStatusFromState(ruleTaskState), + (ruleTaskState) => executionStatusFromState(ruleTaskState), (err: ElasticsearchError) => executionStatusFromError(err) ); @@ -701,37 +724,43 @@ export class TaskRunner< ); eventLogger.stopTiming(event); - event.kibana = event.kibana || {}; - event.kibana.alerting = event.kibana.alerting || {}; - event.kibana.alerting.status = executionStatus.status; + set(event, 'kibana.alerting.status', executionStatus.status); + + const monitoringHistory: RuleMonitoringHistory = { + success: true, + timestamp: +new Date(), + }; // Copy duration into execution status if available if (null != event.event?.duration) { executionStatus.lastDuration = Math.round(event.event?.duration / Millis2Nanos); + monitoringHistory.duration = executionStatus.lastDuration; } - const monitoringHistory = { - success: true, - timestamp: +new Date(), - }; // if executionStatus indicates an error, fill in fields in // event from it if (executionStatus.error) { - event.event = event.event || {}; - event.event.reason = executionStatus.error?.reason || 'unknown'; - event.event.outcome = 'failure'; - event.error = event.error || {}; - event.error.message = event.error.message || executionStatus.error.message; + set(event, 'event.reason', executionStatus.error?.reason || 'unknown'); + set(event, 'event.outcome', 'failure'); + set(event, 'error.message', event?.error?.message || executionStatus.error.message); if (!event.message) { event.message = `${this.ruleType.id}:${ruleId}: execution failed`; } monitoringHistory.success = false; + } else { + set( + event, + 'kibana.alert.rule.execution.metrics.number_of_triggered_actions', + executionStatus.numberOfTriggeredActions ?? 0 + ); } ruleMonitoring.execution.history.push(monitoringHistory); - ruleMonitoring.execution.calculated_metrics.success_ratio = - ruleMonitoring.execution.history.filter(({ success }) => success).length / - ruleMonitoring.execution.history.length; + ruleMonitoring.execution.calculated_metrics = { + success_ratio: getExecutionSuccessRatio(ruleMonitoring), + ...getExecutionDurationPercentiles(ruleMonitoring), + }; + eventLogger.logEvent(event); if (!this.cancelled) { @@ -746,15 +775,20 @@ export class TaskRunner< }); } + const transformStateForTaskState = ( + stateWithActions: RuleTaskStateWithActions + ): RuleTaskState => { + return { + ...omit(stateWithActions, 'triggeredActions'), + previousStartedAt: startedAt, + }; + }; + return { - state: map( + state: map( state, - (stateUpdates: RuleTaskState) => { - return { - ...stateUpdates, - previousStartedAt: startedAt, - }; - }, + (stateWithActions: RuleTaskStateWithActions) => + transformStateForTaskState(stateWithActions), (err: ElasticsearchError) => { const message = `Executing Rule ${spaceId}:${ this.ruleType.id @@ -1089,7 +1123,7 @@ interface ScheduleActionsForRecoveredAlertsParams< ruleLabel: string; } -function scheduleActionsForRecoveredAlerts< +async function scheduleActionsForRecoveredAlerts< InstanceState extends AlertInstanceState, InstanceContext extends AlertInstanceContext, RecoveryActionGroupId extends string @@ -1099,7 +1133,7 @@ function scheduleActionsForRecoveredAlerts< InstanceContext, RecoveryActionGroupId > -) { +): Promise { const { logger, recoveryActionGroup, @@ -1109,6 +1143,7 @@ function scheduleActionsForRecoveredAlerts< ruleLabel, } = params; const recoveredIds = Object.keys(recoveredAlerts); + let triggeredActions: AlertAction[] = []; for (const id of recoveredIds) { if (mutedAlertIdsSet.has(id)) { logger.debug( @@ -1118,15 +1153,17 @@ function scheduleActionsForRecoveredAlerts< const alert = recoveredAlerts[id]; alert.updateLastScheduledActions(recoveryActionGroup.id); alert.unscheduleActions(); - executionHandler({ + const triggeredActionsForRecoveredAlert = await executionHandler({ actionGroup: recoveryActionGroup.id, context: {}, state: {}, alertId: id, }); alert.scheduleActions(recoveryActionGroup.id); + triggeredActions = concat(triggeredActions, triggeredActionsForRecoveredAlert); } } + return triggeredActions; } interface LogActiveAndRecoveredAlertsParams< @@ -1189,8 +1226,8 @@ function logActiveAndRecoveredAlerts< * so that we can treat each field independantly */ async function errorAsRuleTaskRunResult( - future: Promise> -): Promise> { + future: Promise> +): Promise> { try { return await future; } catch (e) { 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 f071af53bc10e..47f888fc71136 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 @@ -287,6 +287,9 @@ describe('Task Runner Cancel', () => { alert: { rule: { execution: { + metrics: { + number_of_triggered_actions: 0, + }, uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, @@ -463,7 +466,7 @@ describe('Task Runner Cancel', () => { ); expect(logger.debug).nthCalledWith( 7, - 'ruleExecutionStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}' + 'ruleExecutionStatus for test:1: {"numberOfTriggeredActions":0,"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}' ); const eventLogger = taskRunnerFactoryInitializerParams.eventLogger; @@ -547,6 +550,9 @@ describe('Task Runner Cancel', () => { alert: { rule: { execution: { + metrics: { + number_of_triggered_actions: 0, + }, uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, @@ -607,7 +613,7 @@ describe('Task Runner Cancel', () => { ); expect(logger.debug).nthCalledWith( 6, - 'ruleExecutionStatus for test:1: {"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}' + 'ruleExecutionStatus for test:1: {"numberOfTriggeredActions":1,"lastExecutionDate":"1970-01-01T00:00:00.000Z","status":"active"}' ); const eventLogger = taskRunnerFactoryInitializerParams.eventLogger; @@ -801,6 +807,9 @@ describe('Task Runner Cancel', () => { alert: { rule: { execution: { + metrics: { + number_of_triggered_actions: 1, + }, uuid: '5f6aa57d-3e22-484e-bae8-cbed868f4d28', }, }, diff --git a/x-pack/plugins/alerting/server/types.ts b/x-pack/plugins/alerting/server/types.ts index 93ee520c7126a..de6649bb44891 100644 --- a/x-pack/plugins/alerting/server/types.ts +++ b/x-pack/plugins/alerting/server/types.ts @@ -191,6 +191,7 @@ export interface AlertMeta extends SavedObjectAttributes { // delete any previous error if the current status has no error export interface RawRuleExecutionStatus extends SavedObjectAttributes { status: AlertExecutionStatuses; + numberOfTriggeredActions?: number; lastExecutionDate: string; lastDuration?: number; error: null | { 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 2ed7ca2d02c5d..d679c140733c2 100644 --- a/x-pack/plugins/alerting/server/usage/alerting_telemetry.test.ts +++ b/x-pack/plugins/alerting/server/usage/alerting_telemetry.test.ts @@ -14,6 +14,7 @@ import { getTotalCountInUse, getExecutionsPerDayCount, getExecutionTimeoutsPerDayCount, + getFailedAndUnrecognizedTasksPerDay, } from './alerting_telemetry'; describe('alerting telemetry', () => { @@ -237,4 +238,54 @@ Object { }, }); }); + + test('getFailedAndUnrecognizedTasksPerDay should aggregations for total count, count by status and count by status and rule type for failed and unrecognized tasks', async () => { + const mockEsClient = elasticsearchClientMock.createClusterClient().asScoped().asInternalUser; + mockEsClient.search.mockReturnValue( + // @ts-expect-error @elastic/elasticsearch Aggregate only allows unknown values + elasticsearchClientMock.createSuccessTransportRequestPromise({ + aggregations: { + byTaskTypeId: { + value: { + statuses: { + failed: { + '.index-threshold': 2, + 'logs.alert.document.count': 1, + 'document.test.': 1, + }, + unrecognized: { + 'o.l.d.task-type': 1, + }, + }, + }, + }, + }, + hits: { + hits: [], + }, + }) + ); + + const telemetry = await getFailedAndUnrecognizedTasksPerDay(mockEsClient, 'test'); + + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + + expect(telemetry).toStrictEqual({ + countByStatus: { + failed: 4, + unrecognized: 1, + }, + countByStatusByRuleType: { + failed: { + '__index-threshold': 2, + document__test__: 1, + logs__alert__document__count: 1, + }, + unrecognized: { + 'o__l__d__task-type': 1, + }, + }, + countTotal: 5, + }); + }); }); diff --git a/x-pack/plugins/alerting/server/usage/alerting_telemetry.ts b/x-pack/plugins/alerting/server/usage/alerting_telemetry.ts index b21e1d4b00ef1..15d6650b2cb4b 100644 --- a/x-pack/plugins/alerting/server/usage/alerting_telemetry.ts +++ b/x-pack/plugins/alerting/server/usage/alerting_telemetry.ts @@ -92,6 +92,35 @@ const ruleTypeExecutionsMetric = { }, }; +const taskTypeExecutionsMetric = { + scripted_metric: { + init_script: 'state.statuses = [:]', + map_script: ` + String status = doc['task.status'].value; + String taskType = doc['task.taskType'].value.replace('alerting:', ''); + Map taskTypes = state.statuses.containsKey(status) ? state.statuses.get(status) : [:]; + taskTypes.put(taskType, taskTypes.containsKey(taskType) ? taskTypes.get(taskType) + 1 : 1); + state.statuses.put(status, taskTypes); + `, + // Combine script is executed per cluster, but we already have a key-value pair per cluster. + // Despite docs that say this is optional, this script can't be blank. + combine_script: 'return state', + // Reduce script is executed across all clusters, so we need to add up all the total from each cluster + // This also needs to account for having no data + reduce_script: ` + Map result = [:]; + for (Map m : states.toArray()) { + if (m !== null) { + for (String k : m.keySet()) { + result.put(k, result.containsKey(k) ? result.get(k) + m.get(k) : m.get(k)); + } + } + } + return result; + `, + }, +}; + const ruleTypeFailureExecutionsMetric = { scripted_metric: { init_script: 'state.reasons = [:]', @@ -511,6 +540,102 @@ export async function getExecutionTimeoutsPerDayCount( }; } +export async function getFailedAndUnrecognizedTasksPerDay( + esClient: ElasticsearchClient, + taskManagerIndex: string +) { + const { body: searchResult } = await esClient.search({ + index: taskManagerIndex, + size: 0, + body: { + query: { + bool: { + must: [ + { + bool: { + should: [ + { + term: { + 'task.status': 'unrecognized', + }, + }, + { + term: { + 'task.status': 'failed', + }, + }, + ], + }, + }, + { + wildcard: { + 'task.taskType': { + value: 'alerting:*', + }, + }, + }, + { + range: { + 'task.runAt': { + gte: 'now-1d', + }, + }, + }, + ], + }, + }, + aggs: { + byTaskTypeId: taskTypeExecutionsMetric, + }, + }, + }); + + const executionsAggregations = searchResult.aggregations as { + byTaskTypeId: { value: { statuses: Record> } }; + }; + + return { + countTotal: Object.keys(executionsAggregations.byTaskTypeId.value.statuses).reduce( + (total: number, status: string) => { + const byRuleTypesRefs = executionsAggregations.byTaskTypeId.value.statuses[status]; + const countByRuleTypes = Object.keys(byRuleTypesRefs).reduce( + (totalByType, ruleType) => parseInt(byRuleTypesRefs[ruleType] + totalByType, 10), + 0 + ); + return countByRuleTypes + total; + }, + 0 + ), + countByStatus: Object.keys(executionsAggregations.byTaskTypeId.value.statuses).reduce( + // ES DSL aggregations are returned as `any` by esClient.search + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (obj: any, status: string) => { + const byRuleTypesRefs = executionsAggregations.byTaskTypeId.value.statuses[status]; + const countByRuleTypes = Object.keys(byRuleTypesRefs).reduce( + (totalByType, ruleType) => parseInt(byRuleTypesRefs[ruleType] + totalByType, 10), + 0 + ); + return { + ...obj, + [status]: countByRuleTypes, + }; + }, + {} + ), + countByStatusByRuleType: Object.keys(executionsAggregations.byTaskTypeId.value.statuses).reduce( + // ES DSL aggregations are returned as `any` by esClient.search + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (obj: any, key: string) => ({ + ...obj, + [key]: replaceDotSymbolsInRuleTypeIds( + executionsAggregations.byTaskTypeId.value.statuses[key] + ), + }), + {} + ), + }; +} + function replaceDotSymbols(strToReplace: string) { return strToReplace.replaceAll('.', '__'); } 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 2e5b012cf3b47..54e4549786381 100644 --- a/x-pack/plugins/alerting/server/usage/alerting_usage_collector.ts +++ b/x-pack/plugins/alerting/server/usage/alerting_usage_collector.ts @@ -76,6 +76,22 @@ const byReasonSchemaByType: MakeSchemaFrom['count_rules_execution unknown: byTypeSchema, }; +const byTaskStatusSchema: MakeSchemaFrom['count_failed_and_unrecognized_rule_tasks_by_status_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) + DYNAMIC_KEY: { type: 'long' }, + failed: { type: 'long' }, + unrecognized: { type: 'long' }, + }; + +const byTaskStatusSchemaByType: MakeSchemaFrom['count_failed_and_unrecognized_rule_tasks_by_status_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) + DYNAMIC_KEY: byTypeSchema, + failed: byTypeSchema, + unrecognized: byTypeSchema, + }; + export function createAlertingUsageCollector( usageCollection: UsageCollectionSetup, taskManager: Promise @@ -135,6 +151,9 @@ export function createAlertingUsageCollector( count_rules_executions_failured_by_reason_by_type_per_day: {}, count_rules_executions_timeouts_per_day: 0, count_rules_executions_timeouts_by_type_per_day: {}, + count_failed_and_unrecognized_rule_tasks_per_day: 0, + count_failed_and_unrecognized_rule_tasks_by_status_per_day: {}, + count_failed_and_unrecognized_rule_tasks_by_status_by_type_per_day: {}, avg_execution_time_per_day: 0, avg_execution_time_by_type_per_day: {}, }; @@ -179,6 +198,9 @@ export function createAlertingUsageCollector( count_rules_executions_failured_by_reason_by_type_per_day: byReasonSchemaByType, count_rules_executions_timeouts_per_day: { type: 'long' }, count_rules_executions_timeouts_by_type_per_day: byTypeSchema, + count_failed_and_unrecognized_rule_tasks_per_day: { type: 'long' }, + count_failed_and_unrecognized_rule_tasks_by_status_per_day: byTaskStatusSchema, + count_failed_and_unrecognized_rule_tasks_by_status_by_type_per_day: byTaskStatusSchemaByType, avg_execution_time_per_day: { type: 'long' }, avg_execution_time_by_type_per_day: byTypeSchema, }, diff --git a/x-pack/plugins/alerting/server/usage/task.ts b/x-pack/plugins/alerting/server/usage/task.ts index 04ed88edfc722..15978e9967ad2 100644 --- a/x-pack/plugins/alerting/server/usage/task.ts +++ b/x-pack/plugins/alerting/server/usage/task.ts @@ -18,6 +18,7 @@ import { getTotalCountInUse, getExecutionsPerDayCount, getExecutionTimeoutsPerDayCount, + getFailedAndUnrecognizedTasksPerDay, } from './alerting_telemetry'; export const TELEMETRY_TASK_TYPE = 'alerting_telemetry'; @@ -51,7 +52,13 @@ function registerAlertingTelemetryTask( [TELEMETRY_TASK_TYPE]: { title: 'Alerting usage fetch task', timeout: '5m', - createTaskRunner: telemetryTaskRunner(logger, core, kibanaIndex, eventLogIndex), + createTaskRunner: telemetryTaskRunner( + logger, + core, + kibanaIndex, + eventLogIndex, + taskManager.index + ), }, }); } @@ -73,7 +80,8 @@ export function telemetryTaskRunner( logger: Logger, core: CoreSetup, kibanaIndex: string, - eventLogIndex: string + eventLogIndex: string, + taskManagerIndex: string ) { return ({ taskInstance }: RunContext) => { const { state } = taskInstance; @@ -94,6 +102,7 @@ export function telemetryTaskRunner( getTotalCountInUse(esClient, kibanaIndex), getExecutionsPerDayCount(esClient, eventLogIndex), getExecutionTimeoutsPerDayCount(esClient, eventLogIndex), + getFailedAndUnrecognizedTasksPerDay(esClient, taskManagerIndex), ]) .then( ([ @@ -101,6 +110,7 @@ export function telemetryTaskRunner( totalInUse, dailyExecutionCounts, dailyExecutionTimeoutCounts, + dailyFailedAndUnrecognizedTasks, ]) => { return { state: { @@ -120,6 +130,12 @@ export function telemetryTaskRunner( count_rules_executions_timeouts_per_day: dailyExecutionTimeoutCounts.countTotal, count_rules_executions_timeouts_by_type_per_day: dailyExecutionTimeoutCounts.countByType, + count_failed_and_unrecognized_rule_tasks_per_day: + dailyFailedAndUnrecognizedTasks.countTotal, + count_failed_and_unrecognized_rule_tasks_by_status_per_day: + dailyFailedAndUnrecognizedTasks.countByStatus, + count_failed_and_unrecognized_rule_tasks_by_status_by_type_per_day: + dailyFailedAndUnrecognizedTasks.countByStatusByRuleType, avg_execution_time_per_day: dailyExecutionCounts.avgExecutionTime, avg_execution_time_by_type_per_day: dailyExecutionCounts.avgExecutionTimeByType, }, diff --git a/x-pack/plugins/alerting/server/usage/types.ts b/x-pack/plugins/alerting/server/usage/types.ts index b86176e23548e..ae951f5d65942 100644 --- a/x-pack/plugins/alerting/server/usage/types.ts +++ b/x-pack/plugins/alerting/server/usage/types.ts @@ -19,6 +19,12 @@ export interface AlertingUsage { count_rules_executions_failured_by_reason_by_type_per_day: Record>; count_rules_executions_timeouts_per_day: number; count_rules_executions_timeouts_by_type_per_day: Record; + count_failed_and_unrecognized_rule_tasks_per_day: number; + count_failed_and_unrecognized_rule_tasks_by_status_per_day: Record; + count_failed_and_unrecognized_rule_tasks_by_status_by_type_per_day: Record< + string, + Record + >; avg_execution_time_per_day: number; avg_execution_time_by_type_per_day: Record; throttle_time: { diff --git a/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap b/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap index 5dd3588674179..9b255a87df39e 100644 --- a/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap +++ b/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap @@ -37,6 +37,8 @@ exports[`Error CLOUD_PROVIDER 1`] = `"gcp"`; exports[`Error CLOUD_REGION 1`] = `"europe-west1"`; +exports[`Error CLOUD_SERVICE_NAME 1`] = `undefined`; + exports[`Error CLS_FIELD 1`] = `undefined`; exports[`Error CONTAINER_ID 1`] = `undefined`; @@ -63,6 +65,12 @@ exports[`Error ERROR_PAGE_URL 1`] = `undefined`; exports[`Error EVENT_OUTCOME 1`] = `undefined`; +exports[`Error FAAS_COLDSTART 1`] = `undefined`; + +exports[`Error FAAS_ID 1`] = `undefined`; + +exports[`Error FAAS_TRIGGER_TYPE 1`] = `undefined`; + exports[`Error FCP_FIELD 1`] = `undefined`; exports[`Error FID_FIELD 1`] = `undefined`; @@ -282,6 +290,8 @@ exports[`Span CLOUD_PROVIDER 1`] = `"gcp"`; exports[`Span CLOUD_REGION 1`] = `"europe-west1"`; +exports[`Span CLOUD_SERVICE_NAME 1`] = `undefined`; + exports[`Span CLS_FIELD 1`] = `undefined`; exports[`Span CONTAINER_ID 1`] = `undefined`; @@ -308,6 +318,12 @@ exports[`Span ERROR_PAGE_URL 1`] = `undefined`; exports[`Span EVENT_OUTCOME 1`] = `"unknown"`; +exports[`Span FAAS_COLDSTART 1`] = `undefined`; + +exports[`Span FAAS_ID 1`] = `undefined`; + +exports[`Span FAAS_TRIGGER_TYPE 1`] = `undefined`; + exports[`Span FCP_FIELD 1`] = `undefined`; exports[`Span FID_FIELD 1`] = `undefined`; @@ -519,6 +535,8 @@ exports[`Transaction CLOUD_PROVIDER 1`] = `"gcp"`; exports[`Transaction CLOUD_REGION 1`] = `"europe-west1"`; +exports[`Transaction CLOUD_SERVICE_NAME 1`] = `undefined`; + exports[`Transaction CLS_FIELD 1`] = `undefined`; exports[`Transaction CONTAINER_ID 1`] = `"container1234567890abcdef"`; @@ -545,6 +563,12 @@ exports[`Transaction ERROR_PAGE_URL 1`] = `undefined`; exports[`Transaction EVENT_OUTCOME 1`] = `"unknown"`; +exports[`Transaction FAAS_COLDSTART 1`] = `undefined`; + +exports[`Transaction FAAS_ID 1`] = `undefined`; + +exports[`Transaction FAAS_TRIGGER_TYPE 1`] = `undefined`; + exports[`Transaction FCP_FIELD 1`] = `undefined`; exports[`Transaction FID_FIELD 1`] = `undefined`; diff --git a/x-pack/plugins/apm/common/agent_name.test.ts b/x-pack/plugins/apm/common/agent_name.test.ts index 162a5716d6c7b..e48fa502d33d1 100644 --- a/x-pack/plugins/apm/common/agent_name.test.ts +++ b/x-pack/plugins/apm/common/agent_name.test.ts @@ -5,7 +5,12 @@ * 2.0. */ -import { isJavaAgentName, isRumAgentName, isIosAgentName } from './agent_name'; +import { + isJavaAgentName, + isRumAgentName, + isIosAgentName, + isServerlessAgent, +} from './agent_name'; describe('agent name helpers', () => { describe('isJavaAgentName', () => { @@ -79,4 +84,30 @@ describe('agent name helpers', () => { }); }); }); + + describe('isServerlessAgent', () => { + describe('when the runtime name is AWS_LAMBDA', () => { + it('returns true', () => { + expect(isServerlessAgent('AWS_LAMBDA')).toEqual(true); + }); + }); + + describe('when the runtime name is aws_lambda', () => { + it('returns true', () => { + expect(isServerlessAgent('aws_lambda')).toEqual(true); + }); + }); + + describe('when the runtime name is aws_lambda_test', () => { + it('returns true', () => { + expect(isServerlessAgent('aws_lambda_test')).toEqual(true); + }); + }); + + describe('when the runtime name is something else', () => { + it('returns false', () => { + expect(isServerlessAgent('not_aws_lambda')).toEqual(false); + }); + }); + }); }); diff --git a/x-pack/plugins/apm/common/agent_name.ts b/x-pack/plugins/apm/common/agent_name.ts index b41ae949d5867..e8947d550a8fc 100644 --- a/x-pack/plugins/apm/common/agent_name.ts +++ b/x-pack/plugins/apm/common/agent_name.ts @@ -90,3 +90,7 @@ export function isIosAgentName(agentName?: string) { export function isJRubyAgent(agentName?: string, runtimeName?: string) { return agentName === 'ruby' && runtimeName?.toLowerCase() === 'jruby'; } + +export function isServerlessAgent(runtimeName?: string) { + return runtimeName?.toLowerCase().startsWith('aws_lambda'); +} diff --git a/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts b/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts index 5c7c953d8d900..f0ea5b6cb116e 100644 --- a/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts +++ b/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts @@ -13,6 +13,7 @@ export const CLOUD_MACHINE_TYPE = 'cloud.machine.type'; export const CLOUD_ACCOUNT_ID = 'cloud.account.id'; export const CLOUD_INSTANCE_ID = 'cloud.instance.id'; export const CLOUD_INSTANCE_NAME = 'cloud.instance.name'; +export const CLOUD_SERVICE_NAME = 'cloud.service.name'; export const SERVICE = 'service'; export const SERVICE_NAME = 'service.name'; @@ -152,3 +153,7 @@ export const PROFILE_ALLOC_OBJECTS = 'profile.alloc_objects.count'; export const PROFILE_ALLOC_SPACE = 'profile.alloc_space.bytes'; export const PROFILE_INUSE_OBJECTS = 'profile.inuse_objects.count'; export const PROFILE_INUSE_SPACE = 'profile.inuse_space.bytes'; + +export const FAAS_ID = 'faas.id'; +export const FAAS_COLDSTART = 'faas.coldstart'; +export const FAAS_TRIGGER_TYPE = 'faas.trigger.type'; diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/aws_lambda/aws_lamba.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/aws_lambda/aws_lamba.spec.ts new file mode 100644 index 0000000000000..518cfefde2fb1 --- /dev/null +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/aws_lambda/aws_lamba.spec.ts @@ -0,0 +1,53 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import url from 'url'; +import { synthtrace } from '../../../../../synthtrace'; +import { generateData } from './generate_data'; + +const start = '2021-10-10T00:00:00.000Z'; +const end = '2021-10-10T00:15:00.000Z'; + +const serviceOverviewHref = url.format({ + pathname: '/app/apm/services/synth-python/overview', + query: { rangeFrom: start, rangeTo: end }, +}); + +const apiToIntercept = { + endpoint: + '/internal/apm/services/synth-python/transactions/charts/coldstart_rate?*', + name: 'coldStartRequest', +}; + +describe('Service overview - aws lambda', () => { + before(async () => { + await synthtrace.index( + generateData({ + start: new Date(start).getTime(), + end: new Date(end).getTime(), + }) + ); + }); + + after(async () => { + await synthtrace.clean(); + }); + + beforeEach(() => { + cy.loginAsReadOnlyUser(); + }); + + it('displays a cold start rate chart and not a transaction breakdown chart', () => { + const { endpoint, name } = apiToIntercept; + + cy.intercept('GET', endpoint).as(name); + cy.visit(serviceOverviewHref); + cy.wait(`@${name}`); + + cy.contains('Cold start rate'); + cy.contains('Time spent by span type').should('not.exist'); + }); +}); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/aws_lambda/generate_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/aws_lambda/generate_data.ts new file mode 100644 index 0000000000000..2dba10e8e517e --- /dev/null +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/aws_lambda/generate_data.ts @@ -0,0 +1,41 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { apm, timerange } from '@elastic/apm-synthtrace'; + +const dataConfig = { + serviceName: 'synth-python', + rate: 10, + transaction: { + name: 'GET /apple 🍎', + duration: 1000, + }, +}; + +export function generateData({ start, end }: { start: number; end: number }) { + const { rate, transaction, serviceName } = dataConfig; + const instance = apm + .service(serviceName, 'production', 'python') + .instance('instance-a'); + + const traceEvents = timerange(start, end) + .interval('1m') + .rate(rate) + .flatMap((timestamp) => [ + ...instance + .transaction(transaction.name) + .defaults({ + 'service.runtime.name': 'AWS_Lambda_python3.8', + 'faas.coldstart': true, + }) + .timestamp(timestamp) + .duration(transaction.duration) + .success() + .serialize(), + ]); + + return traceEvents; +} diff --git a/x-pack/plugins/apm/public/components/app/service_overview/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/index.tsx index 2c30027770f43..3c2db54088770 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/index.tsx @@ -9,13 +9,18 @@ import { EuiFlexGroup, EuiFlexItem, EuiLink, EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { useHistory } from 'react-router-dom'; -import { isRumAgentName, isIosAgentName } from '../../../../common/agent_name'; +import { + isRumAgentName, + isIosAgentName, + isServerlessAgent, +} from '../../../../common/agent_name'; import { AnnotationsContextProvider } from '../../../context/annotations/annotations_context'; import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; import { ChartPointerEventContextProvider } from '../../../context/chart_pointer_event/chart_pointer_event_context'; import { useBreakpoints } from '../../../hooks/use_breakpoints'; import { LatencyChart } from '../../shared/charts/latency_chart'; import { TransactionBreakdownChart } from '../../shared/charts/transaction_breakdown_chart'; +import { TransactionColdstartRateChart } from '../../shared/charts/transaction_coldstart_rate_chart'; import { FailedTransactionRateChart } from '../../shared/charts/failed_transaction_rate_chart'; import { ServiceOverviewDependenciesTable } from './service_overview_dependencies_table'; import { ServiceOverviewErrorsTable } from './service_overview_errors_table'; @@ -35,8 +40,13 @@ import { replace } from '../../shared/links/url_helpers'; export const chartHeight = 288; export function ServiceOverview() { - const { agentName, serviceName, transactionType, fallbackToTransactions } = - useApmServiceContext(); + const { + agentName, + serviceName, + transactionType, + fallbackToTransactions, + runtimeName, + } = useApmServiceContext(); const { query, query: { @@ -69,7 +79,7 @@ export function ServiceOverview() { const rowDirection = isSingleColumn ? 'column' : 'row'; const isRumAgent = isRumAgentName(agentName); const isIosAgent = isIosAgentName(agentName); - + const isServerless = isServerlessAgent(runtimeName); const router = useApmRouter(); const dependenciesLink = router.link('/services/{serviceName}/dependencies', { path: { @@ -152,13 +162,23 @@ export function ServiceOverview() { gutterSize="s" responsive={false} > - - - + {isServerless ? ( + + + + ) : ( + + + + )} {!isRumAgent && ( @@ -180,7 +200,7 @@ export function ServiceOverview() { )} - {!isRumAgent && !isIosAgent && ( + {!isRumAgent && !isIosAgent && !isServerless && ( {fallbackToTransactions && } @@ -66,6 +72,9 @@ export function TransactionDetails() { start={start} end={end} transactionName={transactionName} + isServerlessContext={isServerless} + comparisonEnabled={comparisonEnabled} + comparisonType={comparisonType} /> diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/cold_start_badge.stories.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/cold_start_badge.stories.tsx new file mode 100644 index 0000000000000..50af7cc42435b --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/cold_start_badge.stories.tsx @@ -0,0 +1,18 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { ColdStartBadge } from './cold_start_badge'; + +export default { + title: 'app/TransactionDetails/Waterfall/Badge/ColdStartBadge', + component: ColdStartBadge, +}; + +export function Example() { + return ; +} diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/cold_start_badge.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/cold_start_badge.tsx new file mode 100644 index 0000000000000..dfe38aab5021d --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/cold_start_badge.tsx @@ -0,0 +1,20 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiBadge } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; + +export function ColdStartBadge() { + return ( + + {i18n.translate('xpack.apm.transactionDetails.coldstartBadge', { + defaultMessage: 'cold start', + })} + + ); +} diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/sync_badge.stories.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/sync_badge.stories.tsx similarity index 94% rename from x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/sync_badge.stories.tsx rename to x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/sync_badge.stories.tsx index dea05961c4cef..7209203b54cc0 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/sync_badge.stories.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/sync_badge.stories.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { SyncBadge, SyncBadgeProps } from './sync_badge'; export default { - title: 'app/TransactionDetails/SyncBadge', + title: 'app/TransactionDetails/Waterfall/Badge/SyncBadge', component: SyncBadge, argTypes: { sync: { diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/sync_badge.test.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/sync_badge.test.tsx similarity index 100% rename from x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/sync_badge.test.tsx rename to x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/sync_badge.test.tsx diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/sync_badge.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/sync_badge.tsx similarity index 94% rename from x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/sync_badge.tsx rename to x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/sync_badge.tsx index a51d710bf3961..85571b9065c4d 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/sync_badge.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/sync_badge.tsx @@ -8,7 +8,7 @@ import { EuiBadge } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { AgentName } from '../../../../../../../typings/es_schemas/ui/fields/agent'; +import { AgentName } from '../../../../../../../../typings/es_schemas/ui/fields/agent'; export interface SyncBadgeProps { /** diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/span_flyout/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/span_flyout/index.tsx index 0087b0f9d1fac..0f7a6a295601b 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/span_flyout/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/span_flyout/index.tsx @@ -34,7 +34,7 @@ import { DurationSummaryItem } from '../../../../../../shared/summary/duration_s import { HttpInfoSummaryItem } from '../../../../../../shared/summary/http_info_summary_item'; import { TimestampTooltip } from '../../../../../../shared/timestamp_tooltip'; import { ResponsiveFlyout } from '../responsive_flyout'; -import { SyncBadge } from '../sync_badge'; +import { SyncBadge } from '../badge/sync_badge'; import { SpanDatabase } from './span_db'; import { StickySpanProperties } from './sticky_span_properties'; import { FailureBadge } from '../failure_badge'; diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/transaction_flyout/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/transaction_flyout/index.tsx index 5f1e0cacd8483..43a7ebfa2f97f 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/transaction_flyout/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/transaction_flyout/index.tsx @@ -87,6 +87,7 @@ export function TransactionFlyout({ transaction={transactionDoc} totalDuration={rootTransactionDuration} errorCount={errorCount} + coldStartBadge={transactionDoc.faas?.coldstart} /> diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/waterfall_item.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/waterfall_item.tsx index d8942cab36f77..51e9cbeaba6f7 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/waterfall_item.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/waterfall_item.tsx @@ -18,7 +18,8 @@ import { import { asDuration } from '../../../../../../../common/utils/formatters'; import { Margins } from '../../../../../shared/charts/timeline'; import { TruncateWithTooltip } from '../../../../../shared/truncate_with_tooltip'; -import { SyncBadge } from './sync_badge'; +import { SyncBadge } from './badge/sync_badge'; +import { ColdStartBadge } from './badge/cold_start_badge'; import { IWaterfallSpanOrTransaction } from './waterfall_helpers/waterfall_helpers'; import { FailureBadge } from './failure_badge'; import { useApmRouter } from '../../../../../../hooks/use_apm_router'; @@ -200,6 +201,8 @@ export function WaterfallItem({ const isCompositeSpan = item.docType === 'span' && item.doc.span.composite; const itemBarStyle = getItemBarStyle(item, color, width, left); + const isServerlessColdstart = + item.docType === 'transaction' && item.doc.faas?.coldstart; return ( )} + {isServerlessColdstart && } ); diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall_container.stories.data.ts b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall_container.stories.data.ts index f3331fba0ca23..d4af0e92c9054 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall_container.stories.data.ts +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall_container.stories.data.ts @@ -226,6 +226,9 @@ export const simpleTrace = { timestamp: { us: 1584975868787052, }, + faas: { + coldstart: true, + }, }, { parent: { diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall_container.stories.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall_container.stories.tsx index 312412a8cf827..db82e9e360207 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall_container.stories.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall_container.stories.tsx @@ -19,9 +19,18 @@ import { traceWithErrors, urlParams as testUrlParams, } from './waterfall_container.stories.data'; +import type { ApmPluginContextValue } from '../../../../../context/apm_plugin/apm_plugin_context'; type Args = ComponentProps; +const apmPluginContextMock = { + core: { + http: { + basePath: { prepend: () => {} }, + }, + }, +} as unknown as ApmPluginContextValue; + const stories: Meta = { title: 'app/TransactionDetails/waterfall', component: WaterfallContainer, @@ -32,7 +41,7 @@ const stories: Meta = { '/services/{serviceName}/transactions/view?rangeFrom=now-15m&rangeTo=now&transactionName=testTransactionName', ]} > - + diff --git a/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx index 39d522ca088fc..68315fc3b2b02 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx @@ -15,6 +15,7 @@ import { AggregatedTransactionsBadge } from '../../shared/aggregated_transaction import { TransactionCharts } from '../../shared/charts/transaction_charts'; import { replace } from '../../shared/links/url_helpers'; import { TransactionsTable } from '../../shared/transactions_table'; +import { isServerlessAgent } from '../../../../common/agent_name'; export function TransactionOverview() { const { @@ -24,12 +25,14 @@ export function TransactionOverview() { rangeFrom, rangeTo, transactionType: transactionTypeFromUrl, + comparisonEnabled, + comparisonType, }, } = useApmParams('/services/{serviceName}/transactions'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - const { transactionType, serviceName, fallbackToTransactions } = + const { transactionType, serviceName, fallbackToTransactions, runtimeName } = useApmServiceContext(); const history = useHistory(); @@ -45,6 +48,8 @@ export function TransactionOverview() { return null; } + const isServerless = isServerlessAgent(runtimeName); + return ( <> {fallbackToTransactions && ( @@ -62,6 +67,9 @@ export function TransactionOverview() { environment={environment} start={start} end={end} + isServerlessContext={isServerless} + comparisonEnabled={comparisonEnabled} + comparisonType={comparisonType} /> diff --git a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.test.tsx b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.test.tsx index 5a481b2d6f10c..03a50d6082583 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.test.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.test.tsx @@ -19,6 +19,7 @@ describe('APM service template', () => { { agentName: 'ios/swift' }, { agentName: 'opentelemetry/swift' }, { agentName: 'ruby', runtimeName: 'jruby' }, + { runtimeName: 'aws_lambda' }, ].map((input) => { it(`when input ${JSON.stringify(input)}`, () => { expect(isMetricsTabHidden(input)).toBeTruthy(); @@ -52,6 +53,7 @@ describe('APM service template', () => { { agentName: 'nodejs' }, { agentName: 'php' }, { agentName: 'python' }, + { runtimeName: 'aws_lambda' }, ].map((input) => { it(`when input ${JSON.stringify(input)}`, () => { expect(isJVMsTabHidden(input)).toBeTruthy(); diff --git a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx index 93c222164f026..20f907e03fc37 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx @@ -21,6 +21,7 @@ import { isJavaAgentName, isJRubyAgent, isRumAgentName, + isServerlessAgent, } from '../../../../../common/agent_name'; import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; import { ApmServiceContextProvider } from '../../../../context/apm_service/apm_service_context'; @@ -144,7 +145,8 @@ export function isMetricsTabHidden({ isRumAgentName(agentName) || isJavaAgentName(agentName) || isIosAgentName(agentName) || - isJRubyAgent(agentName, runtimeName) + isJRubyAgent(agentName, runtimeName) || + isServerlessAgent(runtimeName) ); } @@ -155,7 +157,10 @@ export function isJVMsTabHidden({ agentName?: string; runtimeName?: string; }) { - return !(isJavaAgentName(agentName) || isJRubyAgent(agentName, runtimeName)); + return ( + !(isJavaAgentName(agentName) || isJRubyAgent(agentName, runtimeName)) || + isServerlessAgent(runtimeName) + ); } function useTabs({ selectedTab }: { selectedTab: Tab['key'] }) { diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/index.tsx index ff1eec200a0c2..a2bfad0175a5f 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_charts/index.tsx @@ -12,7 +12,9 @@ import { ChartPointerEventContextProvider } from '../../../../context/chart_poin import { ServiceOverviewThroughputChart } from '../../../app/service_overview/service_overview_throughput_chart'; import { LatencyChart } from '../latency_chart'; import { TransactionBreakdownChart } from '../transaction_breakdown_chart'; +import { TransactionColdstartRateChart } from '../transaction_coldstart_rate_chart'; import { FailedTransactionRateChart } from '../failed_transaction_rate_chart'; +import { TimeRangeComparisonType } from '../../../../../common/runtime_types/comparison_type_rt'; export function TransactionCharts({ kuery, @@ -20,12 +22,18 @@ export function TransactionCharts({ start, end, transactionName, + isServerlessContext, + comparisonEnabled, + comparisonType, }: { kuery: string; environment: string; start: string; end: string; transactionName?: string; + isServerlessContext?: boolean; + comparisonEnabled?: boolean; + comparisonType?: TimeRangeComparisonType; }) { return ( <> @@ -56,12 +64,24 @@ export function TransactionCharts({ - - - + {isServerlessContext ? ( + + + + ) : ( + + + + )} diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx new file mode 100644 index 0000000000000..2b99562b67172 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx @@ -0,0 +1,184 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + EuiPanel, + EuiTitle, + EuiFlexGroup, + EuiFlexItem, + EuiIconTip, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { APIReturnType } from '../../../../services/rest/create_call_apm_api'; +import { asPercent } from '../../../../../common/utils/formatters'; +import { useFetcher } from '../../../../hooks/use_fetcher'; +import { useTheme } from '../../../../hooks/use_theme'; +import { TimeseriesChart } from '../timeseries_chart'; +import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context'; +import { + getComparisonChartTheme, + getTimeRangeComparison, +} from '../../time_comparison/get_time_range_comparison'; +import { useApmParams } from '../../../../hooks/use_apm_params'; +import { useTimeRange } from '../../../../hooks/use_time_range'; +import { TimeRangeComparisonType } from '../../../../../common/runtime_types/comparison_type_rt'; + +function yLabelFormat(y?: number | null) { + return asPercent(y || 0, 1); +} + +interface Props { + height?: number; + showAnnotations?: boolean; + kuery: string; + environment: string; + transactionName?: string; + comparisonEnabled?: boolean; + comparisonType?: TimeRangeComparisonType; +} + +type ColdstartRate = + APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate'>; + +const INITIAL_STATE: ColdstartRate = { + currentPeriod: { + transactionColdstartRate: [], + average: null, + }, + previousPeriod: { + transactionColdstartRate: [], + average: null, + }, +}; + +export function TransactionColdstartRateChart({ + height, + showAnnotations = true, + environment, + kuery, + transactionName, + comparisonEnabled, + comparisonType, +}: Props) { + const theme = useTheme(); + + const { + query: { rangeFrom, rangeTo }, + } = useApmParams('/services/{serviceName}'); + + const { start, end } = useTimeRange({ rangeFrom, rangeTo }); + + const { serviceName, transactionType } = useApmServiceContext(); + const comparisonChartThem = getComparisonChartTheme(); + const { comparisonStart, comparisonEnd } = getTimeRangeComparison({ + start, + end, + comparisonType, + comparisonEnabled, + }); + + const endpoint = transactionName + ? ('GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name' as const) + : ('GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate' as const); + + const { data = INITIAL_STATE, status } = useFetcher( + (callApmApi) => { + if (transactionType && serviceName && start && end) { + return callApmApi(endpoint, { + params: { + path: { + serviceName, + }, + query: { + environment, + kuery, + start, + end, + transactionType, + comparisonStart, + comparisonEnd, + ...(transactionName ? { transactionName } : {}), + }, + }, + }); + } + }, + [ + environment, + kuery, + serviceName, + start, + end, + transactionType, + transactionName, + comparisonStart, + comparisonEnd, + endpoint, + ] + ); + + const timeseries = [ + { + data: data.currentPeriod.transactionColdstartRate, + type: 'linemark', + color: theme.eui.euiColorVis5, + title: i18n.translate('xpack.apm.coldstartRate.chart.coldstartRate', { + defaultMessage: 'Cold start rate (avg.)', + }), + }, + ...(comparisonEnabled + ? [ + { + data: data.previousPeriod.transactionColdstartRate, + type: 'area', + color: theme.eui.euiColorMediumShade, + title: i18n.translate( + 'xpack.apm.coldstartRate.chart.coldstartRate.previousPeriodLabel', + { defaultMessage: 'Previous period' } + ), + }, + ] + : []), + ]; + + return ( + + + + +

+ {i18n.translate('xpack.apm.coldstartRate', { + defaultMessage: 'Cold start rate', + })} +

+
+
+ + + + +
+ +
+ ); +} diff --git a/x-pack/plugins/apm/public/components/shared/service_icons/cloud_details.tsx b/x-pack/plugins/apm/public/components/shared/service_icons/cloud_details.tsx index b5938167378d7..91780fec15845 100644 --- a/x-pack/plugins/apm/public/components/shared/service_icons/cloud_details.tsx +++ b/x-pack/plugins/apm/public/components/shared/service_icons/cloud_details.tsx @@ -5,7 +5,13 @@ * 2.0. */ -import { EuiBadge, EuiDescriptionList } from '@elastic/eui'; +import { + EuiBadge, + EuiDescriptionList, + EuiBetaBadge, + EuiFlexGroup, + EuiFlexItem, +} from '@elastic/eui'; import { EuiDescriptionListProps } from '@elastic/eui/src/components/description_list/description_list'; import { i18n } from '@kbn/i18n'; import React from 'react'; @@ -16,9 +22,10 @@ type ServiceDetailsReturnType = interface Props { cloud: ServiceDetailsReturnType['cloud']; + isServerless: boolean; } -export function CloudDetails({ cloud }: Props) { +export function CloudDetails({ cloud, isServerless }: Props) { if (!cloud) { return null; } @@ -36,6 +43,43 @@ export function CloudDetails({ cloud }: Props) { }); } + if (cloud.serviceName) { + listItems.push({ + title: i18n.translate( + 'xpack.apm.serviceIcons.serviceDetails.cloud.serviceNameLabel', + { + defaultMessage: 'Cloud service', + } + ), + description: ( + + {cloud.serviceName} + {isServerless && ( + + + + )} + + ), + }); + } + if (!!cloud.availabilityZones?.length) { listItems.push({ title: i18n.translate( @@ -58,7 +102,29 @@ export function CloudDetails({ cloud }: Props) { }); } - if (cloud.machineTypes) { + if (!!cloud.regions?.length) { + listItems.push({ + title: i18n.translate( + 'xpack.apm.serviceIcons.serviceDetails.cloud.regionLabel', + { + defaultMessage: + '{regions, plural, =0 {Region} one {Region} other {Regions}} ', + values: { regions: cloud.regions.length }, + } + ), + description: ( +
    + {cloud.regions.map((region, index) => ( +
  • + {region} +
  • + ))} +
+ ), + }); + } + + if (!!cloud.machineTypes?.length) { listItems.push({ title: i18n.translate( 'xpack.apm.serviceIcons.serviceDetails.cloud.machineTypesLabel', diff --git a/x-pack/plugins/apm/public/components/shared/service_icons/index.test.tsx b/x-pack/plugins/apm/public/components/shared/service_icons/index.test.tsx index 778cdeb9be3f7..2e15ea9f0db5f 100644 --- a/x-pack/plugins/apm/public/components/shared/service_icons/index.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/service_icons/index.test.tsx @@ -189,6 +189,7 @@ describe('ServiceIcons', () => { data: { agentName: 'java', containerType: 'Kubernetes', + serverlessType: 'lambda', cloudProvider: 'gcp', }, status: fetcherHook.FETCH_STATUS.SUCCESS, @@ -220,6 +221,7 @@ describe('ServiceIcons', () => { expect(queryAllByTestId('loading')).toHaveLength(0); expect(getByTestId('service')).toBeInTheDocument(); expect(getByTestId('container')).toBeInTheDocument(); + expect(getByTestId('serverless')).toBeInTheDocument(); expect(getByTestId('cloud')).toBeInTheDocument(); fireEvent.click(getByTestId('popover_Service')); expect(getByTestId('loading-content')).toBeInTheDocument(); @@ -231,6 +233,7 @@ describe('ServiceIcons', () => { data: { agentName: 'java', containerType: 'Kubernetes', + serverlessType: '', cloudProvider: 'gcp', }, status: fetcherHook.FETCH_STATUS.SUCCESS, @@ -269,5 +272,118 @@ describe('ServiceIcons', () => { expect(getByText('Service')).toBeInTheDocument(); expect(getByText('v1.0.0')).toBeInTheDocument(); }); + + it('shows serverless content', () => { + const apisMockData = { + 'GET /internal/apm/services/{serviceName}/metadata/icons': { + data: { + agentName: 'java', + containerType: 'Kubernetes', + serverlessType: 'lambda', + cloudProvider: 'gcp', + }, + status: fetcherHook.FETCH_STATUS.SUCCESS, + refetch: jest.fn(), + }, + 'GET /internal/apm/services/{serviceName}/metadata/details': { + data: { + serverless: { + type: '', + functionNames: ['lambda-java-dev'], + faasTriggerTypes: ['datasource', 'http'], + }, + }, + status: fetcherHook.FETCH_STATUS.SUCCESS, + refetch: jest.fn(), + }, + }; + jest + .spyOn(fetcherHook, 'useFetcher') + .mockImplementation((func: Function, deps: string[]) => { + return func(callApmApi(apisMockData)) || {}; + }); + + const { queryAllByTestId, getByTestId, getByText } = render( + + + + + + ); + expect(queryAllByTestId('loading')).toHaveLength(0); + expect(getByTestId('service')).toBeInTheDocument(); + expect(getByTestId('container')).toBeInTheDocument(); + expect(getByTestId('serverless')).toBeInTheDocument(); + expect(getByTestId('cloud')).toBeInTheDocument(); + + fireEvent.click(getByTestId('popover_Serverless')); + expect(queryAllByTestId('loading-content')).toHaveLength(0); + expect(getByText('Serverless')).toBeInTheDocument(); + expect(getByText('lambda-java-dev')).toBeInTheDocument(); + expect(getByText('datasource')).toBeInTheDocument(); + expect(getByText('http')).toBeInTheDocument(); + }); + + it('shows cloud content', () => { + const apisMockData = { + 'GET /internal/apm/services/{serviceName}/metadata/icons': { + data: { + agentName: 'java', + containerType: 'Kubernetes', + serverlessType: 'lambda', + cloudProvider: 'gcp', + }, + status: fetcherHook.FETCH_STATUS.SUCCESS, + refetch: jest.fn(), + }, + 'GET /internal/apm/services/{serviceName}/metadata/details': { + data: { + cloud: { + provider: 'aws', + projectName: '', + serviceName: 'lambda', + availabilityZones: [], + regions: ['us-east-1'], + machineTypes: [], + }, + }, + status: fetcherHook.FETCH_STATUS.SUCCESS, + refetch: jest.fn(), + }, + }; + jest + .spyOn(fetcherHook, 'useFetcher') + .mockImplementation((func: Function, deps: string[]) => { + return func(callApmApi(apisMockData)) || {}; + }); + + const { queryAllByTestId, getByTestId, getByText } = render( + + + + + + ); + expect(queryAllByTestId('loading')).toHaveLength(0); + expect(getByTestId('service')).toBeInTheDocument(); + expect(getByTestId('container')).toBeInTheDocument(); + expect(getByTestId('serverless')).toBeInTheDocument(); + expect(getByTestId('cloud')).toBeInTheDocument(); + + fireEvent.click(getByTestId('popover_Cloud')); + expect(queryAllByTestId('loading-content')).toHaveLength(0); + expect(getByText('Cloud')).toBeInTheDocument(); + expect(getByText('aws')).toBeInTheDocument(); + expect(getByText('lambda')).toBeInTheDocument(); + expect(getByText('us-east-1')).toBeInTheDocument(); + }); }); }); diff --git a/x-pack/plugins/apm/public/components/shared/service_icons/index.tsx b/x-pack/plugins/apm/public/components/shared/service_icons/index.tsx index 52c5ca37d818e..2fd578f10b110 100644 --- a/x-pack/plugins/apm/public/components/shared/service_icons/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/service_icons/index.tsx @@ -13,6 +13,7 @@ import { ContainerType } from '../../../../common/service_metadata'; import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher'; import { getAgentIcon } from '../agent_icon/get_agent_icon'; import { CloudDetails } from './cloud_details'; +import { ServerlessDetails } from './serverless_details'; import { ContainerDetails } from './container_details'; import { IconPopover } from './icon_popover'; import { ServiceDetails } from './service_details'; @@ -47,7 +48,7 @@ export function getContainerIcon(container?: ContainerType) { } } -type Icons = 'service' | 'container' | 'cloud' | 'alerts'; +type Icons = 'service' | 'container' | 'serverless' | 'cloud' | 'alerts'; export interface PopoverItem { key: Icons; @@ -130,6 +131,17 @@ export function ServiceIcons({ start, end, serviceName }: Props) { }), component: , }, + { + key: 'serverless', + icon: { + type: getAgentIcon(icons?.serverlessType, theme.darkMode) || 'node', + }, + isVisible: !!icons?.serverlessType, + title: i18n.translate('xpack.apm.serviceIcons.serverless', { + defaultMessage: 'Serverless', + }), + component: , + }, { key: 'cloud', icon: { @@ -139,7 +151,12 @@ export function ServiceIcons({ start, end, serviceName }: Props) { title: i18n.translate('xpack.apm.serviceIcons.cloud', { defaultMessage: 'Cloud', }), - component: , + component: ( + + ), }, ]; diff --git a/x-pack/plugins/apm/public/components/shared/service_icons/serverless_details.tsx b/x-pack/plugins/apm/public/components/shared/service_icons/serverless_details.tsx new file mode 100644 index 0000000000000..d05abab6d674a --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/service_icons/serverless_details.tsx @@ -0,0 +1,73 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiBadge, EuiDescriptionList } from '@elastic/eui'; +import { EuiDescriptionListProps } from '@elastic/eui/src/components/description_list/description_list'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { APIReturnType } from '../../../services/rest/create_call_apm_api'; + +type ServiceDetailsReturnType = + APIReturnType<'GET /internal/apm/services/{serviceName}/metadata/details'>; + +interface Props { + serverless: ServiceDetailsReturnType['serverless']; +} + +export function ServerlessDetails({ serverless }: Props) { + if (!serverless) { + return null; + } + + const listItems: EuiDescriptionListProps['listItems'] = []; + + if (!!serverless.functionNames?.length) { + listItems.push({ + title: i18n.translate( + 'xpack.apm.serviceIcons.serviceDetails.cloud.functionNameLabel', + { + defaultMessage: + '{functionNames, plural, =0 {Function name} one {Function name} other {Function names}} ', + values: { functionNames: serverless.functionNames.length }, + } + ), + description: ( +
    + {serverless.functionNames.map((type, index) => ( +
  • + {type} +
  • + ))} +
+ ), + }); + } + + if (!!serverless.faasTriggerTypes?.length) { + listItems.push({ + title: i18n.translate( + 'xpack.apm.serviceIcons.serviceDetails.cloud.faasTriggerTypeLabel', + { + defaultMessage: + '{triggerTypes, plural, =0 {Trigger type} one {Trigger type} other {Trigger types}} ', + values: { triggerTypes: serverless.faasTriggerTypes.length }, + } + ), + description: ( +
    + {serverless.faasTriggerTypes.map((type, index) => ( +
  • + {type} +
  • + ))} +
+ ), + }); + } + + return ; +} diff --git a/x-pack/plugins/apm/public/components/shared/summary/transaction_summary.tsx b/x-pack/plugins/apm/public/components/shared/summary/transaction_summary.tsx index 399121b710ce9..7ceec331ae8fe 100644 --- a/x-pack/plugins/apm/public/components/shared/summary/transaction_summary.tsx +++ b/x-pack/plugins/apm/public/components/shared/summary/transaction_summary.tsx @@ -14,11 +14,13 @@ import { ErrorCountSummaryItemBadge } from './error_count_summary_item_badge'; import { HttpInfoSummaryItem } from './http_info_summary_item'; import { TransactionResultSummaryItem } from './transaction_result_summary_item'; import { UserAgentSummaryItem } from './user_agent_summary_item'; +import { ColdStartBadge } from '../../app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/badge/cold_start_badge'; interface Props { transaction: Transaction; totalDuration: number | undefined; errorCount: number; + coldStartBadge?: boolean; } function getTransactionResultSummaryItem(transaction: Transaction) { @@ -39,7 +41,12 @@ function getTransactionResultSummaryItem(transaction: Transaction) { return null; } -function TransactionSummary({ transaction, totalDuration, errorCount }: Props) { +function TransactionSummary({ + transaction, + totalDuration, + errorCount, + coldStartBadge, +}: Props) { const items = [ , ) : null, + coldStartBadge ? : null, ]; return ; diff --git a/x-pack/plugins/apm/server/lib/helpers/transaction_coldstart_rate.ts b/x-pack/plugins/apm/server/lib/helpers/transaction_coldstart_rate.ts new file mode 100644 index 0000000000000..094d5ed6350df --- /dev/null +++ b/x-pack/plugins/apm/server/lib/helpers/transaction_coldstart_rate.ts @@ -0,0 +1,67 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FAAS_COLDSTART } from '../../../common/elasticsearch_fieldnames'; +import { + AggregationOptionsByType, + AggregationResultOf, +} from '../../../../../../src/core/types/elasticsearch'; + +export const getColdstartAggregation = () => ({ + terms: { + field: FAAS_COLDSTART, + }, +}); + +type ColdstartAggregation = ReturnType; + +export const getTimeseriesAggregation = ( + start: number, + end: number, + intervalString: string +) => ({ + date_histogram: { + field: '@timestamp', + fixed_interval: intervalString, + min_doc_count: 0, + extended_bounds: { min: start, max: end }, + }, + aggs: { coldstartStates: getColdstartAggregation() }, +}); + +export function calculateTransactionColdstartRate( + coldstartStatesResponse: AggregationResultOf +) { + const coldstartStates = Object.fromEntries( + coldstartStatesResponse.buckets.map(({ key, doc_count: count }) => [ + key === 1 ? 'true' : 'false', + count, + ]) + ); + + const coldstarts = coldstartStates.true ?? 0; + const warmstarts = coldstartStates.false ?? 0; + + return coldstarts / (coldstarts + warmstarts); +} + +export function getTransactionColdstartRateTimeSeries( + buckets: AggregationResultOf< + { + date_histogram: AggregationOptionsByType['date_histogram']; + aggs: { coldstartStates: ColdstartAggregation }; + }, + {} + >['buckets'] +) { + return buckets.map((dateBucket) => { + return { + x: dateBucket.key, + y: calculateTransactionColdstartRate(dateBucket.coldstartStates), + }; + }); +} diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/get_coldstart_rate.ts b/x-pack/plugins/apm/server/lib/transaction_groups/get_coldstart_rate.ts new file mode 100644 index 0000000000000..e7c9e111be7a5 --- /dev/null +++ b/x-pack/plugins/apm/server/lib/transaction_groups/get_coldstart_rate.ts @@ -0,0 +1,181 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + FAAS_COLDSTART, + SERVICE_NAME, + TRANSACTION_NAME, + TRANSACTION_TYPE, +} from '../../../common/elasticsearch_fieldnames'; +import { offsetPreviousPeriodCoordinates } from '../../../common/utils/offset_previous_period_coordinate'; +import { kqlQuery, rangeQuery } from '../../../../observability/server'; +import { environmentQuery } from '../../../common/utils/environment_query'; +import { Coordinate } from '../../../typings/timeseries'; +import { + getDocumentTypeFilterForTransactions, + getProcessorEventForTransactions, +} from '../helpers/transactions'; +import { getBucketSizeForAggregatedTransactions } from '../helpers/get_bucket_size_for_aggregated_transactions'; +import { Setup } from '../helpers/setup_request'; +import { + calculateTransactionColdstartRate, + getColdstartAggregation, + getTransactionColdstartRateTimeSeries, +} from '../helpers/transaction_coldstart_rate'; +import { termQuery } from '../../../../observability/server'; + +export async function getColdstartRate({ + environment, + kuery, + serviceName, + transactionType, + transactionName, + setup, + searchAggregatedTransactions, + start, + end, +}: { + environment: string; + kuery: string; + serviceName: string; + transactionType?: string; + transactionName: string; + setup: Setup; + searchAggregatedTransactions: boolean; + start: number; + end: number; +}): Promise<{ + transactionColdstartRate: Coordinate[]; + average: number | null; +}> { + const { apmEventClient } = setup; + + const filter = [ + ...termQuery(SERVICE_NAME, serviceName), + { exists: { field: FAAS_COLDSTART } }, + ...(transactionName ? termQuery(TRANSACTION_NAME, transactionName) : []), + ...termQuery(TRANSACTION_TYPE, transactionType), + ...getDocumentTypeFilterForTransactions(searchAggregatedTransactions), + ...rangeQuery(start, end), + ...environmentQuery(environment), + ...kqlQuery(kuery), + ]; + + const coldstartStates = getColdstartAggregation(); + + const params = { + apm: { + events: [getProcessorEventForTransactions(searchAggregatedTransactions)], + }, + body: { + size: 0, + query: { bool: { filter } }, + aggs: { + coldstartStates, + timeseries: { + date_histogram: { + field: '@timestamp', + fixed_interval: getBucketSizeForAggregatedTransactions({ + start, + end, + searchAggregatedTransactions, + }).intervalString, + min_doc_count: 0, + extended_bounds: { min: start, max: end }, + }, + aggs: { + coldstartStates, + }, + }, + }, + }, + }; + + const resp = await apmEventClient.search( + 'get_transaction_group_coldstart_rate', + params + ); + + if (!resp.aggregations) { + return { transactionColdstartRate: [], average: null }; + } + + const transactionColdstartRate = getTransactionColdstartRateTimeSeries( + resp.aggregations.timeseries.buckets + ); + + const average = calculateTransactionColdstartRate( + resp.aggregations.coldstartStates + ); + + return { transactionColdstartRate, average }; +} + +export async function getColdstartRatePeriods({ + environment, + kuery, + serviceName, + transactionType, + transactionName = '', + setup, + searchAggregatedTransactions, + comparisonStart, + comparisonEnd, + start, + end, +}: { + environment: string; + kuery: string; + serviceName: string; + transactionType?: string; + transactionName?: string; + setup: Setup; + searchAggregatedTransactions: boolean; + comparisonStart?: number; + comparisonEnd?: number; + start: number; + end: number; +}) { + const commonProps = { + environment, + kuery, + serviceName, + transactionType, + transactionName, + setup, + searchAggregatedTransactions, + }; + + const currentPeriodPromise = getColdstartRate({ ...commonProps, start, end }); + + const previousPeriodPromise = + comparisonStart && comparisonEnd + ? getColdstartRate({ + ...commonProps, + start: comparisonStart, + end: comparisonEnd, + }) + : { transactionColdstartRate: [], average: null }; + + const [currentPeriod, previousPeriod] = await Promise.all([ + currentPeriodPromise, + previousPeriodPromise, + ]); + + const firstCurrentPeriod = currentPeriod.transactionColdstartRate; + + return { + currentPeriod, + previousPeriod: { + ...previousPeriod, + transactionColdstartRate: offsetPreviousPeriodCoordinates({ + currentPeriodTimeseries: firstCurrentPeriod, + previousPeriodTimeseries: previousPeriod.transactionColdstartRate, + }), + }, + }; +} diff --git a/x-pack/plugins/apm/server/routes/services/get_service_metadata_details.ts b/x-pack/plugins/apm/server/routes/services/get_service_metadata_details.ts index b7ce68a0de578..6b7f16084e5f3 100644 --- a/x-pack/plugins/apm/server/routes/services/get_service_metadata_details.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_metadata_details.ts @@ -10,7 +10,9 @@ import { AGENT, CLOUD, CLOUD_AVAILABILITY_ZONE, + CLOUD_REGION, CLOUD_MACHINE_TYPE, + CLOUD_SERVICE_NAME, CONTAINER_ID, HOST, KUBERNETES, @@ -18,6 +20,8 @@ import { SERVICE_NAME, SERVICE_NODE_NAME, SERVICE_VERSION, + FAAS_ID, + FAAS_TRIGGER_TYPE, } from '../../../common/elasticsearch_fieldnames'; import { ContainerType } from '../../../common/service_metadata'; import { rangeQuery } from '../../../../observability/server'; @@ -50,11 +54,18 @@ export interface ServiceMetadataDetails { totalNumberInstances?: number; type?: ContainerType; }; + serverless?: { + type?: string; + functionNames?: string[]; + faasTriggerTypes?: string[]; + }; cloud?: { provider?: string; availabilityZones?: string[]; + regions?: string[]; machineTypes?: string[]; projectName?: string; + serviceName?: string; }; } @@ -104,12 +115,36 @@ export async function getServiceMetadataDetails({ size: 10, }, }, + regions: { + terms: { + field: CLOUD_REGION, + size: 10, + }, + }, + cloudServices: { + terms: { + field: CLOUD_SERVICE_NAME, + size: 1, + }, + }, machineTypes: { terms: { field: CLOUD_MACHINE_TYPE, size: 10, }, }, + faasTriggerTypes: { + terms: { + field: FAAS_TRIGGER_TYPE, + size: 10, + }, + }, + faasFunctionNames: { + terms: { + field: FAAS_ID, + size: 10, + }, + }, totalNumberInstances: { cardinality: { field: SERVICE_NODE_NAME } }, }, }, @@ -153,13 +188,30 @@ export async function getServiceMetadataDetails({ } : undefined; + const serverlessDetails = + !!response.aggregations?.faasTriggerTypes?.buckets.length && cloud + ? { + type: cloud.service?.name, + functionNames: response.aggregations?.faasFunctionNames.buckets + .map((bucket) => getLambdaFunctionNameFromARN(bucket.key as string)) + .filter((name) => name), + faasTriggerTypes: response.aggregations?.faasTriggerTypes.buckets.map( + (bucket) => bucket.key as string + ), + } + : undefined; + const cloudDetails = cloud ? { provider: cloud.provider, projectName: cloud.project?.name, + serviceName: cloud.service?.name, availabilityZones: response.aggregations?.availabilityZones.buckets.map( (bucket) => bucket.key as string ), + regions: response.aggregations?.regions.buckets.map( + (bucket) => bucket.key as string + ), machineTypes: response.aggregations?.machineTypes.buckets.map( (bucket) => bucket.key as string ), @@ -169,6 +221,12 @@ export async function getServiceMetadataDetails({ return { service: serviceMetadataDetails, container: containerDetails, + serverless: serverlessDetails, cloud: cloudDetails, }; } + +function getLambdaFunctionNameFromARN(arn: string) { + // Lambda function ARN example: arn:aws:lambda:us-west-2:123456789012:function:my-function + return arn.split(':')[6] || ''; +} diff --git a/x-pack/plugins/apm/server/routes/services/get_service_metadata_icons.ts b/x-pack/plugins/apm/server/routes/services/get_service_metadata_icons.ts index ca97e9d58f060..6082ae6c5b112 100644 --- a/x-pack/plugins/apm/server/routes/services/get_service_metadata_icons.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_metadata_icons.ts @@ -9,6 +9,7 @@ import { ProcessorEvent } from '../../../common/processor_event'; import { AGENT_NAME, CLOUD_PROVIDER, + CLOUD_SERVICE_NAME, CONTAINER_ID, KUBERNETES, SERVICE_NAME, @@ -29,6 +30,7 @@ type ServiceMetadataIconsRaw = Pick< export interface ServiceMetadataIcons { agentName?: string; containerType?: ContainerType; + serverlessType?: string; cloudProvider?: string; } @@ -70,7 +72,13 @@ export async function getServiceMetadataIcons({ }, body: { size: 1, - _source: [KUBERNETES, CLOUD_PROVIDER, CONTAINER_ID, AGENT_NAME], + _source: [ + KUBERNETES, + CLOUD_PROVIDER, + CONTAINER_ID, + AGENT_NAME, + CLOUD_SERVICE_NAME, + ], query: { bool: { filter, should } }, }, }; @@ -85,6 +93,7 @@ export async function getServiceMetadataIcons({ agentName: undefined, containerType: undefined, cloudProvider: undefined, + serverlessType: undefined, }; } @@ -98,9 +107,15 @@ export async function getServiceMetadataIcons({ containerType = 'Docker'; } + let serverlessType: string | undefined; + if (cloud?.provider === 'aws' && cloud?.service?.name === 'lambda') { + serverlessType = 'lambda'; + } + return { agentName: agent?.name, containerType, + serverlessType, cloudProvider: cloud?.provider, }; } diff --git a/x-pack/plugins/apm/server/routes/transactions/route.ts b/x-pack/plugins/apm/server/routes/transactions/route.ts index e22e521c699ec..657387037855f 100644 --- a/x-pack/plugins/apm/server/routes/transactions/route.ts +++ b/x-pack/plugins/apm/server/routes/transactions/route.ts @@ -19,6 +19,7 @@ import { getTransactionBreakdown } from './breakdown'; import { getTransactionTraceSamples } from './trace_samples'; import { getLatencyPeriods } from './get_latency_charts'; import { getFailedTransactionRatePeriods } from './get_failed_transaction_rate_periods'; +import { getColdstartRatePeriods } from '../../lib/transaction_groups/get_coldstart_rate'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; import { comparisonRangeRt, @@ -461,6 +462,158 @@ const transactionChartsErrorRateRoute = createApmServerRoute({ }, }); +const transactionChartsColdstartRateRoute = createApmServerRoute({ + endpoint: + 'GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate', + params: t.type({ + path: t.type({ + serviceName: t.string, + }), + query: t.intersection([ + t.type({ transactionType: t.string }), + t.intersection([environmentRt, kueryRt, rangeRt, comparisonRangeRt]), + ]), + }), + options: { tags: ['access:apm'] }, + handler: async ( + resources + ): Promise<{ + currentPeriod: { + transactionColdstartRate: Array< + import('../../../typings/timeseries').Coordinate + >; + average: number | null; + }; + previousPeriod: + | { + transactionColdstartRate: Array<{ + x: number; + y: import('../../../typings/common').Maybe; + }>; + average: number | null; + } + | { + transactionColdstartRate: Array<{ + x: number; + y: import('../../../typings/common').Maybe; + }>; + average: null; + }; + }> => { + const setup = await setupRequest(resources); + + const { params } = resources; + const { serviceName } = params.path; + const { + environment, + kuery, + transactionType, + comparisonStart, + comparisonEnd, + start, + end, + } = params.query; + + const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + ...setup, + kuery, + start, + end, + }); + + return getColdstartRatePeriods({ + environment, + kuery, + serviceName, + transactionType, + setup, + searchAggregatedTransactions, + comparisonStart, + comparisonEnd, + start, + end, + }); + }, +}); + +const transactionChartsColdstartRateByTransactionNameRoute = + createApmServerRoute({ + endpoint: + 'GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name', + params: t.type({ + path: t.type({ + serviceName: t.string, + }), + query: t.intersection([ + t.type({ transactionType: t.string, transactionName: t.string }), + t.intersection([environmentRt, kueryRt, rangeRt, comparisonRangeRt]), + ]), + }), + options: { tags: ['access:apm'] }, + handler: async ( + resources + ): Promise<{ + currentPeriod: { + transactionColdstartRate: Array< + import('../../../typings/timeseries').Coordinate + >; + average: number | null; + }; + previousPeriod: + | { + transactionColdstartRate: Array<{ + x: number; + y: import('../../../typings/common').Maybe; + }>; + average: number | null; + } + | { + transactionColdstartRate: Array<{ + x: number; + y: import('../../../typings/common').Maybe; + }>; + average: null; + }; + }> => { + const setup = await setupRequest(resources); + + const { params } = resources; + const { serviceName } = params.path; + const { + environment, + kuery, + transactionType, + transactionName, + comparisonStart, + comparisonEnd, + start, + end, + } = params.query; + + const searchAggregatedTransactions = + await getSearchAggregatedTransactions({ + ...setup, + kuery, + start, + end, + }); + + return getColdstartRatePeriods({ + environment, + kuery, + serviceName, + transactionType, + transactionName, + setup, + searchAggregatedTransactions, + comparisonStart, + comparisonEnd, + start, + end, + }); + }, + }); + export const transactionRouteRepository = { ...transactionGroupsMainStatisticsRoute, ...transactionGroupsDetailedStatisticsRoute, @@ -468,4 +621,6 @@ export const transactionRouteRepository = { ...transactionTraceSamplesRoute, ...transactionChartsBreakdownRoute, ...transactionChartsErrorRateRoute, + ...transactionChartsColdstartRateRoute, + ...transactionChartsColdstartRateByTransactionNameRoute, }; diff --git a/x-pack/plugins/apm/typings/es_schemas/raw/fields/cloud.ts b/x-pack/plugins/apm/typings/es_schemas/raw/fields/cloud.ts index 8891318554e92..bc0c3ea8002ad 100644 --- a/x-pack/plugins/apm/typings/es_schemas/raw/fields/cloud.ts +++ b/x-pack/plugins/apm/typings/es_schemas/raw/fields/cloud.ts @@ -27,4 +27,7 @@ export interface Cloud { image?: { id: string; }; + service?: { + name: string; + }; } diff --git a/x-pack/plugins/cases/public/components/connectors/case/types.ts b/x-pack/plugins/apm/typings/es_schemas/raw/fields/faas.ts similarity index 58% rename from x-pack/plugins/cases/public/components/connectors/case/types.ts rename to x-pack/plugins/apm/typings/es_schemas/raw/fields/faas.ts index aec9e09ea198c..1229b8134ac13 100644 --- a/x-pack/plugins/cases/public/components/connectors/case/types.ts +++ b/x-pack/plugins/apm/typings/es_schemas/raw/fields/faas.ts @@ -5,14 +5,12 @@ * 2.0. */ -export interface CaseActionParams { - subAction: string; - subActionParams: { - caseId: string; - comment: { - alertId: string; - index: string; - type: 'alert'; - }; +export interface Faas { + id: string; + coldstart?: boolean; + execution?: string; + trigger?: { + type?: string; + request_id?: string; }; } diff --git a/x-pack/plugins/apm/typings/es_schemas/raw/transaction_raw.ts b/x-pack/plugins/apm/typings/es_schemas/raw/transaction_raw.ts index 34c391134b604..0811bfb8c1a79 100644 --- a/x-pack/plugins/apm/typings/es_schemas/raw/transaction_raw.ts +++ b/x-pack/plugins/apm/typings/es_schemas/raw/transaction_raw.ts @@ -19,6 +19,7 @@ import { TimestampUs } from './fields/timestamp_us'; import { Url } from './fields/url'; import { User } from './fields/user'; import { UserAgent } from './fields/user_agent'; +import { Faas } from './fields/faas'; interface Processor { name: 'transaction'; @@ -69,4 +70,5 @@ export interface TransactionRaw extends APMBaseDoc { user?: User; user_agent?: UserAgent; cloud?: Cloud; + faas?: Faas; } diff --git a/x-pack/plugins/cases/README.md b/x-pack/plugins/cases/README.md index 012a715dbb6cd..e43d3c8f47087 100644 --- a/x-pack/plugins/cases/README.md +++ b/x-pack/plugins/cases/README.md @@ -104,8 +104,8 @@ Arguments: | owner | `string[];` owner ids of the cases | | alertData? | `Omit;` alert data to post to case | | hiddenStatuses? | `CaseStatuses[];` array of hidden statuses | -| onRowClick | (theCase?: Case | SubCase) => void; callback for row click, passing case in row | -| updateCase? | (theCase: Case | SubCase) => void; callback after case has been updated | +| onRowClick | (theCase?: Case) => void; callback for row click, passing case in row | +| updateCase? | (theCase: Case) => void; callback after case has been updated | | onClose? | `() => void` called when the modal is closed without selecting a case | UI component: @@ -140,123 +140,6 @@ Arguments: UI component: ![Recent Cases Component][recent-cases-img] -## Case Action Type - -_**\*Feature in development, disabled by default**_ - -See [Kibana Actions](https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions) for more information. - -ID: `.case` - -The params properties are modelled after the arguments to the [Cases API](https://www.elastic.co/guide/en/security/master/cases-api-overview.html). - -### `config` - -This action has no `config` properties. - -### `secrets` - -This action type has no `secrets` properties. - -### `params` - -| Property | Description | Type | -| --------------- | ------------------------------------------------------------------------- | ------ | -| subAction | The sub action to perform. It can be `create`, `update`, and `addComment` | string | -| subActionParams | The parameters of the sub action | object | - -#### `subActionParams (create)` - -| Property | Description | Type | -| ----------- | --------------------------------------------------------------------- | ----------------------- | -| tile | The case’s title. | string | -| description | The case’s description. | string | -| tags | String array containing words and phrases that help categorize cases. | string[] | -| connector | Object containing the connector’s configuration. | [connector](#connector) | -| settings | Object containing the case’s settings. | [settings](#settings) | - -#### `subActionParams (update)` - -| Property | Description | Type | -| ----------- | ------------------------------------------------------------------------- | ----------------------- | -| id | The ID of the case being updated. | string | -| tile | The updated case title. | string | -| description | The updated case description. | string | -| tags | The updated case tags. | string | -| connector | Object containing the connector’s configuration. | [connector](#connector) | -| status | The updated case status, which can be: `open`, `in-progress` or `closed`. | string | -| settings | Object containing the case’s settings. | [settings](#settings) | -| version | The current case version. | string | - -#### `subActionParams (addComment)` - -| Property | Description | Type | -| -------- | ------------------------ | ------ | -| type | The type of the comment. | `user` | -| comment | The comment. | string | - -#### `connector` - -| Property | Description | Type | -| -------- | --------------------------------------------------------------------------------------------------------------------------------- | ----------------- | -| id | ID of the connector used for pushing case updates to external systems. | string | -| name | The connector name. | string | -| type | The type of the connector. Must be one of these: `.servicenow`, `.servicenow-sir`, `.swimlane`, `jira`, `.resilient`, and `.none` | string | -| fields | Object containing the connector’s fields. | [fields](#fields) | - -#### `fields` - -For ServiceNow ITSM connectors (`.servicenow`): - -| Property | Description | Type | -| ----------- | ------------------------------ | ------ | -| urgency | The urgency of the incident. | string | -| severity | The severity of the incident. | string | -| impact | The impact of the incident. | string | -| category | The category in ServiceNow. | string | -| subcategory | The subcategory in ServiceNow. | string | - -For ServiceNow SecOps connectors (`.servicenow-sir`): - -| Property | Description | Type | -| ----------- | ----------------------------------------------------------------- | ------- | -| category | The category in ServiceNow. | string | -| destIp | Include all destination IPs from all alerts attached to the case. | boolean | -| malwareHash | Include all malware hashes from all alerts attached to the case. | boolean | -| malwareUrl | Include all malware URLs from all alerts attached to the case. | boolean | -| priority | The priority of the incident. | string | -| sourceIp | Include all sources IPs from all alerts attached to the case. | boolean | -| subcategory | The subcategory in ServiceNow. | string | - -For Jira connectors (`.jira`): - -| Property | Description | Type | -| --------- | -------------------------------------------------------------------- | ------ | -| issueType | The issue type of the issue. | string | -| priority | The priority of the issue. | string | -| parent | The key of the parent issue (Valid when the issue type is Sub-task). | string | - -For IBM Resilient connectors (`.resilient`): - -| Property | Description | Type | -| ------------ | ------------------------------- | -------- | -| issueTypes | The issue types of the issue. | string[] | -| severityCode | The severity code of the issue. | string | - -For Swimlane (`.swimlane`): - -| Property | Description | Type | -| -------- | ------------------- | ------ | -| caseId | The ID of the case. | string | - -Connectors of type (`.none`) should have the `fields` attribute set to `null`. - -#### `settings` - -| Property | Description | Type | -| ---------- | ------------------------------ | ------- | -| syncAlerts | Turn on or off alert synching. | boolean | - diff --git a/x-pack/plugins/cases/common/api/cases/case.ts b/x-pack/plugins/cases/common/api/cases/case.ts index 3e9f59441208d..061a720bdf9c3 100644 --- a/x-pack/plugins/cases/common/api/cases/case.ts +++ b/x-pack/plugins/cases/common/api/cases/case.ts @@ -12,7 +12,6 @@ import { UserRT } from '../user'; import { CommentResponseRt } from './comment'; import { CasesStatusResponseRt, CaseStatusRt } from './status'; import { CaseConnectorRt } from '../connectors'; -import { SubCaseResponseRt } from './sub_case'; const BucketsAggs = rt.array( rt.type({ @@ -36,18 +35,6 @@ export const CasesByAlertIdRt = rt.array( }) ); -export enum CaseType { - collection = 'collection', - individual = 'individual', -} - -/** - * Exposing the field used to define the case type so that it can be used for filtering in saved object find queries. - */ -export const caseTypeField = 'type'; - -const CaseTypeRt = rt.union([rt.literal(CaseType.collection), rt.literal(CaseType.individual)]); - export const SettingsRt = rt.type({ syncAlerts: rt.boolean, }); @@ -69,10 +56,6 @@ const CaseBasicRt = rt.type({ * The title of a case */ title: rt.string, - /** - * The type of a case (individual or collection) - */ - [caseTypeField]: CaseTypeRt, /** * The external system that the case can be synced with */ @@ -122,7 +105,7 @@ export const CaseAttributesRt = rt.intersection([ }), ]); -const CasePostRequestNoTypeRt = rt.type({ +export const CasePostRequestRt = rt.type({ /** * Description of the case */ @@ -150,33 +133,7 @@ const CasePostRequestNoTypeRt = rt.type({ owner: rt.string, }); -/** - * This type is used for validating a create case request. It requires that the type field be defined. - */ -export const CasesClientPostRequestRt = rt.type({ - ...CasePostRequestNoTypeRt.props, - [caseTypeField]: CaseTypeRt, -}); - -/** - * This type is not used for validation when decoding a request because intersection does not have props defined which - * required for the excess function. Instead we use this as the type used by the UI. This allows the type field to be - * optional and the server will handle setting it to a default value before validating that the request - * has all the necessary fields. CasesClientPostRequestRt is used for validation. - */ -export const CasePostRequestRt = rt.intersection([ - /** - * The case type: an individual case (one without children) or a collection case (one with children) - */ - rt.partial({ [caseTypeField]: CaseTypeRt }), - CasePostRequestNoTypeRt, -]); - export const CasesFindRequestRt = rt.partial({ - /** - * Type of a case (individual, or collection) - */ - type: CaseTypeRt, /** * Tags to filter by */ @@ -248,8 +205,6 @@ export const CaseResponseRt = rt.intersection([ version: rt.string, }), rt.partial({ - subCaseIds: rt.array(rt.string), - subCases: rt.array(SubCaseResponseRt), comments: rt.array(CommentResponseRt), }), ]); @@ -321,12 +276,7 @@ export const AllTagsFindRequestRt = rt.partial({ export const AllReportersFindRequestRt = AllTagsFindRequestRt; export type CaseAttributes = rt.TypeOf; -/** - * This field differs from the CasePostRequest in that the post request's type field can be optional. This type requires - * that the type field be defined. The CasePostRequest should be used in most places (the UI etc). This type is really - * only necessary for validation. - */ -export type CasesClientPostRequest = rt.TypeOf; + export type CasePostRequest = rt.TypeOf; export type CaseResponse = rt.TypeOf; export type CaseResolveResponse = rt.TypeOf; diff --git a/x-pack/plugins/cases/common/api/cases/comment.ts b/x-pack/plugins/cases/common/api/cases/comment.ts index 19ad15286db6a..900f90156d431 100644 --- a/x-pack/plugins/cases/common/api/cases/comment.ts +++ b/x-pack/plugins/cases/common/api/cases/comment.ts @@ -10,22 +10,7 @@ import { SavedObjectFindOptionsRt } from '../saved_object'; import { UserRT } from '../user'; -/** - * this is used to differentiate between an alert attached to a top-level case and a group of alerts that should only - * be attached to a sub case. The reason we need this is because an alert group comment will have references to both a case and - * sub case when it is created. For us to be able to filter out alert groups in a top-level case we need a field to - * use as a filter. - */ -export enum AssociationType { - case = 'case', - subCase = 'sub_case', -} - export const CommentAttributesBasicRt = rt.type({ - associationType: rt.union([ - rt.literal(AssociationType.case), - rt.literal(AssociationType.subCase), - ]), created_at: rt.string, created_by: UserRT, owner: rt.string, @@ -38,7 +23,6 @@ export const CommentAttributesBasicRt = rt.type({ export enum CommentType { user = 'user', alert = 'alert', - generatedAlert = 'generated_alert', actions = 'actions', } @@ -59,7 +43,7 @@ export const ContextTypeUserRt = rt.type({ * it matches this structure. User attached alerts do not need to be transformed. */ export const AlertCommentRequestRt = rt.type({ - type: rt.union([rt.literal(CommentType.generatedAlert), rt.literal(CommentType.alert)]), + type: rt.literal(CommentType.alert), alertId: rt.union([rt.array(rt.string), rt.string]), index: rt.union([rt.array(rt.string), rt.string]), rule: rt.type({ @@ -167,10 +151,6 @@ export const AllCommentsResponseRt = rt.array(CommentResponseRt); export const FindQueryParamsRt = rt.partial({ ...SavedObjectFindOptionsRt.props, - /** - * If specified the attachments found will be associated to a sub case instead of a case object - */ - subCaseId: rt.string, }); export type FindQueryParams = rt.TypeOf; diff --git a/x-pack/plugins/cases/common/api/cases/index.ts b/x-pack/plugins/cases/common/api/cases/index.ts index ba8ad15d02e27..2bcad0c556e63 100644 --- a/x-pack/plugins/cases/common/api/cases/index.ts +++ b/x-pack/plugins/cases/common/api/cases/index.ts @@ -10,6 +10,5 @@ export * from './configure'; export * from './comment'; export * from './status'; export * from './user_actions'; -export * from './sub_case'; export * from './constants'; export * from './alerts'; diff --git a/x-pack/plugins/cases/common/api/cases/sub_case.ts b/x-pack/plugins/cases/common/api/cases/sub_case.ts deleted file mode 100644 index 187778f4a4fab..0000000000000 --- a/x-pack/plugins/cases/common/api/cases/sub_case.ts +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as rt from 'io-ts'; - -import { NumberFromString } from '../saved_object'; -import { UserRT } from '../user'; -import { CommentResponseRt } from './comment'; -import { CaseStatusRt, CasesStatusResponseRt } from './status'; - -const SubCaseBasicRt = rt.type({ - /** - * The status of the sub case (open, closed, in-progress) - */ - status: CaseStatusRt, -}); - -export const SubCaseAttributesRt = rt.intersection([ - SubCaseBasicRt, - rt.type({ - closed_at: rt.union([rt.string, rt.null]), - closed_by: rt.union([UserRT, rt.null]), - created_at: rt.string, - created_by: rt.union([UserRT, rt.null]), - updated_at: rt.union([rt.string, rt.null]), - updated_by: rt.union([UserRT, rt.null]), - owner: rt.string, - }), -]); - -export const SubCasesFindRequestRt = rt.partial({ - /** - * The status of the sub case (open, closed, in-progress) - */ - status: CaseStatusRt, - /** - * Operator to use for the `search` field - */ - defaultSearchOperator: rt.union([rt.literal('AND'), rt.literal('OR')]), - /** - * The fields in the entity to return in the response - */ - fields: rt.array(rt.string), - /** - * The page of objects to return - */ - page: NumberFromString, - /** - * The number of objects to include in each page - */ - perPage: NumberFromString, - /** - * An Elasticsearch simple_query_string - */ - search: rt.string, - /** - * The fields to perform the simple_query_string parsed query against - */ - searchFields: rt.array(rt.string), - /** - * The field to use for sorting the found objects. - */ - sortField: rt.string, - /** - * The order to sort by - */ - sortOrder: rt.union([rt.literal('desc'), rt.literal('asc')]), - owner: rt.string, -}); - -export const SubCaseResponseRt = rt.intersection([ - SubCaseAttributesRt, - rt.type({ - id: rt.string, - totalComment: rt.number, - totalAlerts: rt.number, - version: rt.string, - }), - rt.partial({ - comments: rt.array(CommentResponseRt), - }), -]); - -export const SubCasesFindResponseRt = rt.intersection([ - rt.type({ - subCases: rt.array(SubCaseResponseRt), - page: rt.number, - per_page: rt.number, - total: rt.number, - }), - CasesStatusResponseRt, -]); - -export const SubCasePatchRequestRt = rt.intersection([ - rt.partial(SubCaseBasicRt.props), - rt.type({ id: rt.string, version: rt.string }), -]); - -export const SubCasesPatchRequestRt = rt.type({ subCases: rt.array(SubCasePatchRequestRt) }); -export const SubCasesResponseRt = rt.array(SubCaseResponseRt); - -export type SubCaseAttributes = rt.TypeOf; -export type SubCaseResponse = rt.TypeOf; -export type SubCasesResponse = rt.TypeOf; -export type SubCasesFindResponse = rt.TypeOf; -export type SubCasePatchRequest = rt.TypeOf; -export type SubCasesPatchRequest = rt.TypeOf; -export type SubCasesFindRequest = rt.TypeOf; diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/common.ts b/x-pack/plugins/cases/common/api/cases/user_actions/common.ts index 8942d3c0ed926..a6d12d135c142 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/common.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/common.ts @@ -42,14 +42,11 @@ export const UserActionCommonAttributesRt = rt.type({ action: ActionsRt, }); -export const CaseUserActionSavedObjectIdsRt = rt.intersection([ - rt.type({ - action_id: rt.string, - case_id: rt.string, - comment_id: rt.union([rt.string, rt.null]), - }), - rt.partial({ sub_case_id: rt.string }), -]); +export const CaseUserActionSavedObjectIdsRt = rt.type({ + action_id: rt.string, + case_id: rt.string, + comment_id: rt.union([rt.string, rt.null]), +}); export type UserActionWithAttributes = T & rt.TypeOf; export type UserActionWithResponse = T & rt.TypeOf; diff --git a/x-pack/plugins/cases/common/api/helpers.ts b/x-pack/plugins/cases/common/api/helpers.ts index 2d5a7d1c33674..9aebb7d0ccd9d 100644 --- a/x-pack/plugins/cases/common/api/helpers.ts +++ b/x-pack/plugins/cases/common/api/helpers.ts @@ -11,10 +11,7 @@ import { CASE_COMMENTS_URL, CASE_USER_ACTIONS_URL, CASE_COMMENT_DETAILS_URL, - SUB_CASE_DETAILS_URL, - SUB_CASES_URL, CASE_PUSH_URL, - SUB_CASE_USER_ACTIONS_URL, CASE_CONFIGURE_DETAILS_URL, CASE_ALERTS_URL, } from '../constants'; @@ -27,14 +24,6 @@ export const getCaseDetailsMetricsUrl = (id: string): string => { return CASE_METRICS_DETAILS_URL.replace('{case_id}', id); }; -export const getSubCasesUrl = (caseID: string): string => { - return SUB_CASES_URL.replace('{case_id}', caseID); -}; - -export const getSubCaseDetailsUrl = (caseID: string, subCaseId: string): string => { - return SUB_CASE_DETAILS_URL.replace('{case_id}', caseID).replace('{sub_case_id}', subCaseId); -}; - export const getCaseCommentsUrl = (id: string): string => { return CASE_COMMENTS_URL.replace('{case_id}', id); }; @@ -47,10 +36,6 @@ export const getCaseUserActionUrl = (id: string): string => { return CASE_USER_ACTIONS_URL.replace('{case_id}', id); }; -export const getSubCaseUserActionUrl = (caseID: string, subCaseId: string): string => { - return SUB_CASE_USER_ACTIONS_URL.replace('{case_id}', caseID).replace('{sub_case_id}', subCaseId); -}; - export const getCasePushUrl = (caseId: string, connectorId: string): string => { return CASE_PUSH_URL.replace('{case_id}', caseId).replace('{connector_id}', connectorId); }; diff --git a/x-pack/plugins/cases/common/constants.ts b/x-pack/plugins/cases/common/constants.ts index 8e7d4934271ac..c57b40dbcf002 100644 --- a/x-pack/plugins/cases/common/constants.ts +++ b/x-pack/plugins/cases/common/constants.ts @@ -14,7 +14,6 @@ export const APP_ID = 'cases'; export const CASE_SAVED_OBJECT = 'cases'; export const CASE_CONNECTOR_MAPPINGS_SAVED_OBJECT = 'cases-connector-mappings'; -export const SUB_CASE_SAVED_OBJECT = 'cases-sub-case'; export const CASE_USER_ACTION_SAVED_OBJECT = 'cases-user-actions'; export const CASE_COMMENT_SAVED_OBJECT = 'cases-comments'; export const CASE_CONFIGURE_SAVED_OBJECT = 'cases-configure'; @@ -40,11 +39,6 @@ export const CASE_CONFIGURE_URL = `${CASES_URL}/configure`; export const CASE_CONFIGURE_DETAILS_URL = `${CASES_URL}/configure/{configuration_id}`; export const CASE_CONFIGURE_CONNECTORS_URL = `${CASE_CONFIGURE_URL}/connectors`; -export const SUB_CASES_PATCH_DEL_URL = `${CASES_URL}/sub_cases`; -export const SUB_CASES_URL = `${CASE_DETAILS_URL}/sub_cases`; -export const SUB_CASE_DETAILS_URL = `${CASE_DETAILS_URL}/sub_cases/{sub_case_id}`; -export const SUB_CASE_USER_ACTIONS_URL = `${SUB_CASE_DETAILS_URL}/user_actions`; - export const CASE_COMMENTS_URL = `${CASE_DETAILS_URL}/comments`; export const CASE_COMMENT_DETAILS_URL = `${CASE_DETAILS_URL}/comments/{comment_id}`; export const CASE_PUSH_URL = `${CASE_DETAILS_URL}/connector/{connector_id}/_push`; @@ -77,8 +71,7 @@ export const SUPPORTED_CONNECTORS = [ /** * Alerts */ -export const MAX_ALERTS_PER_SUB_CASE = 5000; -export const MAX_GENERATED_ALERTS_PER_SUB_CASE = 50; +export const MAX_ALERTS_PER_CASE = 5000; export const SECURITY_SOLUTION_OWNER = 'securitySolution'; export const OBSERVABILITY_OWNER = 'observability'; @@ -94,15 +87,6 @@ export const OWNER_INFO = { }, }; -/** - * This flag governs enabling the case as a connector feature. It is disabled by default as the feature is not complete. - */ -export const ENABLE_CASE_CONNECTOR = false; - -if (ENABLE_CASE_CONNECTOR) { - SAVED_OBJECT_TYPES.push(SUB_CASE_SAVED_OBJECT); -} - export const MAX_DOCS_PER_PAGE = 10000; export const MAX_CONCURRENT_SEARCHES = 10; diff --git a/x-pack/plugins/cases/common/index.ts b/x-pack/plugins/cases/common/index.ts index 31f0d9daed4f0..79a5aa4eb7ddd 100644 --- a/x-pack/plugins/cases/common/index.ts +++ b/x-pack/plugins/cases/common/index.ts @@ -15,11 +15,11 @@ // For example, constants below could eventually be in a "kbn-cases-constants" instead. // See: https://docs.elastic.dev/kibana-dev-docs/key-concepts/platform-intro#public-plugin-api -export { CASES_URL, SECURITY_SOLUTION_OWNER, ENABLE_CASE_CONNECTOR } from './constants'; +export { CASES_URL, SECURITY_SOLUTION_OWNER } from './constants'; export { CommentType, CaseStatuses, getCasesFromAlertsUrl, throwErrors } from './api'; -export type { SubCase, Case, Ecs, CasesFeatures, CaseViewRefreshPropInterface } from './ui/types'; +export type { Case, Ecs, CasesFeatures, CaseViewRefreshPropInterface } from './ui/types'; export { StatusAll } from './ui/types'; diff --git a/x-pack/plugins/cases/common/ui/types.ts b/x-pack/plugins/cases/common/ui/types.ts index cfa91a9c57cab..008d4b9245f63 100644 --- a/x-pack/plugins/cases/common/ui/types.ts +++ b/x-pack/plugins/cases/common/ui/types.ts @@ -6,12 +6,10 @@ */ import { - AssociationType, CaseAttributes, CaseConnector, CasePatchRequest, CaseStatuses, - CaseType, User, ActionConnector, CaseExternalServiceBasic, @@ -83,20 +81,12 @@ interface BasicCase { version: string; } -export interface SubCase extends BasicCase { - associationType: AssociationType; - caseParentId: string; -} - export interface Case extends BasicCase { connector: CaseConnector; description: string; externalService: CaseExternalService | null; - subCases?: SubCase[] | null; - subCaseIds: string[]; settings: CaseAttributes['settings']; tags: string[]; - type: CaseType; } export interface ResolvedCase { @@ -118,7 +108,6 @@ export interface FilterOptions { tags: string[]; reporters: User[]; owner: string[]; - onlyCollectionType?: boolean; } export interface CasesStatus { @@ -178,7 +167,6 @@ export interface ActionLicense { export interface DeleteCase { id: string; - type: CaseType | null; title: string; } @@ -195,7 +183,7 @@ export type UpdateKey = keyof Pick< export interface UpdateByKey { updateKey: UpdateKey; updateValue: CasePatchRequest[UpdateKey]; - fetchCaseUserActions?: (caseId: string, caseConnectorId: string, subCaseId?: string) => void; + fetchCaseUserActions?: (caseId: string, caseConnectorId: string) => void; updateCase?: (newCase: Case) => void; caseData: Case; onSuccess?: () => void; diff --git a/x-pack/plugins/cases/package.json b/x-pack/plugins/cases/package.json index bd9a547324ca6..a982c98768fd1 100644 --- a/x-pack/plugins/cases/package.json +++ b/x-pack/plugins/cases/package.json @@ -3,8 +3,5 @@ "name": "cases", "version": "8.0.0", "private": true, - "license": "Elastic-License", - "scripts": { - "test:sub-cases": "node server/scripts/sub_cases/generator" - } + "license": "Elastic-License" } diff --git a/x-pack/plugins/cases/public/common/navigation/paths.test.ts b/x-pack/plugins/cases/public/common/navigation/paths.test.ts index 23fb870fb6cda..a3fa042042a2d 100644 --- a/x-pack/plugins/cases/public/common/navigation/paths.test.ts +++ b/x-pack/plugins/cases/public/common/navigation/paths.test.ts @@ -7,11 +7,9 @@ import { getCreateCasePath, - getSubCaseViewPath, getCaseViewPath, getCasesConfigurePath, getCaseViewWithCommentPath, - getSubCaseViewWithCommentPath, generateCaseViewPath, } from './paths'; @@ -34,51 +32,21 @@ describe('Paths', () => { }); }); - describe('getSubCaseViewPath', () => { - it('returns the correct path', () => { - expect(getSubCaseViewPath('test')).toBe('test/:detailName/sub-cases/:subCaseId'); - }); - }); - describe('getCaseViewWithCommentPath', () => { it('returns the correct path', () => { expect(getCaseViewWithCommentPath('test')).toBe('test/:detailName/:commentId'); }); }); - describe('getSubCaseViewWithCommentPath', () => { - it('returns the correct path', () => { - expect(getSubCaseViewWithCommentPath('test')).toBe( - 'test/:detailName/sub-cases/:subCaseId/:commentId' - ); - }); - }); - describe('generateCaseViewPath', () => { it('returns the correct path', () => { expect(generateCaseViewPath({ detailName: 'my-case' })).toBe('/my-case'); }); - it('returns the correct path when subCaseId is provided', () => { - expect(generateCaseViewPath({ detailName: 'my-case', subCaseId: 'my-sub-case' })).toBe( - '/my-case/sub-cases/my-sub-case' - ); - }); - it('returns the correct path when commentId is provided', () => { expect(generateCaseViewPath({ detailName: 'my-case', commentId: 'my-comment' })).toBe( '/my-case/my-comment' ); }); - - it('returns the correct path when subCaseId and commentId is provided', () => { - expect( - generateCaseViewPath({ - detailName: 'my-case', - subCaseId: 'my-sub-case', - commentId: 'my-comment', - }) - ).toBe('/my-case/sub-cases/my-sub-case/my-comment'); - }); }); }); diff --git a/x-pack/plugins/cases/public/common/navigation/paths.ts b/x-pack/plugins/cases/public/common/navigation/paths.ts index 1cce1ca41ea77..1cd7a99630b85 100644 --- a/x-pack/plugins/cases/public/common/navigation/paths.ts +++ b/x-pack/plugins/cases/public/common/navigation/paths.ts @@ -10,38 +10,26 @@ import { generatePath } from 'react-router-dom'; export const DEFAULT_BASE_PATH = '/cases'; export interface CaseViewPathParams { detailName: string; - subCaseId?: string; commentId?: string; } export const CASES_CREATE_PATH = '/create' as const; export const CASES_CONFIGURE_PATH = '/configure' as const; export const CASE_VIEW_PATH = '/:detailName' as const; -export const SUB_CASE_VIEW_PATH = `${CASE_VIEW_PATH}/sub-cases/:subCaseId` as const; export const CASE_VIEW_COMMENT_PATH = `${CASE_VIEW_PATH}/:commentId` as const; -export const SUB_CASE_VIEW_COMMENT_PATH = `${SUB_CASE_VIEW_PATH}/:commentId` as const; export const getCreateCasePath = (casesBasePath: string) => `${casesBasePath}${CASES_CREATE_PATH}`; export const getCasesConfigurePath = (casesBasePath: string) => `${casesBasePath}${CASES_CONFIGURE_PATH}`; export const getCaseViewPath = (casesBasePath: string) => `${casesBasePath}${CASE_VIEW_PATH}`; -export const getSubCaseViewPath = (casesBasePath: string) => - `${casesBasePath}${SUB_CASE_VIEW_PATH}`; export const getCaseViewWithCommentPath = (casesBasePath: string) => `${casesBasePath}${CASE_VIEW_COMMENT_PATH}`; -export const getSubCaseViewWithCommentPath = (casesBasePath: string) => - `${casesBasePath}${SUB_CASE_VIEW_COMMENT_PATH}`; export const generateCaseViewPath = (params: CaseViewPathParams): string => { - const { subCaseId, commentId } = params; + const { commentId } = params; // Cast for generatePath argument type constraint const pathParams = params as unknown as { [paramName: string]: string }; - if (subCaseId && commentId) { - return generatePath(SUB_CASE_VIEW_COMMENT_PATH, pathParams); - } - if (subCaseId) { - return generatePath(SUB_CASE_VIEW_PATH, pathParams); - } + if (commentId) { return generatePath(CASE_VIEW_COMMENT_PATH, pathParams); } diff --git a/x-pack/plugins/cases/public/common/translations.ts b/x-pack/plugins/cases/public/common/translations.ts index 47e7c461c6ffd..04075ac680627 100644 --- a/x-pack/plugins/cases/public/common/translations.ts +++ b/x-pack/plugins/cases/public/common/translations.ts @@ -241,12 +241,6 @@ export const ALERT_ADDED_TO_CASE = i18n.translate('xpack.cases.common.alertAdded defaultMessage: 'added to case', }); -export const SELECTABLE_MESSAGE_COLLECTIONS = i18n.translate( - 'xpack.cases.common.allCases.table.selectableMessageCollections', - { - defaultMessage: 'Cases with sub-cases cannot be selected', - } -); export const SELECT_CASE_TITLE = i18n.translate('xpack.cases.common.allCases.caseModal.title', { defaultMessage: 'Select case', }); diff --git a/x-pack/plugins/cases/public/components/add_comment/index.test.tsx b/x-pack/plugins/cases/public/components/add_comment/index.test.tsx index f1167504628c4..f7535e6f52071 100644 --- a/x-pack/plugins/cases/public/components/add_comment/index.test.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/index.test.tsx @@ -75,7 +75,6 @@ describe('AddComment ', () => { expect(postComment).toBeCalledWith({ caseId: addCommentProps.caseId, data: sampleData, - subCaseId: undefined, updateCase: onCommentPosted, }); expect(wrapper.find(`[data-test-subj="add-comment"] textarea`).text()).toBe(''); diff --git a/x-pack/plugins/cases/public/components/add_comment/index.tsx b/x-pack/plugins/cases/public/components/add_comment/index.tsx index 83bd187e7863a..dea692f7c71a1 100644 --- a/x-pack/plugins/cases/public/components/add_comment/index.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/index.tsx @@ -52,7 +52,6 @@ export interface AddCommentProps { onCommentPosted: (newCase: Case) => void; showLoading?: boolean; statusActionButton: JSX.Element | null; - subCaseId?: string; } export const AddComment = React.memo( @@ -66,7 +65,6 @@ export const AddComment = React.memo( onCommentSaving, showLoading = true, statusActionButton, - subCaseId, }, ref ) => { @@ -118,11 +116,10 @@ export const AddComment = React.memo( caseId, data: { ...data, type: CommentType.user, owner: owner[0] }, updateCase: onCommentPosted, - subCaseId, }); reset(); } - }, [submit, onCommentSaving, postComment, caseId, owner, onCommentPosted, subCaseId, reset]); + }, [submit, onCommentSaving, postComment, caseId, owner, onCommentPosted, reset]); /** * Focus on the text area when a quote has been added. 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 5897a757b5bdf..4f400bb52601b 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 @@ -14,15 +14,10 @@ import userEvent from '@testing-library/user-event'; import '../../common/mock/match_media'; import { TestProviders } from '../../common/mock'; -import { - casesStatus, - useGetCasesMockState, - collectionCase, - connectorsMock, -} from '../../containers/mock'; +import { casesStatus, useGetCasesMockState, mockCase, connectorsMock } from '../../containers/mock'; import { StatusAll } from '../../../common/ui/types'; -import { CaseStatuses, CaseType } 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'; @@ -207,7 +202,6 @@ describe('AllCasesListGeneric', () => { createdAt: null, createdBy: null, status: null, - subCases: null, tags: null, title: null, totalComment: null, @@ -256,43 +250,6 @@ describe('AllCasesListGeneric', () => { }); }); - it.skip('should enable correct actions for sub cases', async () => { - useGetCasesMock.mockReturnValue({ - ...defaultGetCases, - data: { - ...defaultGetCases.data, - cases: [ - { - ...defaultGetCases.data.cases[0], - id: 'my-case-with-subcases', - createdAt: null, - createdBy: null, - status: null, - subCases: [ - { - id: 'sub-case-id', - }, - ], - tags: null, - title: null, - totalComment: null, - totalAlerts: null, - type: CaseType.collection, - }, - ], - }, - }); - const wrapper = mount( - - - - ); - - expect(wrapper.find('[data-test-subj="action-delete"]').first().props().disabled).toEqual( - false - ); - }); - it('should tableHeaderSortButton AllCasesList', async () => { const wrapper = mount( @@ -339,7 +296,7 @@ describe('AllCasesListGeneric', () => { useGetCasesMock.mockReturnValue({ ...defaultGetCases, filterOptions: { ...defaultGetCases.filterOptions, status: CaseStatuses.closed }, - selectedCases: [...useGetCasesMockState.data.cases, collectionCase], + selectedCases: [...useGetCasesMockState.data.cases, mockCase], }); useDeleteCasesMock @@ -372,11 +329,10 @@ describe('AllCasesListGeneric', () => { expect(handleToggleModal).toBeCalled(); expect(handleOnDeleteConfirm.mock.calls[0][0]).toStrictEqual([ - ...useGetCasesMockState.data.cases.map(({ id, type, title }) => ({ id, type, title })), + ...useGetCasesMockState.data.cases.map(({ id, title }) => ({ id, title })), { - id: collectionCase.id, - title: collectionCase.title, - type: collectionCase.type, + id: mockCase.id, + title: mockCase.title, }, ]); }); @@ -409,49 +365,6 @@ describe('AllCasesListGeneric', () => { }); }); - it('Renders correct bulk actions for case collection when filter status is set to all - enable only bulk delete if any collection is selected', async () => { - useGetCasesMock.mockReturnValue({ - ...defaultGetCases, - filterOptions: { ...defaultGetCases.filterOptions, status: CaseStatuses.open }, - selectedCases: [ - ...useGetCasesMockState.data.cases, - { - ...useGetCasesMockState.data.cases[0], - type: CaseType.collection, - }, - ], - }); - - useDeleteCasesMock - .mockReturnValueOnce({ - ...defaultDeleteCases, - isDisplayConfirmDeleteModal: false, - }) - .mockReturnValue({ - ...defaultDeleteCases, - isDisplayConfirmDeleteModal: true, - }); - - const wrapper = mount( - - - - ); - wrapper.find('[data-test-subj="case-table-bulk-actions"] button').first().simulate('click'); - await waitFor(() => { - expect(wrapper.find('[data-test-subj="cases-bulk-open-button"]').exists()).toEqual(false); - expect( - wrapper.find('[data-test-subj="cases-bulk-in-progress-button"]').first().props().disabled - ).toEqual(true); - expect( - wrapper.find('[data-test-subj="cases-bulk-close-button"]').first().props().disabled - ).toEqual(true); - expect( - wrapper.find('[data-test-subj="cases-bulk-delete-button"]').first().props().disabled - ).toEqual(false); - }); - }); - it('Bulk close status update', async () => { useGetCasesMock.mockReturnValue({ ...defaultGetCases, @@ -637,12 +550,10 @@ describe('AllCasesListGeneric', () => { id: '1', owner: SECURITY_SOLUTION_OWNER, status: 'open', - subCaseIds: [], tags: ['coke', 'pepsi'], title: 'Another horrible breach!!', totalAlerts: 0, totalComment: 0, - type: CaseType.individual, updatedAt: '2020-02-20T15:02:57.995Z', updatedBy: { email: 'leslie.knope@elastic.co', 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 bf88c5a7906bf..1ede1a2b736d3 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 @@ -9,23 +9,19 @@ import React, { useCallback, useMemo, useRef, useState } from 'react'; import { EuiProgress, EuiBasicTable, EuiTableSelectionType } from '@elastic/eui'; import { difference, head, isEmpty } from 'lodash/fp'; import styled, { css } from 'styled-components'; -import classnames from 'classnames'; import { Case, CaseStatusWithAllStatus, FilterOptions, SortFieldCase, - SubCase, } from '../../../common/ui/types'; -import { CaseStatuses, CaseType, CommentRequestAlertType, caseStatuses } from '../../../common/api'; -import { SELECTABLE_MESSAGE_COLLECTIONS } from '../../common/translations'; +import { CaseStatuses, CommentRequestAlertType, 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'; -import { getExpandedRowMap } from './expanded_row'; import { CasesTableFilters } from './table_filters'; import { EuiBasicTableOnChange } from './types'; @@ -53,7 +49,7 @@ export interface AllCasesListProps { alertData?: Omit; hiddenStatuses?: CaseStatusWithAllStatus[]; isSelectorView?: boolean; - onRowClick?: (theCase?: Case | SubCase) => void; + onRowClick?: (theCase?: Case) => void; updateCase?: (newCase: Case) => void; doRefresh?: () => void; } @@ -102,7 +98,7 @@ export const AllCasesList = React.memo( ); const filterRefetch = useRef<() => void>(); - const tableRef = useRef(); + const tableRef = useRef(null); const [isLoading, handleIsLoading] = useState(false); const setFilterRefetch = useCallback( @@ -190,16 +186,6 @@ export const AllCasesList = React.memo( showSolutionColumn: !hasOwner && availableSolutions.length > 1, }); - const itemIdToExpandedRowMap = useMemo( - () => - getExpandedRowMap({ - columns, - data: data.cases, - onSubCaseClick: onRowClick, - }), - [data.cases, columns, onRowClick] - ); - const pagination = useMemo( () => ({ pageIndex: queryParams.page - 1, @@ -213,7 +199,6 @@ export const AllCasesList = React.memo( const euiBasicTableSelectionProps = useMemo>( () => ({ onSelectionChange: setSelectedCases, - selectableMessage: (selectable) => (!selectable ? SELECTABLE_MESSAGE_COLLECTIONS : ''), initialSelected: selectedCases, }), [selectedCases, setSelectedCases] @@ -224,7 +209,6 @@ export const AllCasesList = React.memo( const tableRowProps = useCallback( (theCase: Case) => ({ 'data-test-subj': `cases-table-row-${theCase.id}`, - className: classnames({ isDisabled: theCase.type === CaseType.collection }), }), [] ); @@ -263,7 +247,6 @@ export const AllCasesList = React.memo( isCommentUpdating={isCommentUpdating} isDataEmpty={isDataEmpty} isSelectorView={isSelectorView} - itemIdToExpandedRowMap={itemIdToExpandedRowMap} onChange={tableOnChangeCallback} pagination={pagination} refreshCases={refreshCases} 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 d08f788c85311..9287d9db7e5b0 100644 --- a/x-pack/plugins/cases/public/components/all_cases/columns.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/columns.tsx @@ -22,10 +22,9 @@ import { import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services'; import styled from 'styled-components'; -import { Case, DeleteCase, SubCase } from '../../../common/ui/types'; +import { Case, DeleteCase } from '../../../common/ui/types'; import { CaseStatuses, - CaseType, CommentType, CommentRequestAlertType, ActionConnector, @@ -35,7 +34,6 @@ import { getEmptyTagValue } from '../empty_value'; import { FormattedRelativePreferenceDate } from '../formatted_date'; import { CaseDetailsLink } from '../links'; import * as i18n from './translations'; -import { getSubCasesStatusCountsBadges, isSubCase } from './helpers'; import { ALERTS } from '../../common/translations'; import { getActions } from './actions'; import { UpdateCase } from '../../containers/use_get_cases'; @@ -111,13 +109,12 @@ export const useCasesColumns = ({ const [deleteThisCase, setDeleteThisCase] = useState({ id: '', title: '', - type: null, }); const toggleDeleteModal = useCallback( (deleteCase: Case) => { handleToggleModal(); - setDeleteThisCase({ id: deleteCase.id, title: deleteCase.title, type: deleteCase.type }); + setDeleteThisCase({ id: deleteCase.id, title: deleteCase.title }); }, [handleToggleModal] ); @@ -175,16 +172,12 @@ export const useCasesColumns = ({ return [ { name: i18n.NAME, - render: (theCase: Case | SubCase) => { + render: (theCase: Case) => { if (theCase.id != null && theCase.title != null) { const caseDetailsLinkComponent = isSelectorView ? ( ) : ( - + ); @@ -350,32 +343,24 @@ export const useCasesColumns = ({ { name: i18n.STATUS, render: (theCase: Case) => { - if (theCase?.subCases == null || theCase.subCases.length === 0) { - if (theCase.status == null || theCase.type === CaseType.collection) { - return getEmptyTagValue(); - } - return ( - 0} - onStatusChanged={(status) => - handleDispatchUpdate({ - updateKey: 'status', - updateValue: status, - caseId: theCase.id, - version: theCase.version, - }) - } - /> - ); + if (theCase.status === null || theCase.status === undefined) { + return getEmptyTagValue(); } - const badges = getSubCasesStatusCountsBadges(theCase.subCases); - return badges.map(({ color, count }, index) => ( - - {count} - - )); + return ( + 0} + onStatusChanged={(status) => + handleDispatchUpdate({ + updateKey: 'status', + updateValue: status, + caseId: theCase.id, + version: theCase.version, + }) + } + /> + ); }, }, ] diff --git a/x-pack/plugins/cases/public/components/all_cases/expanded_row.tsx b/x-pack/plugins/cases/public/components/all_cases/expanded_row.tsx deleted file mode 100644 index 4719c2ce3db82..0000000000000 --- a/x-pack/plugins/cases/public/components/all_cases/expanded_row.tsx +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiBasicTable } from '@elastic/eui'; -import styled from 'styled-components'; -import { Case, SubCase } from '../../containers/types'; -import { CasesColumns } from './columns'; -import { AssociationType } from '../../../common/api'; - -type ExpandedRowMap = Record | {}; - -// @ts-expect-error TS2769 -const BasicTable = styled(EuiBasicTable)` - thead { - display: none; - } - - tbody { - .euiTableCellContent { - padding: 8px !important; - } - .euiTableRowCell { - border: 0; - } - } -`; -BasicTable.displayName = 'BasicTable'; - -export const getExpandedRowMap = ({ - data, - columns, - onSubCaseClick, -}: { - data: Case[] | null; - columns: CasesColumns[]; - onSubCaseClick?: (theSubCase: SubCase) => void; -}): ExpandedRowMap => { - if (data == null) { - return {}; - } - - const rowProps = (theSubCase: SubCase) => { - return { - ...(onSubCaseClick ? { onClick: () => onSubCaseClick(theSubCase) } : {}), - className: 'subCase', - }; - }; - - return data.reduce((acc, curr) => { - if (curr.subCases != null) { - const subCases = curr.subCases.map((subCase, index) => ({ - ...subCase, - caseParentId: curr.id, - title: `${curr.title} ${index + 1}`, - associationType: AssociationType.subCase, - })); - return { - ...acc, - [curr.id]: ( - - ), - }; - } else { - return acc; - } - }, {}); -}; diff --git a/x-pack/plugins/cases/public/components/all_cases/helpers.ts b/x-pack/plugins/cases/public/components/all_cases/helpers.ts deleted file mode 100644 index f84f19d3030ae..0000000000000 --- a/x-pack/plugins/cases/public/components/all_cases/helpers.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { filter } from 'lodash/fp'; -import { AssociationType, CaseStatuses, CaseType } from '../../../common/api'; -import { Case, SubCase } from '../../containers/types'; -import { statuses } from '../status'; - -export const isSelectedCasesIncludeCollections = (selectedCases: Case[]) => - selectedCases.length > 0 && - selectedCases.some((caseObj: Case) => caseObj.type === CaseType.collection); - -export const isSubCase = (theCase: Case | SubCase): theCase is SubCase => - (theCase as SubCase).caseParentId !== undefined && - (theCase as SubCase).associationType === AssociationType.subCase; - -export const isCollection = (theCase: Case | SubCase | null | undefined) => - theCase != null && (theCase as Case).type === CaseType.collection; - -export const isIndividual = (theCase: Case | SubCase | null | undefined) => - theCase != null && (theCase as Case).type === CaseType.individual; - -export const getSubCasesStatusCountsBadges = ( - subCases: SubCase[] -): Array<{ name: CaseStatuses; color: string; count: number }> => [ - { - color: statuses[CaseStatuses.open].color, - count: filter({ status: CaseStatuses.open }, subCases).length, - name: CaseStatuses.open, - }, - { - color: statuses[CaseStatuses['in-progress']].color, - count: filter({ status: CaseStatuses['in-progress'] }, subCases).length, - name: CaseStatuses['in-progress'], - }, - { - color: statuses[CaseStatuses.closed].color, - count: filter({ status: CaseStatuses.closed }, subCases).length, - name: CaseStatuses.closed, - }, -]; 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 5db6531d8e140..d63c56456b07e 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 @@ -15,14 +15,14 @@ import { EuiModalHeaderTitle, } from '@elastic/eui'; import styled from 'styled-components'; -import { Case, SubCase, CaseStatusWithAllStatus } from '../../../../common/ui/types'; +import { Case, CaseStatusWithAllStatus } from '../../../../common/ui/types'; import { CommentRequestAlertType } from '../../../../common/api'; import * as i18n from '../../../common/translations'; import { AllCasesList } from '../all_cases_list'; export interface AllCasesSelectorModalProps { alertData?: Omit; hiddenStatuses?: CaseStatusWithAllStatus[]; - onRowClick: (theCase?: Case | SubCase) => void; + onRowClick: (theCase?: Case) => void; updateCase?: (newCase: Case) => void; onClose?: () => void; } @@ -45,7 +45,7 @@ export const AllCasesSelectorModal = React.memo( }, [onClose]); const onClick = useCallback( - (theCase?: Case | SubCase) => { + (theCase?: Case) => { closeModal(); onRowClick(theCase); }, diff --git a/x-pack/plugins/cases/public/components/all_cases/table.tsx b/x-pack/plugins/cases/public/components/all_cases/table.tsx index 0d4a4cb6b38f1..2a2cf79e6f690 100644 --- a/x-pack/plugins/cases/public/components/all_cases/table.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/table.tsx @@ -12,6 +12,7 @@ import { EuiTableSelectionType, EuiBasicTable, EuiBasicTableProps, + Pagination, } from '@elastic/eui'; import classnames from 'classnames'; import styled from 'styled-components'; @@ -23,7 +24,7 @@ import * as i18n from './translations'; import { useCreateCaseNavigation } from '../../common/navigation'; interface CasesTableProps { - columns: EuiBasicTableProps['columns']; // CasesColumns[]; + columns: EuiBasicTableProps['columns']; data: AllCases; filterOptions: FilterOptions; goToCreateCase?: () => void; @@ -32,44 +33,18 @@ interface CasesTableProps { isCommentUpdating: boolean; isDataEmpty: boolean; isSelectorView?: boolean; - itemIdToExpandedRowMap: EuiBasicTableProps['itemIdToExpandedRowMap']; onChange: EuiBasicTableProps['onChange']; - pagination: EuiBasicTableProps['pagination']; + pagination: Pagination; refreshCases: (a?: boolean) => void; selectedCases: Case[]; selection: EuiTableSelectionType; showActions: boolean; sorting: EuiBasicTableProps['sorting']; - tableRef: MutableRefObject; + tableRef: MutableRefObject; tableRowProps: EuiBasicTableProps['rowProps']; userCanCrud: boolean; } -// @ts-expect-error TS2769 -const BasicTable = styled(EuiBasicTable)` - ${({ theme }) => ` - .euiTableRow-isExpandedRow.euiTableRow-isSelectable .euiTableCellContent { - padding: 8px 0 8px 32px; - } - - &.isSelectorView .euiTableRow.isDisabled { - cursor: not-allowed; - background-color: ${theme.eui.euiTableHoverClickableColor}; - } - - &.isSelectorView .euiTableRow.euiTableRow-isExpandedRow .euiTableRowCell, - &.isSelectorView .euiTableRow.euiTableRow-isExpandedRow:hover { - background-color: transparent; - } - - &.isSelectorView .euiTableRow.euiTableRow-isExpandedRow { - .subCase:hover { - background-color: ${theme.eui.euiTableHoverClickableColor}; - } - } - `} -`; - const Div = styled.div` margin-top: ${({ theme }) => theme.eui.paddingSizes.m}; `; @@ -84,7 +59,6 @@ export const CasesTable: FunctionComponent = ({ isCommentUpdating, isDataEmpty, isSelectorView, - itemIdToExpandedRowMap, onChange, pagination, refreshCases, @@ -123,14 +97,13 @@ export const CasesTable: FunctionComponent = ({ selectedCases={selectedCases} refreshCases={refreshCases} /> - = ({ (cases: Case[]) => { handleToggleModal(); - const convertToDeleteCases: DeleteCase[] = cases.map(({ id, title, type }) => ({ + const convertToDeleteCases: DeleteCase[] = cases.map(({ id, title }) => ({ id, title, - type, })); setDeleteCases(convertToDeleteCases); }, @@ -109,7 +107,6 @@ export const CasesTableUtilityBar: FunctionComponent = ({ deleteCasesAction: toggleBulkDeleteModal, selectedCases, updateCaseStatus: handleUpdateCaseStatus, - includeCollections: isSelectedCasesIncludeCollections(selectedCases), })} /> ), diff --git a/x-pack/plugins/cases/public/components/app/routes.test.tsx b/x-pack/plugins/cases/public/components/app/routes.test.tsx index 69410327af1ef..0eb27479bc8a8 100644 --- a/x-pack/plugins/cases/public/components/app/routes.test.tsx +++ b/x-pack/plugins/cases/public/components/app/routes.test.tsx @@ -29,12 +29,7 @@ jest.mock('../configure_cases', () => ({ ConfigureCases: () =>
{'Configure cases'}
, })); -const getCaseViewPaths = () => [ - '/cases/test-id', - '/cases/test-id/comment-id', - '/cases/test-id/sub-cases/sub-case-id', - '/cases/test-id/sub-cases/sub-case-id/comment-id', -]; +const getCaseViewPaths = () => ['/cases/test-id', '/cases/test-id/comment-id']; const renderWithRouter = ( initialEntries: MemoryRouterProps['initialEntries'] = ['/cases'], diff --git a/x-pack/plugins/cases/public/components/app/routes.tsx b/x-pack/plugins/cases/public/components/app/routes.tsx index ab4bf2ac51f19..6222c413a1167 100644 --- a/x-pack/plugins/cases/public/components/app/routes.tsx +++ b/x-pack/plugins/cases/public/components/app/routes.tsx @@ -18,8 +18,6 @@ import { getCreateCasePath, getCaseViewPath, getCaseViewWithCommentPath, - getSubCaseViewPath, - getSubCaseViewWithCommentPath, useAllCasesNavigation, useCaseViewNavigation, } from '../../common/navigation'; @@ -72,15 +70,7 @@ const CasesRoutesComponent: React.FC = ({ )} - + void; deleteCasesAction: (cases: Case[]) => void; - includeCollections: boolean; selectedCases: Case[]; updateCaseStatus: (status: string) => void; } @@ -27,7 +26,6 @@ export const getBulkItems = ({ caseStatus, closePopover, deleteCasesAction, - includeCollections, selectedCases, updateCaseStatus, }: GetBulkItems) => { @@ -36,7 +34,7 @@ export const getBulkItems = ({ const openMenuItem = ( { @@ -51,7 +49,7 @@ export const getBulkItems = ({ const inProgressMenuItem = ( { @@ -66,7 +64,7 @@ export const getBulkItems = ({ const closeMenuItem = ( { diff --git a/x-pack/plugins/cases/public/components/case_action_bar/actions.test.tsx b/x-pack/plugins/cases/public/components/case_action_bar/actions.test.tsx index ed8e238db75e7..308f6bc86f41a 100644 --- a/x-pack/plugins/cases/public/components/case_action_bar/actions.test.tsx +++ b/x-pack/plugins/cases/public/components/case_action_bar/actions.test.tsx @@ -81,7 +81,7 @@ describe('CaseView actions', () => { expect(wrapper.find('[data-test-subj="confirm-delete-case-modal"]').exists()).toBeTruthy(); wrapper.find('button[data-test-subj="confirmModalConfirmButton"]').simulate('click'); expect(handleOnDeleteConfirm.mock.calls[0][0]).toEqual([ - { id: basicCase.id, title: basicCase.title, type: 'individual' }, + { id: basicCase.id, title: basicCase.title }, ]); }); diff --git a/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx b/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx index a6db64b83bf09..3c78fa6f5fa4b 100644 --- a/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx +++ b/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx @@ -57,9 +57,7 @@ const ActionsComponent: React.FC = ({ caseData, currentExternal caseTitle={caseData.title} isModalVisible={isDisplayConfirmDeleteModal} onCancel={handleToggleModal} - onConfirm={handleOnDeleteConfirm.bind(null, [ - { id: caseData.id, title: caseData.title, type: caseData.type }, - ])} + onConfirm={handleOnDeleteConfirm.bind(null, [{ id: caseData.id, title: caseData.title }])} /> ); diff --git a/x-pack/plugins/cases/public/components/case_action_bar/index.tsx b/x-pack/plugins/cases/public/components/case_action_bar/index.tsx index 26c7ed2699133..31d8b91d9432c 100644 --- a/x-pack/plugins/cases/public/components/case_action_bar/index.tsx +++ b/x-pack/plugins/cases/public/components/case_action_bar/index.tsx @@ -17,7 +17,7 @@ import { EuiIconTip, } from '@elastic/eui'; import { Case } from '../../../common/ui/types'; -import { CaseStatuses, CaseType } from '../../../common/api'; +import { CaseStatuses } from '../../../common/api'; import * as i18n from '../case_view/translations'; import { Actions } from './actions'; import { CaseService } from '../../containers/use_get_case_user_actions'; @@ -83,18 +83,16 @@ const CaseActionBarComponent: React.FC = ({ - {caseData.type !== CaseType.collection && ( - - {i18n.STATUS} - - - - - )} + + {i18n.STATUS} + + + + {!metricsFeatures.includes('lifespan') ? ( {title} diff --git a/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx b/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx index d67796b98d99a..e5564ee9429aa 100644 --- a/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx @@ -26,7 +26,7 @@ import { useConnectors } from '../../containers/configure/use_connectors'; import { connectorsMock } from '../../containers/configure/mock'; import { usePostPushToService } from '../../containers/use_post_push_to_service'; import { useGetCaseMetrics } from '../../containers/use_get_case_metrics'; -import { CaseType, ConnectorTypes } from '../../../common/api'; +import { ConnectorTypes } from '../../../common/api'; import { caseViewProps, caseData } from './index.test'; jest.mock('../../containers/use_update_case'); @@ -576,68 +576,4 @@ describe('CaseViewPage', () => { }); }); }); - - describe('Collections', () => { - it('it does not allow the user to update the status', async () => { - const wrapper = mount( - - - - ); - - await waitFor(() => { - expect(wrapper.find('[data-test-subj="case-action-bar-wrapper"]').exists()).toBe(true); - expect(wrapper.find('button[data-test-subj="case-view-status"]').exists()).toBe(false); - expect(wrapper.find('[data-test-subj="user-actions"]').exists()).toBe(true); - expect( - wrapper.find('button[data-test-subj="case-view-status-action-button"]').exists() - ).toBe(false); - }); - }); - - it('it shows the push button when has data to push', async () => { - useGetCaseUserActionsMock.mockImplementation(() => ({ - ...defaultUseGetCaseUserActions, - hasDataToPush: true, - })); - - const wrapper = mount( - - - - ); - - await waitFor(() => { - expect(wrapper.find('[data-test-subj="has-data-to-push-button"]').exists()).toBe(true); - }); - }); - - it('it does not show the horizontal rule when does NOT has data to push', async () => { - useGetCaseUserActionsMock.mockImplementation(() => ({ - ...defaultUseGetCaseUserActions, - hasDataToPush: false, - })); - - const wrapper = mount( - - - - ); - - await waitFor(() => { - expect( - wrapper.find('[data-test-subj="case-view-bottom-actions-horizontal-rule"]').exists() - ).toBe(false); - }); - }); - }); }); diff --git a/x-pack/plugins/cases/public/components/case_view/case_view_page.tsx b/x-pack/plugins/cases/public/components/case_view/case_view_page.tsx index e58a10d22481f..c0dc4fa4d95e9 100644 --- a/x-pack/plugins/cases/public/components/case_view/case_view_page.tsx +++ b/x-pack/plugins/cases/public/components/case_view/case_view_page.tsx @@ -8,7 +8,7 @@ import React, { useCallback, useEffect, useMemo, useState, useRef } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiLoadingContent, EuiSpacer } from '@elastic/eui'; -import { CaseStatuses, CaseAttributes, CaseType, CaseConnector } from '../../../common/api'; +import { CaseStatuses, CaseAttributes, CaseConnector } from '../../../common/api'; import { Case, UpdateKey, UpdateByKey } from '../../../common/ui'; import { EditableTitle } from '../header_page/editable_title'; import { TagList } from '../tag_list'; @@ -38,19 +38,13 @@ import { useCasesFeatures } from '../cases_context/use_cases_features'; const useOnUpdateField = ({ caseData, caseId, - subCaseId, handleUpdateField, }: { caseData: Case; caseId: string; - subCaseId?: string; handleUpdateField: (newCase: Case, updateKey: UpdateKey) => void; }) => { - const { - isLoading, - updateKey: loadingKey, - updateCaseProperty, - } = useUpdateCase({ caseId, subCaseId }); + const { isLoading, updateKey: loadingKey, updateCaseProperty } = useUpdateCase({ caseId }); const onUpdateField = useCallback( ({ key, value, onSuccess, onError }: OnUpdateFields) => { @@ -117,7 +111,6 @@ export const CaseViewPage = React.memo( actionsNavigation, ruleDetailsNavigation, showAlertDetails, - subCaseId, updateCase, useFetchAlertData, refreshRef, @@ -138,11 +131,11 @@ export const CaseViewPage = React.memo( hasDataToPush, isLoading: isLoadingUserActions, participants, - } = useGetCaseUserActions(caseId, caseData.connector.id, subCaseId); + } = useGetCaseUserActions(caseId, caseData.connector.id); const refetchCaseUserActions = useCallback(() => { - fetchCaseUserActions(caseId, caseData.connector.id, subCaseId); - }, [caseId, fetchCaseUserActions, subCaseId, caseData]); + fetchCaseUserActions(caseId, caseData.connector.id); + }, [caseId, fetchCaseUserActions, caseData]); const { metrics, @@ -159,24 +152,23 @@ export const CaseViewPage = React.memo( const handleUpdateCase = useCallback( (newCase: Case) => { updateCase(newCase); - fetchCaseUserActions(caseId, newCase.connector.id, subCaseId); + fetchCaseUserActions(caseId, newCase.connector.id); fetchCaseMetrics(); }, - [updateCase, fetchCaseUserActions, caseId, subCaseId, fetchCaseMetrics] + [updateCase, fetchCaseUserActions, caseId, fetchCaseMetrics] ); const handleUpdateField = useCallback( (newCase: Case, updateKey: UpdateKey) => { updateCase({ ...newCase, comments: caseData.comments }); - fetchCaseUserActions(caseId, newCase.connector.id, subCaseId); + fetchCaseUserActions(caseId, newCase.connector.id); fetchCaseMetrics(); }, - [updateCase, caseData, fetchCaseUserActions, caseId, subCaseId, fetchCaseMetrics] + [updateCase, caseData, fetchCaseUserActions, caseId, fetchCaseMetrics] ); const { onUpdateField, isLoading, loadingKey } = useOnUpdateField({ caseId, - subCaseId, caseData, handleUpdateField, }); @@ -274,9 +266,9 @@ export const CaseViewPage = React.memo( const emailContent = useMemo( () => ({ subject: i18n.EMAIL_SUBJECT(caseData.title), - body: i18n.EMAIL_BODY(getCaseViewUrl({ detailName: caseId, subCaseId })), + body: i18n.EMAIL_BODY(getCaseViewUrl({ detailName: caseId })), }), - [caseData.title, getCaseViewUrl, caseId, subCaseId] + [caseData.title, getCaseViewUrl, caseId] ); useEffect(() => { @@ -368,7 +360,7 @@ export const CaseViewPage = React.memo( timelineUi?.renderInvestigateInTimelineActionComponent } statusActionButton={ - caseData.type !== CaseType.collection && userCanCrud ? ( + userCanCrud ? ( ( connectorName={connectorName} connectors={connectors} hasDataToPush={hasDataToPush && userCanCrud} - hideConnectorServiceNowSir={ - subCaseId != null || caseData.type === CaseType.collection - } isLoading={isLoadingConnectors || (isLoading && loadingKey === 'connector')} isValidConnector={isLoadingConnectors ? true : isValidConnector} onSubmit={onSubmitConnector} diff --git a/x-pack/plugins/cases/public/components/case_view/index.test.tsx b/x-pack/plugins/cases/public/components/case_view/index.test.tsx index aeffbd3240cab..4f112b09d0ea2 100644 --- a/x-pack/plugins/cases/public/components/case_view/index.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/index.test.tsx @@ -263,7 +263,7 @@ describe('CaseView', () => { ); wrapper.find('[data-test-subj="case-refresh"]').first().simulate('click'); await waitFor(() => { - expect(fetchCaseUserActions).toBeCalledWith(caseData.id, 'resilient-2', undefined); + expect(fetchCaseUserActions).toBeCalledWith(caseData.id, 'resilient-2'); expect(fetchCaseMetrics).toBeCalled(); expect(fetchCase).toBeCalled(); }); @@ -303,7 +303,7 @@ describe('CaseView', () => { it('should refresh actions and comments', async () => { refreshRef!.current!.refreshCase(); await waitFor(() => { - expect(fetchCaseUserActions).toBeCalledWith('basic-case-id', 'resilient-2', undefined); + expect(fetchCaseUserActions).toBeCalledWith('basic-case-id', 'resilient-2'); expect(fetchCaseMetrics).toBeCalledWith(true); expect(fetchCase).toBeCalledWith(true); }); diff --git a/x-pack/plugins/cases/public/components/case_view/index.tsx b/x-pack/plugins/cases/public/components/case_view/index.tsx index afb1666d0f370..25c578e8e3be2 100644 --- a/x-pack/plugins/cases/public/components/case_view/index.tsx +++ b/x-pack/plugins/cases/public/components/case_view/index.tsx @@ -42,10 +42,10 @@ export const CaseView = React.memo( refreshRef, }: CaseViewProps) => { const { spaces: spacesApi } = useKibana().services; - const { detailName: caseId, subCaseId } = useCaseViewParams(); + const { detailName: caseId } = useCaseViewParams(); const { basePath } = useCasesContext(); const { data, resolveOutcome, resolveAliasId, isLoading, isError, fetchCase, updateCase } = - useGetCase(caseId, subCaseId); + useGetCase(caseId); useEffect(() => { if (spacesApi && resolveOutcome === 'aliasMatch' && resolveAliasId != null) { @@ -91,7 +91,6 @@ export const CaseView = React.memo( actionsNavigation={actionsNavigation} ruleDetailsNavigation={ruleDetailsNavigation} showAlertDetails={showAlertDetails} - subCaseId={subCaseId} updateCase={updateCase} useFetchAlertData={useFetchAlertData} refreshRef={refreshRef} diff --git a/x-pack/plugins/cases/public/components/case_view/types.ts b/x-pack/plugins/cases/public/components/case_view/types.ts index 525bbcd225cb2..69d05918e182f 100644 --- a/x-pack/plugins/cases/public/components/case_view/types.ts +++ b/x-pack/plugins/cases/public/components/case_view/types.ts @@ -29,7 +29,6 @@ export interface CaseViewProps extends CaseViewBaseProps { export interface CaseViewPageProps extends CaseViewBaseProps { caseId: string; - subCaseId?: string; fetchCase: UseGetCase['fetchCase']; caseData: Case; updateCase: (newCase: Case) => void; diff --git a/x-pack/plugins/cases/public/components/configure_cases/closure_options.tsx b/x-pack/plugins/cases/public/components/configure_cases/closure_options.tsx index 2bcb137d348ad..1681f2cf94497 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/closure_options.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/closure_options.tsx @@ -29,7 +29,6 @@ const ClosureOptionsComponent: React.FC = ({ description={ <>

{i18n.CASE_CLOSURE_OPTIONS_DESC}

-

{i18n.CASE_CLOSURE_OPTIONS_SUB_CASES}

} data-test-subj="case-closure-options-form-group" diff --git a/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.test.tsx b/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.test.tsx index 03ed3d6512638..127c6c30febfb 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.test.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.test.tsx @@ -245,27 +245,6 @@ describe('ConnectorsDropdown', () => { ).toBeTruthy(); }); - test('if the props hideConnectorServiceNowSir is true, the connector should not be part of the list of options ', () => { - const newWrapper = mount( - , - { - wrappingComponent: TestProviders, - } - ); - const selectProps = newWrapper.find(EuiSuperSelect).props(); - const options = selectProps.options as Array<{ 'data-test-subj': string }>; - expect( - options.some((o) => o['data-test-subj'] === 'dropdown-connector-servicenow-1') - ).toBeTruthy(); - expect( - options.some((o) => o['data-test-subj'] === 'dropdown-connector-servicenow-sir') - ).toBeFalsy(); - }); - test('it does not throw when accessing the icon if the connector type is not registered', () => { expect(() => mount( diff --git a/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.tsx b/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.tsx index 9082fc572324e..cf8d86eb1700a 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.tsx @@ -9,7 +9,6 @@ import React, { useMemo } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiIconTip, EuiSuperSelect } from '@elastic/eui'; import styled from 'styled-components'; -import { ConnectorTypes } from '../../../common/api'; import { ActionConnector } from '../../containers/configure/types'; import * as i18n from './translations'; import { useKibana } from '../../common/lib/kibana'; @@ -23,7 +22,6 @@ export interface Props { onChange: (id: string) => void; selectedConnector: string; appendAddConnectorButton?: boolean; - hideConnectorServiceNowSir?: boolean; } const ICON_SIZE = 'm'; @@ -70,16 +68,11 @@ const ConnectorsDropdownComponent: React.FC = ({ onChange, selectedConnector, appendAddConnectorButton = false, - hideConnectorServiceNowSir = false, }) => { const { triggersActionsUi } = useKibana().services; const connectorsAsOptions = useMemo(() => { const connectorsFormatted = connectors.reduce( (acc, connector) => { - if (hideConnectorServiceNowSir && connector.actionTypeId === ConnectorTypes.serviceNowSIR) { - return acc; - } - return [ ...acc, { diff --git a/x-pack/plugins/cases/public/components/configure_cases/translations.ts b/x-pack/plugins/cases/public/components/configure_cases/translations.ts index 8b682064a0274..ba457905590ab 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/translations.ts +++ b/x-pack/plugins/cases/public/components/configure_cases/translations.ts @@ -50,13 +50,6 @@ export const CASE_CLOSURE_OPTIONS_DESC = i18n.translate( } ); -export const CASE_CLOSURE_OPTIONS_SUB_CASES = i18n.translate( - 'xpack.cases.configureCases.caseClosureOptionsSubCases', - { - defaultMessage: 'Automatic closure of sub-cases is not supported.', - } -); - export const CASE_CLOSURE_OPTIONS_LABEL = i18n.translate( 'xpack.cases.configureCases.caseClosureOptionsLabel', { diff --git a/x-pack/plugins/cases/public/components/connector_selector/form.tsx b/x-pack/plugins/cases/public/components/connector_selector/form.tsx index 83733ea7e97dd..c863d4862f31a 100644 --- a/x-pack/plugins/cases/public/components/connector_selector/form.tsx +++ b/x-pack/plugins/cases/public/components/connector_selector/form.tsx @@ -23,7 +23,6 @@ interface ConnectorSelectorProps { isEdit: boolean; isLoading: boolean; handleChange?: (newValue: string) => void; - hideConnectorServiceNowSir?: boolean; } const EuiFormRowWrapper = styled(EuiFormRow)` @@ -41,7 +40,6 @@ export const ConnectorSelector = ({ isEdit = true, isLoading = false, handleChange, - hideConnectorServiceNowSir = false, }: ConnectorSelectorProps) => { const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field); const onChange = useCallback( @@ -68,7 +66,6 @@ export const ConnectorSelector = ({ ` - padding: ${theme.eui?.euiSizeS ?? '8px'} ${theme.eui?.euiSizeL ?? '24px'} ${ - theme.eui?.euiSizeL ?? '24px' - } ${theme.eui?.euiSizeL ?? '24px'}; - `} -`; - -const defaultAlertComment = { - type: CommentType.generatedAlert, - alerts: `[{{#context.alerts}}{"_id": "{{_id}}", "_index": "{{_index}}", "ruleId": "{{signal.rule.id}}", "ruleName": "{{signal.rule.name}}"}__SEPARATOR__{{/context.alerts}}]`, -}; - -const CaseParamsFields: React.FunctionComponent> = ({ - actionParams, - editAction, - index, - actionConnector, -}) => { - const { caseId = null, comment = defaultAlertComment } = actionParams.subActionParams ?? {}; - - const [selectedCase, setSelectedCase] = useState(null); - - const editSubActionProperty = useCallback( - (key: string, value: unknown) => { - const newProps = { ...actionParams.subActionParams, [key]: value }; - editAction('subActionParams', newProps, index); - }, - // edit action causes re-renders - // eslint-disable-next-line react-hooks/exhaustive-deps - [actionParams.subActionParams, index] - ); - - const onCaseChanged = useCallback( - (id: string) => { - setSelectedCase(id); - editSubActionProperty('caseId', id); - }, - [editSubActionProperty] - ); - - useEffect(() => { - if (!actionParams.subAction) { - editAction('subAction', 'addComment', index); - } - - if (!actionParams.subActionParams?.caseId) { - editSubActionProperty('caseId', caseId); - } - - if (!actionParams.subActionParams?.comment) { - editSubActionProperty('comment', comment); - } - - if (caseId != null) { - setSelectedCase((prevCaseId) => (prevCaseId !== caseId ? caseId : prevCaseId)); - } - - // editAction creates an infinity loop. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ - actionConnector, - index, - actionParams.subActionParams?.caseId, - actionParams.subActionParams?.comment, - caseId, - comment, - actionParams.subAction, - ]); - - /** - * TODO: When the case connector is enabled we need to figure out - * how we can pass the owner to this component - */ - return ( - - - - -

{i18n.CASE_CONNECTOR_CALL_OUT_MSG}

-
-
- ); -}; -CaseParamsFields.displayName = 'CaseParamsFields'; - -// eslint-disable-next-line import/no-default-export -export { CaseParamsFields as default }; diff --git a/x-pack/plugins/cases/public/components/connectors/case/cases_dropdown.tsx b/x-pack/plugins/cases/public/components/connectors/case/cases_dropdown.tsx deleted file mode 100644 index c26fa04df6843..0000000000000 --- a/x-pack/plugins/cases/public/components/connectors/case/cases_dropdown.tsx +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { EuiFormRow, EuiSuperSelect, EuiSuperSelectOption } from '@elastic/eui'; -import React, { memo, useMemo, useCallback } from 'react'; -import { Case } from '../../../containers/types'; - -import * as i18n from './translations'; - -interface CaseDropdownProps { - isLoading: boolean; - cases: Case[]; - selectedCase?: string; - onCaseChanged: (id: string) => void; -} - -export const ADD_CASE_BUTTON_ID = 'add-case'; - -const addNewCase = { - value: ADD_CASE_BUTTON_ID, - inputDisplay: ( - - {i18n.CASE_CONNECTOR_ADD_NEW_CASE} - - ), - 'data-test-subj': 'dropdown-connector-add-connector', -}; - -const CasesDropdownComponent: React.FC = ({ - isLoading, - cases, - selectedCase, - onCaseChanged, -}) => { - const caseOptions: Array> = useMemo( - () => - cases.reduce>>( - (acc, theCase) => [ - ...acc, - { - value: theCase.id, - inputDisplay: {theCase.title}, - 'data-test-subj': `case-connector-cases-dropdown-${theCase.id}`, - }, - ], - [] - ), - [cases] - ); - - const options = useMemo(() => [...caseOptions, addNewCase], [caseOptions]); - const onChange = useCallback((id: string) => onCaseChanged(id), [onCaseChanged]); - - return ( - - - - ); -}; -CasesDropdownComponent.displayName = 'CasesDropdown'; - -export const CasesDropdown = memo(CasesDropdownComponent); diff --git a/x-pack/plugins/cases/public/components/connectors/case/existing_case.tsx b/x-pack/plugins/cases/public/components/connectors/case/existing_case.tsx deleted file mode 100644 index 7472bc6b6047e..0000000000000 --- a/x-pack/plugins/cases/public/components/connectors/case/existing_case.tsx +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { memo, useMemo, useCallback } from 'react'; -import { - useGetCases, - DEFAULT_QUERY_PARAMS, - DEFAULT_FILTER_OPTIONS, -} from '../../../containers/use_get_cases'; -import { useCreateCaseModal } from '../../use_create_case_modal'; -import { CasesDropdown, ADD_CASE_BUTTON_ID } from './cases_dropdown'; - -interface ExistingCaseProps { - selectedCase: string | null; - onCaseChanged: (id: string) => void; -} - -const ExistingCaseComponent: React.FC = ({ onCaseChanged, selectedCase }) => { - const { - data: cases, - loading: isLoadingCases, - refetchCases, - } = useGetCases({ - initialQueryParams: DEFAULT_QUERY_PARAMS, - initialFilterOptions: { - ...DEFAULT_FILTER_OPTIONS, - onlyCollectionType: true, - }, - }); - - const onCaseCreated = useCallback( - (newCase) => { - refetchCases(); - onCaseChanged(newCase.id); - }, - [onCaseChanged, refetchCases] - ); - - const { modal, openModal } = useCreateCaseModal({ - onCaseCreated, - // FUTURE DEVELOPER - // We are making the assumption that this component is only used in rules creation - // that's why we want to hide ServiceNow SIR - hideConnectorServiceNowSir: true, - }); - - const onChange = useCallback( - (id: string) => { - if (id === ADD_CASE_BUTTON_ID) { - openModal(); - return; - } - - onCaseChanged(id); - }, - [onCaseChanged, openModal] - ); - - const isCasesLoading = useMemo( - () => isLoadingCases.includes('cases') || isLoadingCases.includes('caseUpdate'), - [isLoadingCases] - ); - - return ( - <> - - {modal} - - ); -}; -ExistingCaseComponent.displayName = 'ExistingCase'; - -export const ExistingCase = memo(ExistingCaseComponent); diff --git a/x-pack/plugins/cases/public/components/connectors/case/index.ts b/x-pack/plugins/cases/public/components/connectors/case/index.ts deleted file mode 100644 index 8e6680cd65387..0000000000000 --- a/x-pack/plugins/cases/public/components/connectors/case/index.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { lazy } from 'react'; - -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { ActionTypeModel } from '../../../../../triggers_actions_ui/public/types'; -import { CaseActionParams } from './types'; -import * as i18n from './translations'; - -interface ValidationResult { - errors: { - caseId: string[]; - }; -} - -const validateParams = (actionParams: CaseActionParams) => { - const validationResult: ValidationResult = { errors: { caseId: [] } }; - - if (actionParams.subActionParams && !actionParams.subActionParams.caseId) { - validationResult.errors.caseId.push(i18n.CASE_CONNECTOR_CASE_REQUIRED); - } - - return Promise.resolve(validationResult); -}; - -export function getActionType(): ActionTypeModel { - return { - id: '.case', - iconClass: 'securityAnalyticsApp', - selectMessage: i18n.CASE_CONNECTOR_DESC, - actionTypeTitle: i18n.CASE_CONNECTOR_TITLE, - validateConnector: () => Promise.resolve({ config: { errors: {} }, secrets: { errors: {} } }), - validateParams, - actionConnectorFields: null, - actionParamsFields: lazy(() => import('./alert_fields')), - }; -} diff --git a/x-pack/plugins/cases/public/components/connectors/case/translations.ts b/x-pack/plugins/cases/public/components/connectors/case/translations.ts deleted file mode 100644 index 0d4e1d2f0bd63..0000000000000 --- a/x-pack/plugins/cases/public/components/connectors/case/translations.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export * from '../../../common/translations'; - -export const CASE_CONNECTOR_DESC = i18n.translate( - 'xpack.cases.components.connectors.cases.selectMessageText', - { - defaultMessage: 'Create or update a case.', - } -); - -export const CASE_CONNECTOR_TITLE = i18n.translate( - 'xpack.cases.components.connectors.cases.actionTypeTitle', - { - defaultMessage: 'Cases', - } -); -export const CASE_CONNECTOR_CASES_DROPDOWN_ROW_LABEL = i18n.translate( - 'xpack.cases.components.connectors.cases.casesDropdownRowLabel', - { - defaultMessage: 'Case allowing sub-cases', - } -); - -export const CASE_CONNECTOR_CASES_OPTION_EXISTING_CASE = i18n.translate( - 'xpack.cases.components.connectors.cases.optionAddToExistingCase', - { - defaultMessage: 'Add to existing case', - } -); - -export const CASE_CONNECTOR_CASE_REQUIRED = i18n.translate( - 'xpack.cases.components.connectors.cases.caseRequired', - { - defaultMessage: 'You must select a case.', - } -); - -export const CASE_CONNECTOR_CALL_OUT_TITLE = i18n.translate( - 'xpack.cases.components.connectors.cases.callOutTitle', - { - defaultMessage: 'Generated alerts will be attached to sub-cases', - } -); - -export const CASE_CONNECTOR_CALL_OUT_MSG = i18n.translate( - 'xpack.cases.components.connectors.cases.callOutMsg', - { - defaultMessage: - 'A case can contain multiple sub-cases to allow grouping of generated alerts. Sub-cases will give more granular control over the status of these generated alerts and prevents having too many alerts attached to one case.', - } -); - -export const CASE_CONNECTOR_ADD_NEW_CASE = i18n.translate( - 'xpack.cases.components.connectors.cases.addNewCaseOption', - { - defaultMessage: 'Add new case', - } -); - -export const CREATE_CASE = i18n.translate( - 'xpack.cases.components.connectors.cases.createCaseLabel', - { - defaultMessage: 'Create case', - } -); diff --git a/x-pack/plugins/cases/public/components/connectors/index.ts b/x-pack/plugins/cases/public/components/connectors/index.ts index 0d5e33a818d3a..03d18976c40fd 100644 --- a/x-pack/plugins/cases/public/components/connectors/index.ts +++ b/x-pack/plugins/cases/public/components/connectors/index.ts @@ -19,8 +19,6 @@ import { SwimlaneFieldsType, } from '../../../common/api'; -export { getActionType as getCaseConnectorUi } from './case'; - export * from './types'; interface GetCaseConnectorsReturn { diff --git a/x-pack/plugins/cases/public/components/create/connector.tsx b/x-pack/plugins/cases/public/components/create/connector.tsx index 47cc3ea91a868..3b479927ee069 100644 --- a/x-pack/plugins/cases/public/components/create/connector.tsx +++ b/x-pack/plugins/cases/public/components/create/connector.tsx @@ -8,7 +8,7 @@ import React, { memo, useCallback, useMemo, useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { ConnectorTypes, ActionConnector } from '../../../common/api'; +import { ActionConnector } from '../../../common/api'; import { UseField, useFormData, @@ -26,7 +26,6 @@ interface Props { connectors: ActionConnector[]; isLoading: boolean; isLoadingConnectors: boolean; - hideConnectorServiceNowSir?: boolean; } interface ConnectorsFieldProps { @@ -34,27 +33,13 @@ interface ConnectorsFieldProps { field: FieldHook; isEdit: boolean; setErrors: (errors: boolean) => void; - hideConnectorServiceNowSir?: boolean; } -const ConnectorFields = ({ - connectors, - isEdit, - field, - setErrors, - hideConnectorServiceNowSir = false, -}: ConnectorsFieldProps) => { +const ConnectorFields = ({ connectors, isEdit, field, setErrors }: ConnectorsFieldProps) => { const [{ connectorId }] = useFormData({ watch: ['connectorId'] }); const { setValue } = field; - let connector = getConnectorById(connectorId, connectors) ?? null; + const connector = getConnectorById(connectorId, connectors) ?? null; - if ( - connector && - hideConnectorServiceNowSir && - connector.actionTypeId === ConnectorTypes.serviceNowSIR - ) { - connector = null; - } return ( = ({ - connectors, - hideConnectorServiceNowSir = false, - isLoading, - isLoadingConnectors, -}) => { +const ConnectorComponent: React.FC = ({ connectors, isLoading, isLoadingConnectors }) => { const { getFields, setFieldValue } = useFormContext(); const { connector: configurationConnector } = useCaseConfigure(); @@ -81,21 +61,10 @@ const ConnectorComponent: React.FC = ({ }, [getFields]); const defaultConnectorId = useMemo(() => { - if ( - hideConnectorServiceNowSir && - configurationConnector.type === ConnectorTypes.serviceNowSIR - ) { - return 'none'; - } return connectors.some((connector) => connector.id === configurationConnector.id) ? configurationConnector.id : 'none'; - }, [ - configurationConnector.id, - configurationConnector.type, - connectors, - hideConnectorServiceNowSir, - ]); + }, [configurationConnector.id, connectors]); useEffect( () => setFieldValue('connectorId', defaultConnectorId), @@ -118,7 +87,6 @@ const ConnectorComponent: React.FC = ({ componentProps={{ connectors, handleChange: handleConnectorChange, - hideConnectorServiceNowSir, dataTestSubj: 'caseConnectors', disabled: isLoading || isLoadingConnectors, idAria: 'caseConnectors', @@ -132,7 +100,6 @@ const ConnectorComponent: React.FC = ({ component={ConnectorFields} componentProps={{ connectors, - hideConnectorServiceNowSir, isEdit: true, }} /> diff --git a/x-pack/plugins/cases/public/components/create/form.tsx b/x-pack/plugins/cases/public/components/create/form.tsx index a1784397a21a8..506bfdd974b47 100644 --- a/x-pack/plugins/cases/public/components/create/form.tsx +++ b/x-pack/plugins/cases/public/components/create/form.tsx @@ -23,7 +23,7 @@ import { Tags } from './tags'; import { Connector } from './connector'; import * as i18n from './translations'; import { SyncAlertsToggle } from './sync_alerts_toggle'; -import { ActionConnector, CaseType } from '../../../common/api'; +import { ActionConnector } from '../../../common/api'; import { Case } from '../../containers/types'; import { CasesTimelineIntegration, CasesTimelineIntegrationProvider } from '../timeline_context'; import { InsertTimeline } from '../insert_timeline'; @@ -55,21 +55,18 @@ const MySpinner = styled(EuiLoadingSpinner)` export interface CreateCaseFormFieldsProps { connectors: ActionConnector[]; isLoadingConnectors: boolean; - hideConnectorServiceNowSir: boolean; withSteps: boolean; } -export interface CreateCaseFormProps - extends Pick, 'hideConnectorServiceNowSir' | 'withSteps'> { +export interface CreateCaseFormProps extends Pick, 'withSteps'> { onCancel: () => void; onSuccess: (theCase: Case) => Promise; afterCaseCreated?: (theCase: Case, postComment: UsePostComment['postComment']) => Promise; - caseType?: CaseType; timelineIntegration?: CasesTimelineIntegration; } const empty: ActionConnector[] = []; export const CreateCaseFormFields: React.FC = React.memo( - ({ connectors, isLoadingConnectors, hideConnectorServiceNowSir, withSteps }) => { + ({ connectors, isLoadingConnectors, withSteps }) => { const { isSubmitting } = useFormContext(); const { isSyncAlertsEnabled } = useCasesFeatures(); @@ -122,14 +119,13 @@ export const CreateCaseFormFields: React.FC = React.m ), }), - [connectors, hideConnectorServiceNowSir, isLoadingConnectors, isSubmitting] + [connectors, isLoadingConnectors, isSubmitting] ); const allSteps = useMemo( @@ -161,21 +157,12 @@ export const CreateCaseFormFields: React.FC = React.m CreateCaseFormFields.displayName = 'CreateCaseFormFields'; export const CreateCaseForm: React.FC = React.memo( - ({ - hideConnectorServiceNowSir = false, - withSteps = true, - afterCaseCreated, - caseType, - onCancel, - onSuccess, - timelineIntegration, - }) => ( + ({ withSteps = true, afterCaseCreated, onCancel, onSuccess, timelineIntegration }) => ( - + diff --git a/x-pack/plugins/cases/public/components/create/form_context.test.tsx b/x-pack/plugins/cases/public/components/create/form_context.test.tsx index 6e406386b48ef..a07aa55d1a57f 100644 --- a/x-pack/plugins/cases/public/components/create/form_context.test.tsx +++ b/x-pack/plugins/cases/public/components/create/form_context.test.tsx @@ -81,7 +81,6 @@ const defaultCreateCaseForm: CreateCaseFormFieldsProps = { isLoadingConnectors: false, connectors: [], withSteps: true, - hideConnectorServiceNowSir: false, }; const defaultPostPushToService = { diff --git a/x-pack/plugins/cases/public/components/create/form_context.tsx b/x-pack/plugins/cases/public/components/create/form_context.tsx index 34700c37db71e..dca67cac7e688 100644 --- a/x-pack/plugins/cases/public/components/create/form_context.tsx +++ b/x-pack/plugins/cases/public/components/create/form_context.tsx @@ -14,7 +14,7 @@ import { usePostPushToService } from '../../containers/use_post_push_to_service' import { useConnectors } from '../../containers/configure/use_connectors'; import { Case } from '../../containers/types'; -import { CaseType, NONE_CONNECTOR_ID } from '../../../common/api'; +import { NONE_CONNECTOR_ID } from '../../../common/api'; import { UsePostComment, usePostComment } from '../../containers/use_post_comment'; import { useCasesContext } from '../cases_context/use_cases_context'; import { useCasesFeatures } from '../cases_context/use_cases_features'; @@ -32,17 +32,11 @@ const initialCaseValue: FormProps = { interface Props { afterCaseCreated?: (theCase: Case, postComment: UsePostComment['postComment']) => Promise; - caseType?: CaseType; children?: JSX.Element | JSX.Element[]; onSuccess?: (theCase: Case) => Promise; } -export const FormContext: React.FC = ({ - afterCaseCreated, - caseType = CaseType.individual, - children, - onSuccess, -}) => { +export const FormContext: React.FC = ({ afterCaseCreated, children, onSuccess }) => { const { connectors, loading: isLoadingConnectors } = useConnectors(); const { owner } = useCasesContext(); const { isSyncAlertsEnabled } = useCasesFeatures(); @@ -70,7 +64,6 @@ export const FormContext: React.FC = ({ const updatedCase = await postCase({ ...userFormData, - type: caseType, connector: connectorToUpdate, settings: { syncAlerts }, owner: selectedOwner ?? owner[0], @@ -96,7 +89,6 @@ export const FormContext: React.FC = ({ isSyncAlertsEnabled, connectors, postCase, - caseType, owner, afterCaseCreated, onSuccess, diff --git a/x-pack/plugins/cases/public/components/create/index.tsx b/x-pack/plugins/cases/public/components/create/index.tsx index aea7c08829128..eb35f78b87f5f 100644 --- a/x-pack/plugins/cases/public/components/create/index.tsx +++ b/x-pack/plugins/cases/public/components/create/index.tsx @@ -17,15 +17,7 @@ import { CasesDeepLinkId } from '../../common/navigation'; export const CommonUseField = getUseField({ component: Field }); export const CreateCase = React.memo( - ({ - afterCaseCreated, - caseType, - hideConnectorServiceNowSir, - onCancel, - onSuccess, - timelineIntegration, - withSteps, - }) => { + ({ afterCaseCreated, onCancel, onSuccess, timelineIntegration, withSteps }) => { useCasesBreadcrumbs(CasesDeepLinkId.casesCreate); return ( @@ -37,8 +29,6 @@ export const CreateCase = React.memo( /> { }); test('it calls navigateToCaseViewClick on click', () => { - render(); + render(); userEvent.click(screen.getByText('test detail name')); expect(navigateToCaseView).toHaveBeenCalledWith({ detailName: props.detailName, - subCaseId: 'sub-case-id', }); }); test('it set the href correctly', () => { - render(); + render(); expect(getCaseViewUrl).toHaveBeenCalledWith({ detailName: props.detailName, - subCaseId: 'sub-case-id', }); expect(screen.getByRole('link')).toHaveAttribute('href', '/cases/test'); }); diff --git a/x-pack/plugins/cases/public/components/links/index.tsx b/x-pack/plugins/cases/public/components/links/index.tsx index d7c2c18eff9ab..db8a4df2a88ca 100644 --- a/x-pack/plugins/cases/public/components/links/index.tsx +++ b/x-pack/plugins/cases/public/components/links/index.tsx @@ -39,7 +39,6 @@ export const LinkAnchor: React.FC = ({ children, ...props }) => ( export interface CaseDetailsLinkProps { children?: React.ReactNode; detailName: string; - subCaseId?: string; title?: string; } @@ -48,22 +47,21 @@ export interface CaseDetailsLinkProps { const CaseDetailsLinkComponent: React.FC = ({ children, detailName, - subCaseId, title, }) => { const { getCaseViewUrl, navigateToCaseView } = useCaseViewNavigation(); const navigateToCaseViewClick = useCallback( (ev) => { ev.preventDefault(); - navigateToCaseView({ detailName, subCaseId }); + navigateToCaseView({ detailName }); }, - [navigateToCaseView, detailName, subCaseId] + [navigateToCaseView, detailName] ); return ( diff --git a/x-pack/plugins/cases/public/components/recent_cases/index.test.tsx b/x-pack/plugins/cases/public/components/recent_cases/index.test.tsx index 0a1e0447511db..4f99f23b9b208 100644 --- a/x-pack/plugins/cases/public/components/recent_cases/index.test.tsx +++ b/x-pack/plugins/cases/public/components/recent_cases/index.test.tsx @@ -62,7 +62,7 @@ describe('RecentCases', () => {
); - expect(getAllByTestId('case-details-link')).toHaveLength(5); + expect(getAllByTestId('case-details-link')).toHaveLength(7); }); it('is good at rendering max cases', () => { diff --git a/x-pack/plugins/cases/public/components/recent_cases/recent_cases.tsx b/x-pack/plugins/cases/public/components/recent_cases/recent_cases.tsx index 0f9111e5acd1d..231bf666d625e 100644 --- a/x-pack/plugins/cases/public/components/recent_cases/recent_cases.tsx +++ b/x-pack/plugins/cases/public/components/recent_cases/recent_cases.tsx @@ -16,7 +16,6 @@ import { useGetCases } from '../../containers/use_get_cases'; import { CaseDetailsLink } from '../links'; import { LoadingPlaceholders } from './loading_placeholders'; import { NoCases } from './no_cases'; -import { isSubCase } from '../all_cases/helpers'; import { MarkdownRenderer } from '../markdown_editor'; import { FilterOptions } from '../../containers/types'; import { TruncatedText } from '../truncated_text'; @@ -67,11 +66,7 @@ export const RecentCasesComp = ({ filterOptions, maxCasesToShow }: RecentCasesPr - + diff --git a/x-pack/plugins/cases/public/components/use_create_case_modal/create_case_modal.tsx b/x-pack/plugins/cases/public/components/use_create_case_modal/create_case_modal.tsx index 6c844a660b801..f7450b2dd31ef 100644 --- a/x-pack/plugins/cases/public/components/use_create_case_modal/create_case_modal.tsx +++ b/x-pack/plugins/cases/public/components/use_create_case_modal/create_case_modal.tsx @@ -13,14 +13,12 @@ import * as i18n from '../../common/translations'; import { CreateCase } from '../create'; export interface CreateCaseModalProps { - hideConnectorServiceNowSir?: boolean; isModalOpen: boolean; onCloseCaseModal: () => void; onSuccess: (theCase: Case) => Promise; } const CreateModalComponent: React.FC = ({ - hideConnectorServiceNowSir, isModalOpen, onCloseCaseModal, onSuccess, @@ -31,12 +29,7 @@ const CreateModalComponent: React.FC = ({ {i18n.CREATE_CASE_TITLE} - + ) : null; diff --git a/x-pack/plugins/cases/public/components/use_create_case_modal/index.tsx b/x-pack/plugins/cases/public/components/use_create_case_modal/index.tsx index afae43b462a5b..1654bfe86a620 100644 --- a/x-pack/plugins/cases/public/components/use_create_case_modal/index.tsx +++ b/x-pack/plugins/cases/public/components/use_create_case_modal/index.tsx @@ -11,7 +11,6 @@ import { CreateCaseModal } from './create_case_modal'; export interface UseCreateCaseModalProps { onCaseCreated: (theCase: Case) => void; - hideConnectorServiceNowSir?: boolean; } export interface UseCreateCaseModalReturnedValues { modal: JSX.Element; @@ -20,10 +19,7 @@ export interface UseCreateCaseModalReturnedValues { openModal: () => void; } -export const useCreateCaseModal = ({ - onCaseCreated, - hideConnectorServiceNowSir = false, -}: UseCreateCaseModalProps) => { +export const useCreateCaseModal = ({ onCaseCreated }: UseCreateCaseModalProps) => { const [isModalOpen, setIsModalOpen] = useState(false); const closeModal = useCallback(() => setIsModalOpen(false), []); const openModal = useCallback(() => setIsModalOpen(true), []); @@ -39,7 +35,6 @@ export const useCreateCaseModal = ({ () => ({ modal: ( { const { getCaseViewUrl } = useCaseViewNavigation(); - const { detailName, subCaseId } = useCaseViewParams(); + const { detailName } = useCaseViewParams(); const handleAnchorLink = useCallback(() => { - copy(getCaseViewUrl({ detailName, subCaseId, commentId }, true)); - }, [detailName, subCaseId, commentId, getCaseViewUrl]); + copy(getCaseViewUrl({ detailName, commentId }, true)); + }, [detailName, commentId, getCaseViewUrl]); return ( {i18n.COPY_REFERENCE_LINK}

}> diff --git a/x-pack/plugins/cases/public/components/user_actions/helpers.test.ts b/x-pack/plugins/cases/public/components/user_actions/helpers.test.ts index dd75ed8c6fcd8..80b68450f9edd 100644 --- a/x-pack/plugins/cases/public/components/user_actions/helpers.test.ts +++ b/x-pack/plugins/cases/public/components/user_actions/helpers.test.ts @@ -5,14 +5,13 @@ * 2.0. */ -import { AssociationType, CommentType } from '../../../common/api'; +import { CommentType } from '../../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; import { Comment } from '../../containers/types'; import { isUserActionTypeSupported, getManualAlertIdsWithNoRuleId } from './helpers'; const comments: Comment[] = [ { - associationType: AssociationType.case, type: CommentType.alert, alertId: 'alert-id-1', index: 'alert-index-1', @@ -31,7 +30,6 @@ const comments: Comment[] = [ owner: SECURITY_SOLUTION_OWNER, }, { - associationType: AssociationType.case, type: CommentType.alert, alertId: 'alert-id-2', index: 'alert-index-2', diff --git a/x-pack/plugins/cases/public/components/user_actions/index.test.tsx b/x-pack/plugins/cases/public/components/user_actions/index.test.tsx index 67e9b4505ae62..2426e74f3e7b6 100644 --- a/x-pack/plugins/cases/public/components/user_actions/index.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/index.test.tsx @@ -73,9 +73,7 @@ describe(`UserActions`, () => { patchComment, }); - jest - .spyOn(routeData, 'useParams') - .mockReturnValue({ detailName: 'case-id', subCaseId: 'sub-case-id' }); + jest.spyOn(routeData, 'useParams').mockReturnValue({ detailName: 'case-id' }); }); it('Loading spinner when user actions loading and displays fullName/username', () => { @@ -285,7 +283,6 @@ describe(`UserActions`, () => { expect(patchComment).toBeCalledWith({ commentUpdate: sampleData.content, caseId: 'case-id', - subCaseId: 'sub-case-id', commentId: props.data.comments[0].id, fetchUserActions, updateCase, diff --git a/x-pack/plugins/cases/public/components/user_actions/index.tsx b/x-pack/plugins/cases/public/components/user_actions/index.tsx index 084d1c548f903..33394017a4698 100644 --- a/x-pack/plugins/cases/public/components/user_actions/index.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/index.tsx @@ -89,13 +89,12 @@ export const UserActions = React.memo( onRuleDetailsClick, onShowAlertDetails, onUpdateField, - renderInvestigateInTimelineActionComponent, statusActionButton, updateCase, useFetchAlertData, userCanCrud, }: UserActionTreeProps) => { - const { detailName: caseId, subCaseId, commentId } = useCaseViewParams(); + const { detailName: caseId, commentId } = useCaseViewParams(); const [initLoading, setInitLoading] = useState(true); const currentUser = useCurrentUser(); @@ -126,7 +125,6 @@ export const UserActions = React.memo( onCommentSaving={handleManageMarkdownEditId.bind(null, NEW_COMMENT_ID)} showLoading={false} statusActionButton={statusActionButton} - subCaseId={subCaseId} /> ), [ @@ -135,7 +133,6 @@ export const UserActions = React.memo( handleUpdate, handleManageMarkdownEditId, statusActionButton, - subCaseId, commentRefs, ] ); diff --git a/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.test.tsx b/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.test.tsx index 574109b438167..a90cac5b15d56 100644 --- a/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.test.tsx @@ -85,7 +85,6 @@ describe('useUserActionsHandler', () => { commentId: 'test-id', commentUpdate: 'a comment', fetchUserActions, - subCaseId: undefined, updateCase, version: 'test-version', }); diff --git a/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.tsx b/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.tsx index b9943a8960392..61f5329908c04 100644 --- a/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.tsx @@ -43,7 +43,7 @@ export const useUserActionsHandler = ({ fetchUserActions, updateCase, }: UseUserActionsHandlerArgs): UseUserActionsHandler => { - const { detailName: caseId, subCaseId } = useCaseViewParams(); + const { detailName: caseId } = useCaseViewParams(); const { clearDraftComment, draftComment, hasIncomingLensState, openLensModal } = useLensDraftComment(); const handlerTimeoutId = useRef(0); @@ -75,10 +75,9 @@ export const useUserActionsHandler = ({ fetchUserActions, version, updateCase, - subCaseId, }); }, - [caseId, fetchUserActions, patchComment, subCaseId, updateCase] + [caseId, fetchUserActions, patchComment, updateCase] ); const handleOutlineComment = useCallback( diff --git a/x-pack/plugins/cases/public/containers/api.test.tsx b/x-pack/plugins/cases/public/containers/api.test.tsx index c83f5601da64b..e656544084d09 100644 --- a/x-pack/plugins/cases/public/containers/api.test.tsx +++ b/x-pack/plugins/cases/public/containers/api.test.tsx @@ -229,6 +229,7 @@ describe('Case Configuration API', () => { }); test('should return correct response', async () => { + fetchMock.mockResolvedValue(allCasesSnake); const resp = await getCases({ filterOptions: { ...DEFAULT_FILTER_OPTIONS, owner: [SECURITY_SOLUTION_OWNER] }, queryParams: DEFAULT_QUERY_PARAMS, diff --git a/x-pack/plugins/cases/public/containers/api.ts b/x-pack/plugins/cases/public/containers/api.ts index 6ca920fd5a8fe..9d250e2ae6e0c 100644 --- a/x-pack/plugins/cases/public/containers/api.ts +++ b/x-pack/plugins/cases/public/containers/api.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { assign, omit } from 'lodash'; +import { omit } from 'lodash'; import { StatusAll, ResolvedCase } from '../../common/ui/types'; import { @@ -16,7 +16,6 @@ import { CasesFindResponse, CasesResponse, CasesStatusResponse, - CaseType, CaseUserActionsResponse, CommentRequest, CommentType, @@ -25,11 +24,6 @@ import { getCaseDetailsMetricsUrl, getCasePushUrl, getCaseUserActionUrl, - getSubCaseDetailsUrl, - getSubCaseUserActionUrl, - SubCasePatchRequest, - SubCaseResponse, - SubCasesResponse, User, CaseMetricsResponse, } from '../../common/api'; @@ -38,8 +32,6 @@ import { CASE_STATUS_URL, CASE_TAGS_URL, CASES_URL, - SUB_CASE_DETAILS_URL, - SUB_CASES_PATCH_DEL_URL, } from '../../common/constants'; import { getAllConnectorTypesUrl } from '../../common/utils/connectors_api'; @@ -104,34 +96,6 @@ export const resolveCase = async ( return convertToCamelCase(decodeCaseResolveResponse(response)); }; -export const getSubCase = async ( - caseId: string, - subCaseId: string, - includeComments: boolean = true, - signal: AbortSignal -): Promise => { - const [caseResponse, subCaseResponse] = await Promise.all([ - KibanaServices.get().http.fetch(getCaseDetailsUrl(caseId), { - method: 'GET', - query: { - includeComments: false, - }, - signal, - }), - KibanaServices.get().http.fetch(getSubCaseDetailsUrl(caseId, subCaseId), { - method: 'GET', - query: { - includeComments, - }, - signal, - }), - ]); - const response = assign(caseResponse, subCaseResponse); - const subCaseIndex = response.subCaseIds?.findIndex((scId) => scId === response.id) ?? -1; - response.title = `${response.title}${subCaseIndex >= 0 ? ` ${subCaseIndex + 1}` : ''}`; - return convertToCamelCase(decodeCaseResponse(response)); -}; - export const getCasesStatus = async ( signal: AbortSignal, owner: string[] @@ -192,24 +156,8 @@ export const getCaseUserActions = async ( return convertArrayToCamelCase(decodeCaseUserActionsResponse(response)) as CaseUserActions[]; }; -export const getSubCaseUserActions = async ( - caseId: string, - subCaseId: string, - signal: AbortSignal -): Promise => { - const response = await KibanaServices.get().http.fetch( - getSubCaseUserActionUrl(caseId, subCaseId), - { - method: 'GET', - signal, - } - ); - return convertArrayToCamelCase(decodeCaseUserActionsResponse(response)) as CaseUserActions[]; -}; - export const getCases = async ({ filterOptions = { - onlyCollectionType: false, search: '', reporters: [], status: StatusAll, @@ -229,7 +177,6 @@ export const getCases = async ({ tags: filterOptions.tags, status: filterOptions.status, ...(filterOptions.search.length > 0 ? { search: filterOptions.search } : {}), - ...(filterOptions.onlyCollectionType ? { type: CaseType.collection } : {}), ...(filterOptions.owner.length > 0 ? { owner: filterOptions.owner } : {}), ...queryParams, }; @@ -267,35 +214,6 @@ export const patchCase = async ( return convertToCamelCase(decodeCasesResponse(response)); }; -export const patchSubCase = async ( - caseId: string, - subCaseId: string, - updatedSubCase: Pick, - version: string, - signal: AbortSignal -): Promise => { - const subCaseResponse = await KibanaServices.get().http.fetch( - SUB_CASE_DETAILS_URL, - { - method: 'PATCH', - body: JSON.stringify({ cases: [{ ...updatedSubCase, id: caseId, version }] }), - signal, - } - ); - const caseResponse = await KibanaServices.get().http.fetch( - getCaseDetailsUrl(caseId), - { - method: 'GET', - query: { - includeComments: false, - }, - signal, - } - ); - const response = subCaseResponse.map((subCaseResp) => assign(caseResponse, subCaseResp)); - return convertToCamelCase(decodeCasesResponse(response)); -}; - export const patchCasesStatus = async ( cases: BulkUpdateStatus[], signal: AbortSignal @@ -311,15 +229,13 @@ export const patchCasesStatus = async ( export const postComment = async ( newComment: CommentRequest, caseId: string, - signal: AbortSignal, - subCaseId?: string + signal: AbortSignal ): Promise => { const response = await KibanaServices.get().http.fetch( `${CASES_URL}/${caseId}/comments`, { method: 'POST', body: JSON.stringify(newComment), - ...(subCaseId ? { query: { subCaseId } } : {}), signal, } ); @@ -333,7 +249,6 @@ export const patchComment = async ({ version, signal, owner, - subCaseId, }: { caseId: string; commentId: string; @@ -341,7 +256,6 @@ export const patchComment = async ({ version: string; signal: AbortSignal; owner: string; - subCaseId?: string; }): Promise => { const response = await KibanaServices.get().http.fetch(getCaseCommentsUrl(caseId), { method: 'PATCH', @@ -352,7 +266,6 @@ export const patchComment = async ({ version, owner, }), - ...(subCaseId ? { query: { subCaseId } } : {}), signal, }); return convertToCamelCase(decodeCaseResponse(response)); @@ -367,15 +280,6 @@ export const deleteCases = async (caseIds: string[], signal: AbortSignal): Promi return response; }; -export const deleteSubCases = async (caseIds: string[], signal: AbortSignal): Promise => { - const response = await KibanaServices.get().http.fetch(SUB_CASES_PATCH_DEL_URL, { - method: 'DELETE', - query: { ids: JSON.stringify(caseIds) }, - signal, - }); - return response; -}; - export const pushCase = async ( caseId: string, connectorId: string, diff --git a/x-pack/plugins/cases/public/containers/mock.ts b/x-pack/plugins/cases/public/containers/mock.ts index d5e749c46a900..0d2aff225dfa6 100644 --- a/x-pack/plugins/cases/public/containers/mock.ts +++ b/x-pack/plugins/cases/public/containers/mock.ts @@ -11,14 +11,12 @@ import type { ResolvedCase, CaseMetrics, CaseMetricsFeature } from '../../common import { Actions, ActionTypes, - AssociationType, CaseConnector, CaseResponse, CasesFindResponse, CasesResponse, CasesStatusResponse, CaseStatuses, - CaseType, CaseUserActionResponse, CaseUserActionsResponse, CommentResponse, @@ -36,7 +34,8 @@ import { covertToSnakeCase } from './utils'; export { connectorsMock } from './configure/mock'; export const basicCaseId = 'basic-case-id'; -export const basicSubCaseId = 'basic-sub-case-id'; +export const caseWithAlertsId = 'case-with-alerts-id'; +export const caseWithAlertsSyncOffId = 'case-with-alerts-syncoff-id'; const basicCommentId = 'basic-comment-id'; const basicCreatedAt = '2020-02-19T23:06:33.798Z'; const basicUpdatedAt = '2020-02-20T15:02:57.995Z'; @@ -52,7 +51,6 @@ export const elasticUser = { export const tags: string[] = ['coke', 'pepsi']; export const basicComment: Comment = { - associationType: AssociationType.case, comment: 'Solve this fast!', type: CommentType.user, id: basicCommentId, @@ -68,7 +66,6 @@ export const basicComment: Comment = { export const alertComment: Comment = { alertId: 'alert-id-1', - associationType: AssociationType.case, index: 'alert-index-1', type: CommentType.alert, id: 'alert-comment-id', @@ -100,7 +97,6 @@ export const hostIsolationComment: () => Comment = () => { ], type: 'isolate', }, - associationType: AssociationType.case, createdAt: basicCreatedAt, createdBy: elasticUser, owner: SECURITY_SOLUTION_OWNER, @@ -126,7 +122,6 @@ export const hostReleaseComment: () => Comment = () => { ], type: 'unisolate', }, - associationType: AssociationType.case, createdAt: basicCreatedAt, createdBy: elasticUser, owner: SECURITY_SOLUTION_OWNER, @@ -139,7 +134,6 @@ export const hostReleaseComment: () => Comment = () => { }; export const basicCase: Case = { - type: CaseType.individual, owner: SECURITY_SOLUTION_OWNER, closedAt: null, closedBy: null, @@ -166,7 +160,20 @@ export const basicCase: Case = { settings: { syncAlerts: true, }, - subCaseIds: [], +}; + +export const caseWithAlerts = { + ...basicCase, + totalAlerts: 2, + id: caseWithAlertsId, +}; +export const caseWithAlertsSyncOff = { + ...basicCase, + totalAlerts: 2, + settings: { + syncAlerts: false, + }, + id: caseWithAlertsSyncOffId, }; export const basicResolvedCase: ResolvedCase = { @@ -218,12 +225,11 @@ export const basicCaseMetrics: CaseMetrics = { }, }; -export const collectionCase: Case = { - type: CaseType.collection, +export const mockCase: Case = { owner: SECURITY_SOLUTION_OWNER, closedAt: null, closedBy: null, - id: 'collection-id', + id: 'mock-id', comments: [basicComment], createdAt: basicCreatedAt, createdBy: elasticUser, @@ -237,7 +243,7 @@ export const collectionCase: Case = { externalService: null, status: CaseStatuses.open, tags, - title: 'Another horrible breach in a collection!!', + title: 'Another horrible breach!!', totalComment: 1, totalAlerts: 0, updatedAt: basicUpdatedAt, @@ -246,8 +252,6 @@ export const collectionCase: Case = { settings: { syncAlerts: true, }, - subCases: [], - subCaseIds: [], }; export const basicCasePost: Case = { @@ -314,6 +318,8 @@ export const cases: Case[] = [ { ...pushedCase, updatedAt: laterTime, id: '2', totalComment: 0, comments: [] }, { ...basicCase, id: '3', totalComment: 0, comments: [] }, { ...basicCase, id: '4', totalComment: 0, comments: [] }, + caseWithAlerts, + caseWithAlertsSyncOff, ]; export const allCases: AllCases = { @@ -349,7 +355,6 @@ export const elasticUserSnake = { }; export const basicCommentSnake: CommentResponse = { - associationType: AssociationType.case, comment: 'Solve this fast!', type: CommentType.user, id: basicCommentId, @@ -378,6 +383,20 @@ export const basicCaseSnake: CaseResponse = { owner: SECURITY_SOLUTION_OWNER, } as CaseResponse; +export const caseWithAlertsSnake = { + ...basicCaseSnake, + totalAlerts: 2, + id: caseWithAlertsId, +}; +export const caseWithAlertsSyncOffSnake = { + ...basicCaseSnake, + totalAlerts: 2, + settings: { + syncAlerts: false, + }, + id: caseWithAlertsSyncOffId, +}; + export const casesStatusSnake: CasesStatusResponse = { count_closed_cases: 130, count_in_progress_cases: 40, @@ -423,6 +442,8 @@ export const casesSnake: CasesResponse = [ { ...pushedCaseSnake, updated_at: laterTime, id: '2', totalComment: 0, comments: [] }, { ...basicCaseSnake, id: '3', totalComment: 0, comments: [] }, { ...basicCaseSnake, id: '4', totalComment: 0, comments: [] }, + caseWithAlertsSnake, + caseWithAlertsSyncOffSnake, ]; export const allCasesSnake: CasesFindResponse = { diff --git a/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx b/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx index 307dc0941e398..88f6db42144f6 100644 --- a/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx @@ -7,7 +7,6 @@ import { renderHook, act } from '@testing-library/react-hooks'; -import { CaseType } from '../../common/api'; import { useDeleteCases, UseDeleteCase } from './use_delete_cases'; import * as api from './api'; @@ -17,9 +16,9 @@ jest.mock('../common/lib/kibana'); describe('useDeleteCases', () => { const abortCtrl = new AbortController(); const deleteObj = [ - { id: '1', type: CaseType.individual, title: 'case 1' }, - { id: '2', type: CaseType.individual, title: 'case 2' }, - { id: '3', type: CaseType.individual, title: 'case 3' }, + { id: '1', title: 'case 1' }, + { id: '2', title: 'case 2' }, + { id: '3', title: 'case 3' }, ]; const deleteArr = ['1', '2', '3']; it('init', async () => { diff --git a/x-pack/plugins/cases/public/containers/use_delete_cases.tsx b/x-pack/plugins/cases/public/containers/use_delete_cases.tsx index 153be6126f967..7ccec4436ec0b 100644 --- a/x-pack/plugins/cases/public/containers/use_delete_cases.tsx +++ b/x-pack/plugins/cases/public/containers/use_delete_cases.tsx @@ -7,7 +7,7 @@ import { useCallback, useReducer, useRef, useEffect } from 'react'; import * as i18n from './translations'; -import { deleteCases, deleteSubCases } from './api'; +import { deleteCases } from './api'; import { DeleteCase } from './types'; import { useToasts } from '../common/lib/kibana'; @@ -85,11 +85,8 @@ export const useDeleteCases = (): UseDeleteCase => { dispatch({ type: 'FETCH_INIT' }); const caseIds = cases.map((theCase) => theCase.id); - // We don't allow user batch delete sub cases on UI at the moment. - if (cases[0].type != null || cases.length > 1) { + if (cases.length > 0) { await deleteCases(caseIds, abortCtrlRef.current.signal); - } else { - await deleteSubCases(caseIds, abortCtrlRef.current.signal); } if (!isCancelledRef.current) { diff --git a/x-pack/plugins/cases/public/containers/use_get_case.tsx b/x-pack/plugins/cases/public/containers/use_get_case.tsx index 52610981a227c..c7d2a79a53256 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case.tsx @@ -10,7 +10,7 @@ import { useEffect, useReducer, useCallback, useRef } from 'react'; import { Case, ResolvedCase } from './types'; import * as i18n from './translations'; import { useToasts } from '../common/lib/kibana'; -import { resolveCase, getSubCase } from './api'; +import { resolveCase } from './api'; interface CaseState { data: Case | null; @@ -71,7 +71,7 @@ export interface UseGetCase extends CaseState { updateCase: (newCase: Case) => void; } -export const useGetCase = (caseId: string, subCaseId?: string): UseGetCase => { +export const useGetCase = (caseId: string): UseGetCase => { const [state, dispatch] = useReducer(dataFetchReducer, { isLoading: false, isError: false, @@ -94,12 +94,7 @@ export const useGetCase = (caseId: string, subCaseId?: string): UseGetCase => { abortCtrlRef.current = new AbortController(); dispatch({ type: 'FETCH_INIT', payload: { silent } }); - const response: ResolvedCase = subCaseId - ? { - case: await getSubCase(caseId, subCaseId, true, abortCtrlRef.current.signal), - outcome: 'exactMatch', // sub-cases are not resolved, forced to exactMatch always - } - : await resolveCase(caseId, true, abortCtrlRef.current.signal); + const response: ResolvedCase = await resolveCase(caseId, true, abortCtrlRef.current.signal); if (!isCancelledRef.current) { dispatch({ type: 'FETCH_SUCCESS', payload: response }); @@ -116,7 +111,7 @@ export const useGetCase = (caseId: string, subCaseId?: string): UseGetCase => { } } }, - [caseId, subCaseId, toasts] + [caseId, toasts] ); useEffect(() => { @@ -127,6 +122,6 @@ export const useGetCase = (caseId: string, subCaseId?: string): UseGetCase => { abortCtrlRef.current.abort(); }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [caseId, subCaseId]); + }, [caseId]); return { ...state, fetchCase: callFetch, updateCase }; }; diff --git a/x-pack/plugins/cases/public/containers/use_get_case_user_actions.tsx b/x-pack/plugins/cases/public/containers/use_get_case_user_actions.tsx index fc73a898aa8e7..e5f3006ee924f 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_user_actions.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_user_actions.tsx @@ -11,7 +11,7 @@ import deepEqual from 'fast-deep-equal'; import { ElasticUser, CaseUserActions, CaseExternalService } from '../../common/ui/types'; import { ActionTypes, CaseConnector, NONE_CONNECTOR_ID } from '../../common/api'; -import { getCaseUserActions, getSubCaseUserActions } from './api'; +import { getCaseUserActions } from './api'; import * as i18n from './translations'; import { useToasts } from '../common/lib/kibana'; import { @@ -50,11 +50,7 @@ export const initialData: CaseUserActionsState = { }; export interface UseGetCaseUserActions extends CaseUserActionsState { - fetchCaseUserActions: ( - caseId: string, - caseConnectorId: string, - subCaseId?: string - ) => Promise; + fetchCaseUserActions: (caseId: string, caseConnectorId: string) => Promise; } const groupConnectorFields = ( @@ -234,8 +230,7 @@ export const getPushedInfo = ( export const useGetCaseUserActions = ( caseId: string, - caseConnectorId: string, - subCaseId?: string + caseConnectorId: string ): UseGetCaseUserActions => { const [caseUserActionsState, setCaseUserActionsState] = useState(initialData); @@ -244,7 +239,7 @@ export const useGetCaseUserActions = ( const toasts = useToasts(); const fetchCaseUserActions = useCallback( - async (thisCaseId: string, thisCaseConnectorId: string, thisSubCaseId?: string) => { + async (thisCaseId: string, thisCaseConnectorId: string) => { try { isCancelledRef.current = false; abortCtrlRef.current.abort(); @@ -254,9 +249,7 @@ export const useGetCaseUserActions = ( isLoading: true, }); - const response = await (thisSubCaseId - ? getSubCaseUserActions(thisCaseId, thisSubCaseId, abortCtrlRef.current.signal) - : getCaseUserActions(thisCaseId, abortCtrlRef.current.signal)); + const response = await getCaseUserActions(thisCaseId, abortCtrlRef.current.signal); if (!isCancelledRef.current) { // Attention Future developer @@ -302,7 +295,7 @@ export const useGetCaseUserActions = ( useEffect(() => { if (!isEmpty(caseId)) { - fetchCaseUserActions(caseId, caseConnectorId, subCaseId); + fetchCaseUserActions(caseId, caseConnectorId); } return () => { @@ -310,6 +303,6 @@ export const useGetCaseUserActions = ( abortCtrlRef.current.abort(); }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [caseId, subCaseId]); + }, [caseId]); return { ...caseUserActionsState, fetchCaseUserActions }; }; diff --git a/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx b/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx index 23b57004ca4d7..dee4d424c84de 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx @@ -17,7 +17,7 @@ import { UseGetCases, } from './use_get_cases'; import { UpdateKey } from './types'; -import { allCases, basicCase } from './mock'; +import { allCases, basicCase, caseWithAlerts, caseWithAlertsSyncOff } from './mock'; import * as api from './api'; import { TestProviders } from '../common/mock'; import { useToasts } from '../common/lib/kibana'; @@ -121,6 +121,47 @@ describe('useGetCases', () => { }); }); + it('shows a success toast notifying of synced alerts when sync is on', async () => { + await act(async () => { + const updateCase = { + updateKey: 'status' as UpdateKey, + updateValue: 'open', + caseId: caseWithAlerts.id, + refetchCasesStatus: jest.fn(), + version: '99999', + }; + const { result, waitForNextUpdate } = renderHook(() => useGetCases(), { + wrapper: ({ children }) => {children}, + }); + await waitForNextUpdate(); + result.current.dispatchUpdateCaseProperty(updateCase); + }); + expect(addSuccess).toHaveBeenCalledWith({ + text: 'Updated the statuses of attached alerts.', + title: 'Updated "Another horrible breach!!"', + }); + }); + + it('shows a success toast without notifying of synced alerts when sync is off', async () => { + await act(async () => { + const updateCase = { + updateKey: 'status' as UpdateKey, + updateValue: 'open', + caseId: caseWithAlertsSyncOff.id, + refetchCasesStatus: jest.fn(), + version: '99999', + }; + const { result, waitForNextUpdate } = renderHook(() => useGetCases(), { + wrapper: ({ children }) => {children}, + }); + await waitForNextUpdate(); + result.current.dispatchUpdateCaseProperty(updateCase); + }); + expect(addSuccess).toHaveBeenCalledWith({ + title: 'Updated "Another horrible breach!!"', + }); + }); + it('refetch cases', async () => { const spyOnGetCases = jest.spyOn(api, 'getCases'); await act(async () => { diff --git a/x-pack/plugins/cases/public/containers/use_get_cases.tsx b/x-pack/plugins/cases/public/containers/use_get_cases.tsx index de0f0f514da1b..283cdfdf39aa4 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases.tsx @@ -104,7 +104,6 @@ export const DEFAULT_FILTER_OPTIONS: FilterOptions = { reporters: [], status: StatusAll, tags: [], - onlyCollectionType: false, owner: [], }; @@ -235,7 +234,7 @@ export const useGetCases = ( toasts.addSuccess({ title: i18n.UPDATED_CASE(caseData.title), text: - updateKey === 'status' && caseData.totalAlerts > 0 + updateKey === 'status' && caseData.totalAlerts > 0 && caseData.settings.syncAlerts ? i18n.STATUS_CHANGED_TOASTER_TEXT : undefined, }); 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 dd9d73cff9bae..cd76738b70307 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 @@ -10,7 +10,7 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { CommentType } from '../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; import { usePostComment, UsePostComment } from './use_post_comment'; -import { basicCaseId, basicSubCaseId } from './mock'; +import { basicCaseId } from './mock'; import * as api from './api'; jest.mock('./api'); @@ -58,32 +58,7 @@ describe('usePostComment', () => { updateCase: updateCaseCallback, }); await waitForNextUpdate(); - expect(spyOnPostCase).toBeCalledWith(samplePost, basicCaseId, abortCtrl.signal, undefined); - }); - }); - - it('calls postComment with correct arguments - sub case', async () => { - const spyOnPostCase = jest.spyOn(api, 'postComment'); - - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - usePostComment() - ); - await waitForNextUpdate(); - - result.current.postComment({ - caseId: basicCaseId, - data: samplePost, - updateCase: updateCaseCallback, - subCaseId: basicSubCaseId, - }); - await waitForNextUpdate(); - expect(spyOnPostCase).toBeCalledWith( - samplePost, - basicCaseId, - abortCtrl.signal, - basicSubCaseId - ); + expect(spyOnPostCase).toBeCalledWith(samplePost, basicCaseId, abortCtrl.signal); }); }); 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 d796c5035ff9d..67db681166d95 100644 --- a/x-pack/plugins/cases/public/containers/use_post_comment.tsx +++ b/x-pack/plugins/cases/public/containers/use_post_comment.tsx @@ -45,7 +45,6 @@ export interface PostComment { caseId: string; data: CommentRequest; updateCase?: (newCase: Case) => void; - subCaseId?: string; } export interface UsePostComment extends NewCommentState { postComment: (args: PostComment) => Promise; @@ -61,14 +60,14 @@ export const usePostComment = (): UsePostComment => { const abortCtrlRef = useRef(new AbortController()); const postMyComment = useCallback( - async ({ caseId, data, updateCase, subCaseId }: PostComment) => { + async ({ caseId, data, updateCase }: PostComment) => { try { isCancelledRef.current = false; abortCtrlRef.current.abort(); abortCtrlRef.current = new AbortController(); dispatch({ type: 'FETCH_INIT' }); - const response = await postComment(data, caseId, abortCtrlRef.current.signal, subCaseId); + const response = await postComment(data, caseId, abortCtrlRef.current.signal); if (!isCancelledRef.current) { dispatch({ type: 'FETCH_SUCCESS' }); diff --git a/x-pack/plugins/cases/public/containers/use_update_case.test.tsx b/x-pack/plugins/cases/public/containers/use_update_case.test.tsx index 8d7cfc56b195c..52ab9d3a3ebc5 100644 --- a/x-pack/plugins/cases/public/containers/use_update_case.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_update_case.test.tsx @@ -7,7 +7,7 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { useUpdateCase, UseUpdateCase } from './use_update_case'; -import { basicCase, basicSubCaseId } from './mock'; +import { basicCase } from './mock'; import * as api from './api'; import { UpdateKey } from './types'; @@ -85,27 +85,7 @@ describe('useUpdateCase', () => { isError: false, updateCaseProperty: result.current.updateCaseProperty, }); - expect(fetchCaseUserActions).toBeCalledWith(basicCase.id, 'none', undefined); - expect(updateCase).toBeCalledWith(basicCase); - expect(onSuccess).toHaveBeenCalled(); - }); - }); - - it('patch sub case', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => - useUpdateCase({ caseId: basicCase.id, subCaseId: basicSubCaseId }) - ); - await waitForNextUpdate(); - result.current.updateCaseProperty(sampleUpdate); - await waitForNextUpdate(); - expect(result.current).toEqual({ - updateKey: null, - isLoading: false, - isError: false, - updateCaseProperty: result.current.updateCaseProperty, - }); - expect(fetchCaseUserActions).toBeCalledWith(basicCase.id, 'none', basicSubCaseId); + expect(fetchCaseUserActions).toBeCalledWith(basicCase.id, 'none'); expect(updateCase).toBeCalledWith(basicCase); expect(onSuccess).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/cases/public/containers/use_update_case.tsx b/x-pack/plugins/cases/public/containers/use_update_case.tsx index 42e861d300341..eedaf1fca7a8e 100644 --- a/x-pack/plugins/cases/public/containers/use_update_case.tsx +++ b/x-pack/plugins/cases/public/containers/use_update_case.tsx @@ -8,9 +8,8 @@ import { useReducer, useCallback, useRef, useEffect } from 'react'; import { useToasts } from '../common/lib/kibana'; -import { patchCase, patchSubCase } from './api'; +import { patchCase } from './api'; import { UpdateKey, UpdateByKey } from '../../common/ui/types'; -import { CaseStatuses } from '../../common/api'; import * as i18n from './translations'; import { createUpdateSuccessToaster } from './utils'; @@ -57,13 +56,7 @@ const dataFetchReducer = (state: NewCaseState, action: Action): NewCaseState => export interface UseUpdateCase extends NewCaseState { updateCaseProperty: (updates: UpdateByKey) => void; } -export const useUpdateCase = ({ - caseId, - subCaseId, -}: { - caseId: string; - subCaseId?: string; -}): UseUpdateCase => { +export const useUpdateCase = ({ caseId }: { caseId: string }): UseUpdateCase => { const [state, dispatch] = useReducer(dataFetchReducer, { isLoading: false, isError: false, @@ -89,24 +82,16 @@ export const useUpdateCase = ({ abortCtrlRef.current = new AbortController(); dispatch({ type: 'FETCH_INIT', payload: updateKey }); - const response = await (updateKey === 'status' && subCaseId - ? patchSubCase( - caseId, - subCaseId, - { status: updateValue as CaseStatuses }, - caseData.version, - abortCtrlRef.current.signal - ) - : patchCase( - caseId, - { [updateKey]: updateValue }, - caseData.version, - abortCtrlRef.current.signal - )); + const response = await patchCase( + caseId, + { [updateKey]: updateValue }, + caseData.version, + abortCtrlRef.current.signal + ); if (!isCancelledRef.current) { if (fetchCaseUserActions != null) { - fetchCaseUserActions(caseId, response[0].connector.id, subCaseId); + fetchCaseUserActions(caseId, response[0].connector.id); } if (updateCase != null) { updateCase(response[0]); @@ -136,7 +121,7 @@ export const useUpdateCase = ({ } }, // eslint-disable-next-line react-hooks/exhaustive-deps - [caseId, subCaseId] + [caseId] ); useEffect( diff --git a/x-pack/plugins/cases/public/containers/use_update_comment.test.tsx b/x-pack/plugins/cases/public/containers/use_update_comment.test.tsx index 836ec10e608a6..9e5358a5f8b5e 100644 --- a/x-pack/plugins/cases/public/containers/use_update_comment.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_update_comment.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { renderHook, act } from '@testing-library/react-hooks'; import { useUpdateComment, UseUpdateComment } from './use_update_comment'; -import { basicCase, basicCaseCommentPatch, basicSubCaseId } from './mock'; +import { basicCase, basicCaseCommentPatch } from './mock'; import * as api from './api'; import { TestProviders } from '../common/mock'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; @@ -67,28 +67,6 @@ describe('useUpdateComment', () => { version: basicCase.comments[0].version, signal: abortCtrl.signal, owner: SECURITY_SOLUTION_OWNER, - subCaseId: undefined, - }); - }); - }); - - it('calls patchComment with correct arguments - sub case', async () => { - const spyOnPatchComment = jest.spyOn(api, 'patchComment'); - - await act(async () => { - const { result, waitForNextUpdate } = renderHookUseUpdateComment(); - await waitForNextUpdate(); - - result.current.patchComment({ ...sampleUpdate, subCaseId: basicSubCaseId }); - await waitForNextUpdate(); - expect(spyOnPatchComment).toBeCalledWith({ - caseId: basicCase.id, - commentId: basicCase.comments[0].id, - commentUpdate: 'updated comment', - version: basicCase.comments[0].version, - signal: abortCtrl.signal, - owner: SECURITY_SOLUTION_OWNER, - subCaseId: basicSubCaseId, }); }); }); diff --git a/x-pack/plugins/cases/public/containers/use_update_comment.tsx b/x-pack/plugins/cases/public/containers/use_update_comment.tsx index cc287d4dee863..1a457237d2e64 100644 --- a/x-pack/plugins/cases/public/containers/use_update_comment.tsx +++ b/x-pack/plugins/cases/public/containers/use_update_comment.tsx @@ -56,7 +56,6 @@ interface UpdateComment { commentId: string; commentUpdate: string; fetchUserActions: () => void; - subCaseId?: string; updateCase: (newCase: Case) => void; version: string; } @@ -83,7 +82,6 @@ export const useUpdateComment = (): UseUpdateComment => { commentId, commentUpdate, fetchUserActions, - subCaseId, updateCase, version, }: UpdateComment) => { @@ -99,7 +97,6 @@ export const useUpdateComment = (): UseUpdateComment => { commentUpdate, version, signal: abortCtrlRef.current.signal, - subCaseId, owner, }); diff --git a/x-pack/plugins/cases/public/plugin.ts b/x-pack/plugins/cases/public/plugin.ts index f38b2d12e2ad4..70882560edb77 100644 --- a/x-pack/plugins/cases/public/plugin.ts +++ b/x-pack/plugins/cases/public/plugin.ts @@ -8,7 +8,6 @@ import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'src/core/public'; import { CasesUiStart, SetupPlugins, StartPlugins } from './types'; import { KibanaServices } from './common/lib/kibana'; -import { getCaseConnectorUi } from './components/connectors'; import { getCasesLazy, getRecentCasesLazy, @@ -17,7 +16,6 @@ import { canUseCases, } from './methods'; import { CasesUiConfigType } from '../common/ui/types'; -import { ENABLE_CASE_CONNECTOR } from '../common/constants'; /** * @public @@ -29,11 +27,7 @@ export class CasesUiPlugin implements Plugin(); diff --git a/x-pack/plugins/cases/public/types.ts b/x-pack/plugins/cases/public/types.ts index cb2e570b58e13..5d53b46b8c014 100644 --- a/x-pack/plugins/cases/public/types.ts +++ b/x-pack/plugins/cases/public/types.ts @@ -10,10 +10,7 @@ import { ReactElement } from 'react'; import type { LensPublicStart } from '../../lens/public'; import type { SecurityPluginSetup } from '../../security/public'; -import type { - TriggersAndActionsUIPublicPluginSetup as TriggersActionsSetup, - TriggersAndActionsUIPublicPluginStart as TriggersActionsStart, -} from '../../triggers_actions_ui/public'; +import type { TriggersAndActionsUIPublicPluginStart as TriggersActionsStart } from '../../triggers_actions_ui/public'; import type { DataPublicPluginStart } from '../../../../src/plugins/data/public'; import type { EmbeddableStart } from '../../../../src/plugins/embeddable/public'; import type { SpacesPluginStart } from '../../spaces/public'; @@ -29,7 +26,6 @@ import type { export interface SetupPlugins { security: SecurityPluginSetup; - triggersActionsUi: TriggersActionsSetup; } export interface StartPlugins { diff --git a/x-pack/plugins/cases/server/client/attachments/add.ts b/x-pack/plugins/cases/server/client/attachments/add.ts index b443d0c8bfa7b..ca03381681796 100644 --- a/x-pack/plugins/cases/server/client/attachments/add.ts +++ b/x-pack/plugins/cases/server/client/attachments/add.ts @@ -10,9 +10,7 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; -import { nodeBuilder } from '@kbn/es-query'; import { - SavedObject, SavedObjectsClientContract, Logger, SavedObjectsUtils, @@ -22,201 +20,24 @@ import { LensServerPluginSetup } from '../../../../lens/server'; import { Actions, ActionTypes, - AlertCommentRequestRt, CaseResponse, - CaseStatuses, - CaseType, CommentRequest, CommentRequestRt, CommentType, - SubCaseAttributes, throwErrors, User, } from '../../../common/api'; -import { - CASE_COMMENT_SAVED_OBJECT, - ENABLE_CASE_CONNECTOR, - MAX_GENERATED_ALERTS_PER_SUB_CASE, -} from '../../../common/constants'; -import { AttachmentService, CasesService, CaseUserActionService } from '../../services'; +import { AttachmentService, CasesService } from '../../services'; import { CommentableCase } from '../../common/models'; import { createCaseError } from '../../common/error'; -import { createAlertUpdateRequest, isCommentRequestTypeGenAlert } from '../../common/utils'; +import { createAlertUpdateRequest } from '../../common/utils'; import { CasesClientArgs, CasesClientInternal } from '..'; import { decodeCommentRequest } from '../utils'; import { Operations } from '../../authorization'; -async function getSubCase({ - caseService, - unsecuredSavedObjectsClient, - caseId, - createdAt, - userActionService, - user, -}: { - caseService: CasesService; - unsecuredSavedObjectsClient: SavedObjectsClientContract; - caseId: string; - createdAt: string; - userActionService: CaseUserActionService; - user: User; -}): Promise> { - const mostRecentSubCase = await caseService.getMostRecentSubCase( - unsecuredSavedObjectsClient, - caseId - ); - if (mostRecentSubCase && mostRecentSubCase.attributes.status !== CaseStatuses.closed) { - const subCaseAlertsAttachement = await caseService.getAllSubCaseComments({ - unsecuredSavedObjectsClient, - id: mostRecentSubCase.id, - options: { - fields: [], - filter: nodeBuilder.is( - `${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, - CommentType.generatedAlert - ), - page: 1, - perPage: 1, - }, - }); - - if (subCaseAlertsAttachement.total <= MAX_GENERATED_ALERTS_PER_SUB_CASE) { - return mostRecentSubCase; - } - } - - const newSubCase = await caseService.createSubCase({ - unsecuredSavedObjectsClient, - createdAt, - caseId, - createdBy: user, - }); - - return newSubCase; -} - -const addGeneratedAlerts = async ( - { caseId, comment }: AddArgs, - clientArgs: CasesClientArgs, - casesClientInternal: CasesClientInternal -): Promise => { - const { - unsecuredSavedObjectsClient, - attachmentService, - caseService, - userActionService, - logger, - lensEmbeddableFactory, - authorization, - alertsService, - user, - } = clientArgs; - - const query = pipe( - AlertCommentRequestRt.decode(comment), - fold(throwErrors(Boom.badRequest), identity) - ); - - decodeCommentRequest(comment); - - // This function only supports adding generated alerts - if (comment.type !== CommentType.generatedAlert) { - throw Boom.internal('Attempting to add a non generated alert in the wrong context'); - } - - try { - const createdDate = new Date().toISOString(); - const savedObjectID = SavedObjectsUtils.generateId(); - - await authorization.ensureAuthorized({ - entities: [{ owner: comment.owner, id: savedObjectID }], - operation: Operations.createComment, - }); - - const caseInfo = await caseService.getCase({ - unsecuredSavedObjectsClient, - id: caseId, - }); - - if ( - query.type === CommentType.generatedAlert && - caseInfo.attributes.type !== CaseType.collection - ) { - throw Boom.badRequest('Sub case style alert comment cannot be added to an individual case'); - } - - const userDetails: User = { - username: caseInfo.attributes.created_by?.username, - full_name: caseInfo.attributes.created_by?.full_name, - email: caseInfo.attributes.created_by?.email, - }; - - const subCase = await getSubCase({ - caseService, - unsecuredSavedObjectsClient, - caseId, - createdAt: createdDate, - userActionService, - user: userDetails, - }); - - const commentableCase = new CommentableCase({ - logger, - collection: caseInfo, - subCase, - unsecuredSavedObjectsClient, - caseService, - attachmentService, - lensEmbeddableFactory, - }); - - const { comment: newComment, commentableCase: updatedCase } = - await commentableCase.createComment({ - createdDate, - user: userDetails, - commentReq: query, - id: savedObjectID, - }); - - if ( - (newComment.attributes.type === CommentType.alert || - newComment.attributes.type === CommentType.generatedAlert) && - caseInfo.attributes.settings.syncAlerts - ) { - const alertsToUpdate = createAlertUpdateRequest({ - comment: query, - status: subCase.attributes.status, - }); - await alertsService.updateAlertsStatus(alertsToUpdate); - } - - await userActionService.createUserAction({ - type: ActionTypes.comment, - action: Actions.create, - unsecuredSavedObjectsClient, - caseId: updatedCase.caseId, - subCaseId: updatedCase.subCaseId, - payload: { - attachment: query, - }, - attachmentId: newComment.id, - user, - owner: newComment.attributes.owner, - }); - - return updatedCase.encode(); - } catch (error) { - throw createCaseError({ - message: `Failed while adding a generated alert to case id: ${caseId} error: ${error}`, - error, - logger, - }); - } -}; - -async function getCombinedCase({ +async function createCommentableCase({ caseService, attachmentService, unsecuredSavedObjectsClient, @@ -231,53 +52,19 @@ async function getCombinedCase({ logger: Logger; lensEmbeddableFactory: LensServerPluginSetup['lensEmbeddableFactory']; }): Promise { - const [casePromise, subCasePromise] = await Promise.allSettled([ - caseService.getCase({ - unsecuredSavedObjectsClient, - id, - }), - ...(ENABLE_CASE_CONNECTOR - ? [ - caseService.getSubCase({ - unsecuredSavedObjectsClient, - id, - }), - ] - : [Promise.reject(new Error('case connector feature is disabled'))]), - ]); - - if (subCasePromise.status === 'fulfilled') { - if (subCasePromise.value.references.length > 0) { - const caseValue = await caseService.getCase({ - unsecuredSavedObjectsClient, - id: subCasePromise.value.references[0].id, - }); - return new CommentableCase({ - logger, - collection: caseValue, - subCase: subCasePromise.value, - caseService, - attachmentService, - unsecuredSavedObjectsClient, - lensEmbeddableFactory, - }); - } else { - throw Boom.badRequest('Sub case found without reference to collection'); - } - } + const caseInfo = await caseService.getCase({ + unsecuredSavedObjectsClient, + id, + }); - if (casePromise.status === 'rejected') { - throw casePromise.reason; - } else { - return new CommentableCase({ - logger, - collection: casePromise.value, - caseService, - attachmentService, - unsecuredSavedObjectsClient, - lensEmbeddableFactory, - }); - } + return new CommentableCase({ + logger, + caseInfo, + caseService, + attachmentService, + unsecuredSavedObjectsClient, + lensEmbeddableFactory, + }); } /** @@ -322,16 +109,6 @@ export const addComment = async ( alertsService, } = clientArgs; - if (isCommentRequestTypeGenAlert(comment)) { - if (!ENABLE_CASE_CONNECTOR) { - throw Boom.badRequest( - 'Attempting to add a generated alert when case connector feature is disabled' - ); - } - - return addGeneratedAlerts(addArgs, clientArgs, casesClientInternal); - } - decodeCommentRequest(comment); try { const savedObjectID = SavedObjectsUtils.generateId(); @@ -343,7 +120,7 @@ export const addComment = async ( const createdDate = new Date().toISOString(); - const combinedCase = await getCombinedCase({ + const combinedCase = await createCommentableCase({ caseService, attachmentService, unsecuredSavedObjectsClient, @@ -381,7 +158,6 @@ export const addComment = async ( action: Actions.create, unsecuredSavedObjectsClient, caseId, - subCaseId: updatedCase.subCaseId, attachmentId: newComment.id, payload: { attachment: query, diff --git a/x-pack/plugins/cases/server/client/attachments/delete.ts b/x-pack/plugins/cases/server/client/attachments/delete.ts index 66394dd3cb7f5..9d048162da7eb 100644 --- a/x-pack/plugins/cases/server/client/attachments/delete.ts +++ b/x-pack/plugins/cases/server/client/attachments/delete.ts @@ -9,33 +9,24 @@ import Boom from '@hapi/boom'; import pMap from 'p-map'; import { SavedObject } from 'kibana/public'; -import { Actions, ActionTypes, AssociationType, CommentAttributes } from '../../../common/api'; -import { - CASE_SAVED_OBJECT, - MAX_CONCURRENT_SEARCHES, - SUB_CASE_SAVED_OBJECT, -} from '../../../common/constants'; +import { Actions, ActionTypes, CommentAttributes } from '../../../common/api'; +import { CASE_SAVED_OBJECT, MAX_CONCURRENT_SEARCHES } from '../../../common/constants'; import { CasesClientArgs } from '../types'; import { createCaseError } from '../../common/error'; -import { checkEnabledCaseConnectorOrThrow } from '../../common/utils'; import { Operations } from '../../authorization'; /** - * Parameters for deleting all comments of a case or sub case. + * Parameters for deleting all comments of a case. */ export interface DeleteAllArgs { /** * The case ID to delete all attachments for */ caseID: string; - /** - * If specified the caseID will be ignored and this value will be used to find a sub case for deleting all the attachments - */ - subCaseID?: string; } /** - * Parameters for deleting a single attachment of a case or sub case. + * Parameters for deleting a single attachment of a case. */ export interface DeleteArgs { /** @@ -46,19 +37,15 @@ export interface DeleteArgs { * The attachment ID to delete */ attachmentID: string; - /** - * If specified the caseID will be ignored and this value will be used to find a sub case for deleting the attachment - */ - subCaseID?: string; } /** - * Delete all comments for a case or sub case. + * Delete all comments for a case. * * @ignore */ export async function deleteAll( - { caseID, subCaseID }: DeleteAllArgs, + { caseID }: DeleteAllArgs, clientArgs: CasesClientArgs ): Promise { const { @@ -72,17 +59,13 @@ export async function deleteAll( } = clientArgs; try { - checkEnabledCaseConnectorOrThrow(subCaseID); - - const id = subCaseID ?? caseID; - const comments = await caseService.getCommentsByAssociation({ + const comments = await caseService.getAllCaseComments({ unsecuredSavedObjectsClient, - id, - associationType: subCaseID ? AssociationType.subCase : AssociationType.case, + id: caseID, }); if (comments.total <= 0) { - throw Boom.notFound(`No comments found for ${id}.`); + throw Boom.notFound(`No comments found for ${caseID}.`); } await authorization.ensureAuthorized({ @@ -107,7 +90,6 @@ export async function deleteAll( await userActionService.bulkCreateAttachmentDeletion({ unsecuredSavedObjectsClient, caseId: caseID, - subCaseId: subCaseID, attachments: comments.saved_objects.map((comment) => ({ id: comment.id, owner: comment.attributes.owner, @@ -117,7 +99,7 @@ export async function deleteAll( }); } catch (error) { throw createCaseError({ - message: `Failed to delete all comments case id: ${caseID} sub case id: ${subCaseID}: ${error}`, + message: `Failed to delete all comments case id: ${caseID}: ${error}`, error, logger, }); @@ -130,7 +112,7 @@ export async function deleteAll( * @ignore */ export async function deleteComment( - { caseID, attachmentID, subCaseID }: DeleteArgs, + { caseID, attachmentID }: DeleteArgs, clientArgs: CasesClientArgs ) { const { @@ -143,8 +125,6 @@ export async function deleteComment( } = clientArgs; try { - checkEnabledCaseConnectorOrThrow(subCaseID); - const myComment = await attachmentService.get({ unsecuredSavedObjectsClient, attachmentId: attachmentID, @@ -159,8 +139,8 @@ export async function deleteComment( operation: Operations.deleteComment, }); - const type = subCaseID ? SUB_CASE_SAVED_OBJECT : CASE_SAVED_OBJECT; - const id = subCaseID ?? caseID; + const type = CASE_SAVED_OBJECT; + const id = caseID; const caseRef = myComment.references.find((c) => c.type === type); if (caseRef == null || (caseRef != null && caseRef.id !== id)) { @@ -177,7 +157,6 @@ export async function deleteComment( action: Actions.delete, unsecuredSavedObjectsClient, caseId: id, - subCaseId: subCaseID, attachmentId: attachmentID, payload: { attachment: { ...myComment.attributes } }, user, @@ -185,7 +164,7 @@ export async function deleteComment( }); } catch (error) { throw createCaseError({ - message: `Failed to delete comment: ${caseID} comment id: ${attachmentID} sub case id: ${subCaseID}: ${error}`, + message: `Failed to delete comment: ${caseID} comment id: ${attachmentID}: ${error}`, error, logger, }); diff --git a/x-pack/plugins/cases/server/client/attachments/get.ts b/x-pack/plugins/cases/server/client/attachments/get.ts index 264b3d9f11b85..b9ac0f2eea000 100644 --- a/x-pack/plugins/cases/server/client/attachments/get.ts +++ b/x-pack/plugins/cases/server/client/attachments/get.ts @@ -4,25 +4,20 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import Boom from '@hapi/boom'; -import { SavedObject, SavedObjectsFindResponse } from 'kibana/server'; +import { SavedObject } from 'kibana/server'; import { AlertResponse, AllCommentsResponse, AllCommentsResponseRt, - AssociationType, AttributesTypeAlerts, - CommentAttributes, CommentResponse, CommentResponseRt, CommentsResponse, CommentsResponseRt, FindQueryParams, } from '../../../common/api'; -import { ENABLE_CASE_CONNECTOR } from '../../../common/constants'; import { - checkEnabledCaseConnectorOrThrow, defaultSortField, transformComments, flattenCommentSavedObject, @@ -59,14 +54,6 @@ export interface GetAllArgs { * The case ID to retrieve all attachments for */ caseID: string; - /** - * Optionally include the attachments associated with a sub case - */ - includeSubCaseComments?: boolean; - /** - * If included the case ID will be ignored and the attachments will be retrieved from the specified ID of the sub case - */ - subCaseID?: string; } export interface GetArgs { @@ -122,7 +109,6 @@ export const getAllAlertsAttachToCase = async ( const theCase = await casesClient.cases.get({ id: caseId, includeComments: false, - includeSubCaseComments: false, }); const { filter: authorizationFilter, ensureSavedObjectsAreAuthorized } = @@ -163,13 +149,10 @@ export async function find( const { unsecuredSavedObjectsClient, caseService, logger, authorization } = clientArgs; try { - checkEnabledCaseConnectorOrThrow(queryParams?.subCaseId); - const { filter: authorizationFilter, ensureSavedObjectsAreAuthorized } = await authorization.getAuthorizationFilter(Operations.findComments); - const id = queryParams?.subCaseId ?? caseID; - const associationType = queryParams?.subCaseId ? AssociationType.subCase : AssociationType.case; + const id = caseID; const { filter, ...queryWithoutFilter } = queryParams ?? {}; // if the fields property was defined, make sure we include the 'owner' field in the response @@ -194,7 +177,6 @@ export async function find( ...queryWithoutFilter, fields, }, - associationType, } : { caseService, @@ -206,10 +188,9 @@ export async function find( sortField: 'created_at', filter: combinedFilter, }, - associationType, }; - const theComments = await caseService.getCommentsByAssociation(args); + const theComments = await caseService.getAllCaseComments(args); ensureSavedObjectsAreAuthorized( theComments.saved_objects.map((comment) => ({ @@ -261,53 +242,29 @@ export async function get( } /** - * Retrieves all the attachments for a case. The `includeSubCaseComments` can be used to include the sub case comments for - * collections. If the entity is a sub case, pass in the subCaseID. + * Retrieves all the attachments for a case. * * @ignore */ export async function getAll( - { caseID, includeSubCaseComments, subCaseID }: GetAllArgs, + { caseID }: GetAllArgs, clientArgs: CasesClientArgs ): Promise { const { unsecuredSavedObjectsClient, caseService, logger, authorization } = clientArgs; try { - let comments: SavedObjectsFindResponse; - - if ( - !ENABLE_CASE_CONNECTOR && - (subCaseID !== undefined || includeSubCaseComments !== undefined) - ) { - throw Boom.badRequest( - 'The sub case id and include sub case comments fields are not supported when the case connector feature is disabled' - ); - } - const { filter, ensureSavedObjectsAreAuthorized } = await authorization.getAuthorizationFilter( Operations.getAllComments ); - if (subCaseID) { - comments = await caseService.getAllSubCaseComments({ - unsecuredSavedObjectsClient, - id: subCaseID, - options: { - filter, - sortField: defaultSortField, - }, - }); - } else { - comments = await caseService.getAllCaseComments({ - unsecuredSavedObjectsClient, - id: caseID, - includeSubCaseComments, - options: { - filter, - sortField: defaultSortField, - }, - }); - } + const comments = await caseService.getAllCaseComments({ + unsecuredSavedObjectsClient, + id: caseID, + options: { + filter, + sortField: defaultSortField, + }, + }); ensureSavedObjectsAreAuthorized( comments.saved_objects.map((comment) => ({ id: comment.id, owner: comment.attributes.owner })) @@ -316,7 +273,7 @@ export async function getAll( return AllCommentsResponseRt.encode(flattenCommentSavedObjects(comments.saved_objects)); } catch (error) { throw createCaseError({ - message: `Failed to get all comments case id: ${caseID} include sub case comments: ${includeSubCaseComments} sub case id: ${subCaseID}: ${error}`, + message: `Failed to get all comments case id: ${caseID}: ${error}`, error, logger, }); diff --git a/x-pack/plugins/cases/server/client/attachments/update.ts b/x-pack/plugins/cases/server/client/attachments/update.ts index bfa1d70e55636..1928057f17edf 100644 --- a/x-pack/plugins/cases/server/client/attachments/update.ts +++ b/x-pack/plugins/cases/server/client/attachments/update.ts @@ -11,9 +11,8 @@ import { SavedObjectsClientContract, Logger } from 'kibana/server'; import { LensServerPluginSetup } from '../../../../lens/server'; import { CommentableCase } from '../../common/models'; import { createCaseError } from '../../common/error'; -import { checkEnabledCaseConnectorOrThrow } from '../../common/utils'; import { Actions, ActionTypes, CaseResponse, CommentPatchRequest } from '../../../common/api'; -import { CASE_SAVED_OBJECT, SUB_CASE_SAVED_OBJECT } from '../../../common/constants'; +import { CASE_SAVED_OBJECT } from '../../../common/constants'; import { AttachmentService, CasesService } from '../../services'; import { CasesClientArgs } from '..'; import { decodeCommentRequest } from '../utils'; @@ -31,10 +30,6 @@ export interface UpdateArgs { * The full attachment request with the fields updated with appropriate values */ updateRequest: CommentPatchRequest; - /** - * The ID of a sub case, if specified a sub case will be searched for to perform the attachment update instead of on a case - */ - subCaseID?: string; } interface CombinedCaseParams { @@ -44,52 +39,29 @@ interface CombinedCaseParams { caseID: string; logger: Logger; lensEmbeddableFactory: LensServerPluginSetup['lensEmbeddableFactory']; - subCaseId?: string; } -async function getCommentableCase({ +async function createCommentableCase({ attachmentService, caseService, unsecuredSavedObjectsClient, caseID, - subCaseId, logger, lensEmbeddableFactory, }: CombinedCaseParams) { - if (subCaseId) { - const [caseInfo, subCase] = await Promise.all([ - caseService.getCase({ - unsecuredSavedObjectsClient, - id: caseID, - }), - caseService.getSubCase({ - unsecuredSavedObjectsClient, - id: subCaseId, - }), - ]); - return new CommentableCase({ - attachmentService, - caseService, - collection: caseInfo, - subCase, - unsecuredSavedObjectsClient, - logger, - lensEmbeddableFactory, - }); - } else { - const caseInfo = await caseService.getCase({ - unsecuredSavedObjectsClient, - id: caseID, - }); - return new CommentableCase({ - attachmentService, - caseService, - collection: caseInfo, - unsecuredSavedObjectsClient, - logger, - lensEmbeddableFactory, - }); - } + const caseInfo = await caseService.getCase({ + unsecuredSavedObjectsClient, + id: caseID, + }); + + return new CommentableCase({ + attachmentService, + caseService, + caseInfo, + unsecuredSavedObjectsClient, + logger, + lensEmbeddableFactory, + }); } /** @@ -98,7 +70,7 @@ async function getCommentableCase({ * @ignore */ export async function update( - { caseID, subCaseID, updateRequest: queryParams }: UpdateArgs, + { caseID, updateRequest: queryParams }: UpdateArgs, clientArgs: CasesClientArgs ): Promise { const { @@ -113,8 +85,6 @@ export async function update( } = clientArgs; try { - checkEnabledCaseConnectorOrThrow(subCaseID); - const { id: queryCommentId, version: queryCommentVersion, @@ -123,12 +93,11 @@ export async function update( decodeCommentRequest(queryRestAttributes); - const commentableCase = await getCommentableCase({ + const commentableCase = await createCommentableCase({ attachmentService, caseService, unsecuredSavedObjectsClient, caseID, - subCaseId: subCaseID, logger, lensEmbeddableFactory, }); @@ -155,9 +124,7 @@ export async function update( throw Boom.badRequest(`You cannot change the owner of the comment.`); } - const saveObjType = subCaseID ? SUB_CASE_SAVED_OBJECT : CASE_SAVED_OBJECT; - - const caseRef = myComment.references.find((c) => c.type === saveObjType); + const caseRef = myComment.references.find((c) => c.type === CASE_SAVED_OBJECT); if (caseRef == null || (caseRef != null && caseRef.id !== commentableCase.id)) { throw Boom.notFound( `This comment ${queryCommentId} does not exist in ${commentableCase.id}).` @@ -183,7 +150,6 @@ export async function update( action: Actions.update, unsecuredSavedObjectsClient, caseId: caseID, - subCaseId: subCaseID, attachmentId: updatedComment.id, payload: { attachment: queryRestAttributes }, user, @@ -193,7 +159,7 @@ export async function update( return await updatedCase.encode(); } catch (error) { throw createCaseError({ - message: `Failed to patch comment case id: ${caseID} sub case id: ${subCaseID}: ${error}`, + message: `Failed to patch comment case id: ${caseID}: ${error}`, error, logger, }); diff --git a/x-pack/plugins/cases/server/client/cases/create.ts b/x-pack/plugins/cases/server/client/cases/create.ts index 0a82d900719e0..0101227e265a5 100644 --- a/x-pack/plugins/cases/server/client/cases/create.ts +++ b/x-pack/plugins/cases/server/client/cases/create.ts @@ -17,12 +17,11 @@ import { excess, CaseResponseRt, CaseResponse, - CasesClientPostRequestRt, CasePostRequest, - CaseType, ActionTypes, + CasePostRequestRt, } from '../../../common/api'; -import { ENABLE_CASE_CONNECTOR, MAX_TITLE_LENGTH } from '../../../common/constants'; +import { MAX_TITLE_LENGTH } from '../../../common/constants'; import { Operations } from '../../authorization'; import { createCaseError } from '../../common/error'; @@ -47,20 +46,9 @@ export const create = async ( authorization: auth, } = clientArgs; - // default to an individual case if the type is not defined. - const { type = CaseType.individual, ...nonTypeCaseFields } = data; - - if (!ENABLE_CASE_CONNECTOR && type === CaseType.collection) { - throw Boom.badRequest( - 'Case type cannot be collection when the case connector feature is disabled' - ); - } - const query = pipe( - // decode with the defaulted type field - excess(CasesClientPostRequestRt).decode({ - type, - ...nonTypeCaseFields, + excess(CasePostRequestRt).decode({ + ...data, }), fold(throwErrors(Boom.badRequest), identity) ); diff --git a/x-pack/plugins/cases/server/client/cases/delete.ts b/x-pack/plugins/cases/server/client/cases/delete.ts index 182fa78387707..d1c12219f2ef2 100644 --- a/x-pack/plugins/cases/server/client/cases/delete.ts +++ b/x-pack/plugins/cases/server/client/cases/delete.ts @@ -7,56 +7,13 @@ import pMap from 'p-map'; import { Boom } from '@hapi/boom'; -import { SavedObject, SavedObjectsClientContract, SavedObjectsFindResponse } from 'kibana/server'; -import { CommentAttributes, SubCaseAttributes } from '../../../common/api'; -import { ENABLE_CASE_CONNECTOR, MAX_CONCURRENT_SEARCHES } from '../../../common/constants'; +import { SavedObjectsFindResponse } from 'kibana/server'; +import { CommentAttributes } from '../../../common/api'; +import { MAX_CONCURRENT_SEARCHES } from '../../../common/constants'; import { CasesClientArgs } from '..'; import { createCaseError } from '../../common/error'; -import { AttachmentService, CasesService } from '../../services'; import { Operations, OwnerEntity } from '../../authorization'; -async function deleteSubCases({ - attachmentService, - caseService, - unsecuredSavedObjectsClient, - caseIds, -}: { - attachmentService: AttachmentService; - caseService: CasesService; - unsecuredSavedObjectsClient: SavedObjectsClientContract; - caseIds: string[]; -}) { - const subCasesForCaseIds = await caseService.findSubCasesByCaseId({ - unsecuredSavedObjectsClient, - ids: caseIds, - }); - - const subCaseIDs = subCasesForCaseIds.saved_objects.map((subCase) => subCase.id); - const commentsForSubCases = await caseService.getAllSubCaseComments({ - unsecuredSavedObjectsClient, - id: subCaseIDs, - }); - - const commentMapper = (commentSO: SavedObject) => - attachmentService.delete({ unsecuredSavedObjectsClient, attachmentId: commentSO.id }); - - const subCasesMapper = (subCaseSO: SavedObject) => - caseService.deleteSubCase(unsecuredSavedObjectsClient, subCaseSO.id); - - /** - * This shouldn't actually delete anything because - * all the comments should be deleted when comments are deleted - * per case ID. We also ensure that we don't too many concurrent deletions running. - */ - await pMap(commentsForSubCases.saved_objects, commentMapper, { - concurrency: MAX_CONCURRENT_SEARCHES, - }); - - await pMap(subCasesForCaseIds.saved_objects, subCasesMapper, { - concurrency: MAX_CONCURRENT_SEARCHES, - }); -} - /** * Deletes the specified cases and their attachments. * @@ -134,15 +91,6 @@ export async function deleteCases(ids: string[], clientArgs: CasesClientArgs): P concurrency: MAX_CONCURRENT_SEARCHES, }); - if (ENABLE_CASE_CONNECTOR) { - await deleteSubCases({ - attachmentService, - caseService, - unsecuredSavedObjectsClient, - caseIds: ids, - }); - } - await userActionService.bulkCreateCaseDeletion({ unsecuredSavedObjectsClient, cases: cases.saved_objects.map((caseInfo) => ({ diff --git a/x-pack/plugins/cases/server/client/cases/find.ts b/x-pack/plugins/cases/server/client/cases/find.ts index 4257dfce6d5e3..3e4bc47231d12 100644 --- a/x-pack/plugins/cases/server/client/cases/find.ts +++ b/x-pack/plugins/cases/server/client/cases/find.ts @@ -28,7 +28,7 @@ import { Operations } from '../../authorization'; import { CasesClientArgs } from '..'; /** - * Retrieves a case and optionally its comments and sub case comments. + * Retrieves a case and optionally its comments. * * @ignore */ @@ -52,7 +52,6 @@ export const find = async ( reporters: queryParams.reporters, sortByField: queryParams.sortField, status: queryParams.status, - caseType: queryParams.type, owner: queryParams.owner, }; @@ -61,7 +60,7 @@ export const find = async ( unsecuredSavedObjectsClient, caseOptions: { ...queryParams, - ...caseQueries.case, + ...caseQueries, searchFields: queryParams.searchFields != null ? Array.isArray(queryParams.searchFields) @@ -70,7 +69,6 @@ export const find = async ( : queryParams.searchFields, fields: includeFieldsRequiredForAuthentication(queryParams.fields), }, - subCaseOptions: caseQueries.subCase, }); ensureSavedObjectsAreAuthorized([...cases.casesMap.values()]); @@ -81,8 +79,7 @@ export const find = async ( const statusQuery = constructQueryOptions({ ...queryArgs, status, authorizationFilter }); return caseService.findCaseStatusStats({ unsecuredSavedObjectsClient, - caseOptions: statusQuery.case, - subCaseOptions: statusQuery.subCase, + caseOptions: statusQuery, ensureSavedObjectsAreAuthorized, }); }), diff --git a/x-pack/plugins/cases/server/client/cases/get.ts b/x-pack/plugins/cases/server/client/cases/get.ts index 0d0bcc7f78270..72d5ca2708d28 100644 --- a/x-pack/plugins/cases/server/client/cases/get.ts +++ b/x-pack/plugins/cases/server/client/cases/get.ts @@ -28,7 +28,6 @@ import { CasesByAlertIdRt, CaseAttributes, } from '../../../common/api'; -import { ENABLE_CASE_CONNECTOR } from '../../../common/constants'; import { createCaseError } from '../../common/error'; import { countAlertsForID, flattenCaseSavedObject } from '../../common/utils'; import { CasesClientArgs } from '..'; @@ -147,52 +146,24 @@ export interface GetParams { * Whether to include the attachments for a case in the response */ includeComments?: boolean; - /** - * Whether to include the attachments for all children of a case in the response - */ - includeSubCaseComments?: boolean; } /** - * Retrieves a case and optionally its comments and sub case comments. + * Retrieves a case and optionally its comments. * * @ignore */ export const get = async ( - { id, includeComments, includeSubCaseComments }: GetParams, + { id, includeComments }: GetParams, clientArgs: CasesClientArgs ): Promise => { const { unsecuredSavedObjectsClient, caseService, logger, authorization } = clientArgs; try { - if (!ENABLE_CASE_CONNECTOR && includeSubCaseComments) { - throw Boom.badRequest( - 'The `includeSubCaseComments` is not supported when the case connector feature is disabled' - ); - } - - let theCase: SavedObject; - let subCaseIds: string[] = []; - if (ENABLE_CASE_CONNECTOR) { - const [caseInfo, subCasesForCaseId] = await Promise.all([ - caseService.getCase({ - unsecuredSavedObjectsClient, - id, - }), - caseService.findSubCasesByCaseId({ - unsecuredSavedObjectsClient, - ids: [id], - }), - ]); - - theCase = caseInfo; - subCaseIds = subCasesForCaseId.saved_objects.map((so) => so.id); - } else { - theCase = await caseService.getCase({ - unsecuredSavedObjectsClient, - id, - }); - } + const theCase: SavedObject = await caseService.getCase({ + unsecuredSavedObjectsClient, + id, + }); await authorization.ensureAuthorized({ operation: Operations.getCase, @@ -203,7 +174,6 @@ export const get = async ( return CaseResponseRt.encode( flattenCaseSavedObject({ savedObject: theCase, - subCaseIds, }) ); } @@ -215,14 +185,12 @@ export const get = async ( sortField: 'created_at', sortOrder: 'asc', }, - includeSubCaseComments: ENABLE_CASE_CONNECTOR && includeSubCaseComments, }); return CaseResponseRt.encode( flattenCaseSavedObject({ savedObject: theCase, comments: theComments.saved_objects, - subCaseIds, totalComment: theComments.total, totalAlerts: countAlertsForID({ comments: theComments, id }), }) @@ -233,23 +201,17 @@ export const get = async ( }; /** - * Retrieves a case resolving its ID and optionally loading its comments and sub case comments. + * Retrieves a case resolving its ID and optionally loading its comments. * * @experimental */ export const resolve = async ( - { id, includeComments, includeSubCaseComments }: GetParams, + { id, includeComments }: GetParams, clientArgs: CasesClientArgs ): Promise => { const { unsecuredSavedObjectsClient, caseService, logger, authorization } = clientArgs; try { - if (!ENABLE_CASE_CONNECTOR && includeSubCaseComments) { - throw Boom.badRequest( - 'The `includeSubCaseComments` is not supported when the case connector feature is disabled' - ); - } - const { saved_object: resolvedSavedObject, ...resolveData @@ -268,21 +230,11 @@ export const resolve = async ( ], }); - let subCaseIds: string[] = []; - if (ENABLE_CASE_CONNECTOR) { - const subCasesForCaseId = await caseService.findSubCasesByCaseId({ - unsecuredSavedObjectsClient, - ids: [resolvedSavedObject.id], - }); - subCaseIds = subCasesForCaseId.saved_objects.map((so) => so.id); - } - if (!includeComments) { return CaseResolveResponseRt.encode({ ...resolveData, case: flattenCaseSavedObject({ savedObject: resolvedSavedObject, - subCaseIds, }), }); } @@ -294,14 +246,12 @@ export const resolve = async ( sortField: 'created_at', sortOrder: 'asc', }, - includeSubCaseComments: ENABLE_CASE_CONNECTOR && includeSubCaseComments, }); return CaseResolveResponseRt.encode({ ...resolveData, case: flattenCaseSavedObject({ savedObject: resolvedSavedObject, - subCaseIds, comments: theComments.saved_objects, totalComment: theComments.total, totalAlerts: countAlertsForID({ comments: theComments, id: resolvedSavedObject.id }), diff --git a/x-pack/plugins/cases/server/client/cases/mock.ts b/x-pack/plugins/cases/server/client/cases/mock.ts index 63170ad0957fa..69a5f2d3a587b 100644 --- a/x-pack/plugins/cases/server/client/cases/mock.ts +++ b/x-pack/plugins/cases/server/client/cases/mock.ts @@ -10,7 +10,6 @@ import { CommentType, ConnectorMappingsAttributes, CaseUserActionsResponse, - AssociationType, CommentResponseAlertsType, ConnectorTypes, Actions, @@ -32,7 +31,6 @@ const entity = { }; export const comment: CommentResponse = { - associationType: AssociationType.case, id: 'mock-comment-1', comment: 'Wow, good luck catching that bad meanie!', type: CommentType.user as const, @@ -55,7 +53,6 @@ export const comment: CommentResponse = { }; export const isolateCommentActions: CommentResponse = { - associationType: AssociationType.case, id: 'mock-action-comment-1', comment: 'Isolating this for investigation', type: CommentType.actions as const, @@ -87,7 +84,6 @@ export const isolateCommentActions: CommentResponse = { }; export const releaseCommentActions: CommentResponse = { - associationType: AssociationType.case, id: 'mock-action-comment-1', comment: 'Releasing this for investigation', type: CommentType.actions as const, @@ -119,7 +115,6 @@ export const releaseCommentActions: CommentResponse = { }; export const isolateCommentActionsMultipleTargets: CommentResponse = { - associationType: AssociationType.case, id: 'mock-action-comment-1', comment: 'Isolating this for investigation', type: CommentType.actions as const, @@ -155,7 +150,6 @@ export const isolateCommentActionsMultipleTargets: CommentResponse = { }; export const commentAlert: CommentResponse = { - associationType: AssociationType.case, id: 'mock-comment-1', alertId: 'alert-id-1', index: 'alert-index-1', @@ -191,12 +185,6 @@ export const commentAlertMultipleIds: CommentResponseAlertsType = { owner: SECURITY_SOLUTION_OWNER, }; -export const commentGeneratedAlert: CommentResponseAlertsType = { - ...commentAlertMultipleIds, - id: 'mock-comment-3', - type: CommentType.generatedAlert as const, -}; - export const defaultPipes = ['informationCreated']; export const basicParams: BasicParams = { description: 'a description', diff --git a/x-pack/plugins/cases/server/client/cases/push.ts b/x-pack/plugins/cases/server/client/cases/push.ts index 8775d89f22802..e68c67951d571 100644 --- a/x-pack/plugins/cases/server/client/cases/push.ts +++ b/x-pack/plugins/cases/server/client/cases/push.ts @@ -6,7 +6,7 @@ */ import Boom from '@hapi/boom'; -import { SavedObjectsFindResponse, SavedObject } from 'kibana/server'; +import { SavedObjectsFindResponse } from 'kibana/server'; import { ActionConnector, @@ -14,12 +14,9 @@ import { CaseResponse, CaseStatuses, ExternalServiceResponse, - CaseType, CasesConfigureAttributes, - CaseAttributes, ActionTypes, } from '../../../common/api'; -import { ENABLE_CASE_CONNECTOR } from '../../../common/constants'; import { createIncident, getCommentContextFromAttributes } from './utils'; import { createCaseError } from '../../common/error'; @@ -30,18 +27,14 @@ import { casesConnectors } from '../../connectors'; import { getAlerts } from '../alerts/get'; /** - * Returns true if the case should be closed based on the configuration settings and whether the case - * is a collection. Collections are not closable because we aren't allowing their status to be changed. - * In the future we could allow push to close all the sub cases of a collection but that's not currently supported. + * Returns true if the case should be closed based on the configuration settings. */ function shouldCloseByPush( - configureSettings: SavedObjectsFindResponse, - caseInfo: SavedObject + configureSettings: SavedObjectsFindResponse ): boolean { return ( configureSettings.total > 0 && - configureSettings.saved_objects[0].attributes.closure_type === 'close-by-pushing' && - caseInfo.attributes.type !== CaseType.collection + configureSettings.saved_objects[0].attributes.closure_type === 'close-by-pushing' ); } @@ -88,7 +81,6 @@ export const push = async ( casesClient.cases.get({ id: caseId, includeComments: true, - includeSubCaseComments: ENABLE_CASE_CONNECTOR, }), actionsClient.get({ id: connectorId }), casesClient.userActions.getAll({ caseId }), @@ -99,7 +91,6 @@ export const push = async ( operation: Operations.pushCase, }); - // We need to change the logic when we support subcases if (theCase?.status === CaseStatuses.closed) { throw Boom.conflict( `The ${theCase.title} case is closed. Pushing a closed case is not allowed.` @@ -163,7 +154,6 @@ export const push = async ( page: 1, perPage: theCase?.totalComment ?? 0, }, - includeSubCaseComments: ENABLE_CASE_CONNECTOR, }), ]); @@ -182,7 +172,7 @@ export const push = async ( external_url: externalServiceResponse.url, }; - const shouldMarkAsClosed = shouldCloseByPush(myCaseConfigure, myCase); + const shouldMarkAsClosed = shouldCloseByPush(myCaseConfigure); const [updatedCase, updatedComments] = await Promise.all([ caseService.patchCase({ diff --git a/x-pack/plugins/cases/server/client/cases/update.ts b/x-pack/plugins/cases/server/client/cases/update.ts index 23db7f36634ce..fa8319d37efd8 100644 --- a/x-pack/plugins/cases/server/client/cases/update.ts +++ b/x-pack/plugins/cases/server/client/cases/update.ts @@ -5,7 +5,6 @@ * 2.0. */ -import pMap from 'p-map'; import Boom from '@hapi/boom'; import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; @@ -21,14 +20,12 @@ import { import { nodeBuilder } from '@kbn/es-query'; import { - AssociationType, CasePatchRequest, CasesPatchRequest, CasesPatchRequestRt, CasesResponse, CasesResponseRt, CaseStatuses, - CaseType, CommentAttributes, CommentType, excess, @@ -38,9 +35,6 @@ import { import { CASE_COMMENT_SAVED_OBJECT, CASE_SAVED_OBJECT, - ENABLE_CASE_CONNECTOR, - MAX_CONCURRENT_SEARCHES, - SUB_CASE_SAVED_OBJECT, MAX_TITLE_LENGTH, } from '../../../common/constants'; @@ -51,62 +45,12 @@ import { createCaseError } from '../../common/error'; import { createAlertUpdateRequest, flattenCaseSavedObject, - isCommentRequestTypeAlertOrGenAlert, + isCommentRequestTypeAlert, } from '../../common/utils'; import { UpdateAlertRequest } from '../alerts/types'; import { CasesClientArgs } from '..'; import { Operations, OwnerEntity } from '../../authorization'; -/** - * Throws an error if any of the requests attempt to update a collection style cases' status field. - */ -function throwIfUpdateStatusOfCollection(requests: UpdateRequestWithOriginalCase[]) { - const requestsUpdatingStatusOfCollection = requests.filter( - ({ updateReq, originalCase }) => - updateReq.status !== undefined && originalCase.attributes.type === CaseType.collection - ); - - if (requestsUpdatingStatusOfCollection.length > 0) { - const ids = requestsUpdatingStatusOfCollection.map(({ updateReq }) => updateReq.id); - throw Boom.badRequest( - `Updating the status of a collection is not allowed ids: [${ids.join(', ')}]` - ); - } -} - -/** - * Throws an error if any of the requests attempt to update a collection style case to an individual one. - */ -function throwIfUpdateTypeCollectionToIndividual(requests: UpdateRequestWithOriginalCase[]) { - const requestsUpdatingTypeCollectionToInd = requests.filter( - ({ updateReq, originalCase }) => - updateReq.type === CaseType.individual && originalCase.attributes.type === CaseType.collection - ); - - if (requestsUpdatingTypeCollectionToInd.length > 0) { - const ids = requestsUpdatingTypeCollectionToInd.map(({ updateReq }) => updateReq.id); - throw Boom.badRequest( - `Converting a collection to an individual case is not allowed ids: [${ids.join(', ')}]` - ); - } -} - -/** - * Throws an error if any of the requests attempt to update the type of a case. - */ -function throwIfUpdateType(requests: UpdateRequestWithOriginalCase[]) { - const requestsUpdatingType = requests.filter(({ updateReq }) => updateReq.type !== undefined); - - if (requestsUpdatingType.length > 0) { - const ids = requestsUpdatingType.map(({ updateReq }) => updateReq.id); - throw Boom.badRequest( - `Updating the type of a case when sub cases are disabled is not allowed ids: [${ids.join( - ', ' - )}]` - ); - } -} - /** * Throws an error if any of the requests attempt to update the owner of a case. */ @@ -119,64 +63,6 @@ function throwIfUpdateOwner(requests: UpdateRequestWithOriginalCase[]) { } } -/** - * Throws an error if any of the requests attempt to update an individual style cases' type field to a collection - * when alerts are attached to the case. - */ -async function throwIfInvalidUpdateOfTypeWithAlerts({ - requests, - caseService, - unsecuredSavedObjectsClient, -}: { - requests: UpdateRequestWithOriginalCase[]; - caseService: CasesService; - unsecuredSavedObjectsClient: SavedObjectsClientContract; -}) { - const getAlertsForID = async ({ updateReq }: UpdateRequestWithOriginalCase) => { - const alerts = await caseService.getAllCaseComments({ - unsecuredSavedObjectsClient, - id: updateReq.id, - options: { - fields: [], - // there should never be generated alerts attached to an individual case but we'll check anyway - filter: nodeBuilder.or([ - nodeBuilder.is(`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, CommentType.alert), - nodeBuilder.is( - `${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, - CommentType.generatedAlert - ), - ]), - page: 1, - perPage: 1, - }, - }); - - return { id: updateReq.id, alerts }; - }; - - const requestsUpdatingTypeField = requests.filter( - ({ updateReq }) => updateReq.type === CaseType.collection - ); - const getAlertsMapper = async (caseToUpdate: UpdateRequestWithOriginalCase) => - getAlertsForID(caseToUpdate); - // Ensuring we don't too many concurrent get running. - const casesAlertTotals = await pMap(requestsUpdatingTypeField, getAlertsMapper, { - concurrency: MAX_CONCURRENT_SEARCHES, - }); - - // grab the cases that have at least one alert comment attached to them - const typeUpdateWithAlerts = casesAlertTotals.filter((caseInfo) => caseInfo.alerts.total > 0); - - if (typeUpdateWithAlerts.length > 0) { - const ids = typeUpdateWithAlerts.map((req) => req.id); - throw Boom.badRequest( - `Converting a case to a collection is not allowed when it has alert comments, ids: [${ids.join( - ', ' - )}]` - ); - } -} - /** * Throws an error if any of the requests updates a title and the length is over MAX_TITLE_LENGTH. */ @@ -200,7 +86,7 @@ function throwIfTitleIsInvalid(requests: UpdateRequestWithOriginalCase[]) { */ function getID( comment: SavedObject, - type: typeof CASE_SAVED_OBJECT | typeof SUB_CASE_SAVED_OBJECT + type: typeof CASE_SAVED_OBJECT ): string | undefined { return comment.references.find((ref) => ref.type === type)?.id; } @@ -223,80 +109,29 @@ async function getAlertComments({ return caseService.getAllCaseComments({ unsecuredSavedObjectsClient, id: idsOfCasesToSync, - includeSubCaseComments: true, options: { - filter: nodeBuilder.or([ - nodeBuilder.is(`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, CommentType.alert), - nodeBuilder.is(`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, CommentType.generatedAlert), - ]), + filter: nodeBuilder.is(`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, CommentType.alert), }, }); } /** - * Returns a map of sub case IDs to their status. This uses a group of alert comments to determine which sub cases should - * be retrieved. This is based on whether the comment is associated to a sub case. - */ -async function getSubCasesToStatus({ - totalAlerts, - caseService, - unsecuredSavedObjectsClient, -}: { - totalAlerts: SavedObjectsFindResponse; - caseService: CasesService; - unsecuredSavedObjectsClient: SavedObjectsClientContract; -}): Promise> { - const subCasesToRetrieve = totalAlerts.saved_objects.reduce((acc, alertComment) => { - if ( - isCommentRequestTypeAlertOrGenAlert(alertComment.attributes) && - alertComment.attributes.associationType === AssociationType.subCase - ) { - const id = getID(alertComment, SUB_CASE_SAVED_OBJECT); - if (id !== undefined) { - acc.add(id); - } - } - return acc; - }, new Set()); - - const subCases = await caseService.getSubCases({ - ids: Array.from(subCasesToRetrieve.values()), - unsecuredSavedObjectsClient, - }); - - return subCases.saved_objects.reduce((acc, subCase) => { - // log about the sub cases that we couldn't find - if (!subCase.error) { - acc.set(subCase.id, subCase.attributes.status); - } - return acc; - }, new Map()); -} - -/** - * Returns what status the alert comment should have based on whether it is associated to a case or sub case. + * Returns what status the alert comment should have based on whether it is associated to a case. */ function getSyncStatusForComment({ alertComment, casesToSyncToStatus, - subCasesToStatus, }: { alertComment: SavedObjectsFindResult; casesToSyncToStatus: Map; - subCasesToStatus: Map; }): CaseStatuses { - let status: CaseStatuses = CaseStatuses.open; - if (alertComment.attributes.associationType === AssociationType.case) { - const id = getID(alertComment, CASE_SAVED_OBJECT); - // We should log if we can't find the status - // attempt to get the case status from our cases to sync map if we found the ID otherwise default to open - status = - id !== undefined ? casesToSyncToStatus.get(id) ?? CaseStatuses.open : CaseStatuses.open; - } else if (alertComment.attributes.associationType === AssociationType.subCase) { - const id = getID(alertComment, SUB_CASE_SAVED_OBJECT); - status = id !== undefined ? subCasesToStatus.get(id) ?? CaseStatuses.open : CaseStatuses.open; + const id = getID(alertComment, CASE_SAVED_OBJECT); + + if (!id) { + return CaseStatuses.open; } - return status; + + return casesToSyncToStatus.get(id) ?? CaseStatuses.open; } /** @@ -322,36 +157,25 @@ async function updateAlerts({ const casesToSync = [...casesWithSyncSettingChangedToOn, ...casesWithStatusChangedAndSynced]; // build a map of case id to the status it has - // this will have collections in it but the alerts should be associated to sub cases and not collections so it shouldn't - // matter. const casesToSyncToStatus = casesToSync.reduce((acc, { updateReq, originalCase }) => { acc.set(updateReq.id, updateReq.status ?? originalCase.attributes.status ?? CaseStatuses.open); return acc; }, new Map()); - // get all the alerts for all the alert comments for all cases and collections. Collections themselves won't have any - // but their sub cases could + // get all the alerts for all the alert comments for all cases const totalAlerts = await getAlertComments({ casesToSync, caseService, unsecuredSavedObjectsClient, }); - // get a map of sub case id to the sub case status - const subCasesToStatus = await getSubCasesToStatus({ - totalAlerts, - unsecuredSavedObjectsClient, - caseService, - }); - // create an array of requests that indicate the id, index, and status to update an alert const alertsToUpdate = totalAlerts.saved_objects.reduce( (acc: UpdateAlertRequest[], alertComment) => { - if (isCommentRequestTypeAlertOrGenAlert(alertComment.attributes)) { + if (isCommentRequestTypeAlert(alertComment.attributes)) { const status = getSyncStatusForComment({ alertComment, casesToSyncToStatus, - subCasesToStatus, }); acc.push(...createAlertUpdateRequest({ comment: alertComment.attributes, status })); @@ -489,19 +313,8 @@ export const update = async ( throw Boom.notAcceptable('All update fields are identical to current version.'); } - if (!ENABLE_CASE_CONNECTOR) { - throwIfUpdateType(updateCases); - } - throwIfUpdateOwner(updateCases); throwIfTitleIsInvalid(updateCases); - throwIfUpdateStatusOfCollection(updateCases); - throwIfUpdateTypeCollectionToIndividual(updateCases); - await throwIfInvalidUpdateOfTypeWithAlerts({ - requests: updateCases, - caseService, - unsecuredSavedObjectsClient, - }); // eslint-disable-next-line @typescript-eslint/naming-convention const { username, full_name, email } = user; diff --git a/x-pack/plugins/cases/server/client/cases/utils.test.ts b/x-pack/plugins/cases/server/client/cases/utils.test.ts index 5aab972c8489e..664509ba6b03e 100644 --- a/x-pack/plugins/cases/server/client/cases/utils.test.ts +++ b/x-pack/plugins/cases/server/client/cases/utils.test.ts @@ -17,7 +17,6 @@ import { userActions, commentAlert, commentAlertMultipleIds, - commentGeneratedAlert, isolateCommentActions, releaseCommentActions, isolateCommentActionsMultipleTargets, @@ -641,11 +640,7 @@ describe('utils', () => { actionsClient: actionsMock, theCase: { ...theCase, - comments: [ - { ...commentObj, id: 'comment-user-1' }, - commentAlertMultipleIds, - commentGeneratedAlert, - ], + comments: [{ ...commentObj, id: 'comment-user-1' }, commentAlertMultipleIds], }, userActions, connector, @@ -661,7 +656,7 @@ describe('utils', () => { commentId: 'comment-user-1', }, { - comment: 'Elastic Alerts attached to the case: 4', + comment: 'Elastic Alerts attached to the case: 2', commentId: 'mock-id-1-total-alerts', }, ]); @@ -674,7 +669,7 @@ describe('utils', () => { ...theCase, comments: [ { ...commentObj, id: 'comment-user-1', pushed_at: '2019-11-25T21:55:00.177Z' }, - { ...commentGeneratedAlert, pushed_at: '2019-11-25T21:55:00.177Z' }, + { ...commentAlertMultipleIds, pushed_at: '2019-11-25T21:55:00.177Z' }, ], }, userActions, diff --git a/x-pack/plugins/cases/server/client/cases/utils.ts b/x-pack/plugins/cases/server/client/cases/utils.ts index edef1b2362b12..4c7e444c114ac 100644 --- a/x-pack/plugins/cases/server/client/cases/utils.ts +++ b/x-pack/plugins/cases/server/client/cases/utils.ts @@ -78,7 +78,7 @@ export const getLatestPushInfo = ( const getCommentContent = (comment: CommentResponse): string => { if (comment.type === CommentType.user) { return comment.comment; - } else if (comment.type === CommentType.alert || comment.type === CommentType.generatedAlert) { + } else if (comment.type === CommentType.alert) { const ids = getAlertIds(comment); return `Alert with ids ${ids.join(', ')} added to case`; } else if ( @@ -110,7 +110,7 @@ const getAlertsInfo = ( const res = comments?.reduce(({ totalComments, pushed, totalAlerts }, comment) => { - if (comment.type === CommentType.alert || comment.type === CommentType.generatedAlert) { + if (comment.type === CommentType.alert) { return { totalComments: totalComments + 1, pushed: comment.pushed_at != null ? pushed + 1 : pushed, @@ -379,7 +379,6 @@ export const getCommentContextFromAttributes = ( comment: attributes.comment, owner, }; - case CommentType.generatedAlert: case CommentType.alert: return { type: attributes.type, diff --git a/x-pack/plugins/cases/server/client/client.ts b/x-pack/plugins/cases/server/client/client.ts index f85667bee7bc3..fb111f267ddac 100644 --- a/x-pack/plugins/cases/server/client/client.ts +++ b/x-pack/plugins/cases/server/client/client.ts @@ -10,8 +10,6 @@ import { CasesSubClient, createCasesSubClient } from './cases/client'; import { AttachmentsSubClient, createAttachmentsSubClient } from './attachments/client'; import { UserActionsSubClient, createUserActionsSubClient } from './user_actions/client'; import { CasesClientInternal, createCasesClientInternal } from './client_internal'; -import { createSubCasesClient, SubCasesClient } from './sub_cases/client'; -import { ENABLE_CASE_CONNECTOR } from '../../common/constants'; import { ConfigureSubClient, createConfigurationSubClient } from './configure/client'; import { createStatsSubClient, StatsSubClient } from './stats/client'; import { createMetricsSubClient, MetricsSubClient } from './metrics/client'; @@ -24,7 +22,6 @@ export class CasesClient { private readonly _cases: CasesSubClient; private readonly _attachments: AttachmentsSubClient; private readonly _userActions: UserActionsSubClient; - private readonly _subCases: SubCasesClient; private readonly _configure: ConfigureSubClient; private readonly _stats: StatsSubClient; private readonly _metrics: MetricsSubClient; @@ -34,7 +31,6 @@ export class CasesClient { this._cases = createCasesSubClient(args, this, this._casesClientInternal); this._attachments = createAttachmentsSubClient(args, this, this._casesClientInternal); this._userActions = createUserActionsSubClient(args); - this._subCases = createSubCasesClient(args); this._configure = createConfigurationSubClient(args, this._casesClientInternal); this._stats = createStatsSubClient(args); this._metrics = createMetricsSubClient(args, this); @@ -61,18 +57,6 @@ export class CasesClient { return this._userActions; } - /** - * Retrieves an interface for interacting with the case as a connector entities. - * - * Currently this functionality is disabled and will throw an error if this function is called. - */ - public get subCases() { - if (!ENABLE_CASE_CONNECTOR) { - throw new Error('The case connector feature is disabled'); - } - return this._subCases; - } - /** * Retrieves an interface for interacting with the configuration of external connectors for the plugin entities. */ diff --git a/x-pack/plugins/cases/server/client/metrics/actions/actions.ts b/x-pack/plugins/cases/server/client/metrics/actions/actions.ts index d104ae212b83e..c700c3998e503 100644 --- a/x-pack/plugins/cases/server/client/metrics/actions/actions.ts +++ b/x-pack/plugins/cases/server/client/metrics/actions/actions.ts @@ -31,7 +31,6 @@ export class Actions extends AggregationHandler { const theCase = await casesClient.cases.get({ id: caseId, includeComments: false, - includeSubCaseComments: false, }); const { filter: authorizationFilter } = await authorization.getAuthorizationFilter( diff --git a/x-pack/plugins/cases/server/client/metrics/alerts/count.ts b/x-pack/plugins/cases/server/client/metrics/alerts/count.ts index 8e04b5fc42c85..10fb1b97b4511 100644 --- a/x-pack/plugins/cases/server/client/metrics/alerts/count.ts +++ b/x-pack/plugins/cases/server/client/metrics/alerts/count.ts @@ -27,7 +27,6 @@ export class AlertsCount extends BaseHandler { const theCase = await casesClient.cases.get({ id: caseId, includeComments: false, - includeSubCaseComments: false, }); const { filter: authorizationFilter } = await authorization.getAuthorizationFilter( diff --git a/x-pack/plugins/cases/server/client/metrics/lifespan.test.ts b/x-pack/plugins/cases/server/client/metrics/lifespan.test.ts index b14d96189006e..61b6c2ff3d1bd 100644 --- a/x-pack/plugins/cases/server/client/metrics/lifespan.test.ts +++ b/x-pack/plugins/cases/server/client/metrics/lifespan.test.ts @@ -193,7 +193,6 @@ function createStatusChangeSavedObject( action_id: '', case_id: '', comment_id: null, - sub_case_id: '', }, }; } diff --git a/x-pack/plugins/cases/server/client/metrics/test_utils/lifespan.ts b/x-pack/plugins/cases/server/client/metrics/test_utils/lifespan.ts index b8e8875ff4ecc..07b4248315435 100644 --- a/x-pack/plugins/cases/server/client/metrics/test_utils/lifespan.ts +++ b/x-pack/plugins/cases/server/client/metrics/test_utils/lifespan.ts @@ -32,7 +32,6 @@ export function createStatusChangeSavedObject( action_id: '', case_id: '', comment_id: null, - sub_case_id: '', }, }; } diff --git a/x-pack/plugins/cases/server/client/mocks.ts b/x-pack/plugins/cases/server/client/mocks.ts index bc601d084caef..1d0cf000018cb 100644 --- a/x-pack/plugins/cases/server/client/mocks.ts +++ b/x-pack/plugins/cases/server/client/mocks.ts @@ -14,7 +14,6 @@ import { ConfigureSubClient } from './configure/client'; import { CasesClientFactory } from './factory'; import { MetricsSubClient } from './metrics/client'; import { StatsSubClient } from './stats/client'; -import { SubCasesClient } from './sub_cases/client'; import { UserActionsSubClient } from './user_actions/client'; type CasesSubClientMock = jest.Mocked; @@ -65,17 +64,6 @@ const createUserActionsSubClientMock = (): UserActionsSubClientMock => { }; }; -type SubCasesClientMock = jest.Mocked; - -const createSubCasesClientMock = (): SubCasesClientMock => { - return { - delete: jest.fn(), - find: jest.fn(), - get: jest.fn(), - update: jest.fn(), - }; -}; - type ConfigureSubClientMock = jest.Mocked; const createConfigureSubClientMock = (): ConfigureSubClientMock => { @@ -99,7 +87,6 @@ export interface CasesClientMock extends CasesClient { cases: CasesSubClientMock; attachments: AttachmentsSubClientMock; userActions: UserActionsSubClientMock; - subCases: SubCasesClientMock; } export const createCasesClientMock = (): CasesClientMock => { @@ -107,7 +94,6 @@ export const createCasesClientMock = (): CasesClientMock => { cases: createCasesSubClientMock(), attachments: createAttachmentsSubClientMock(), userActions: createUserActionsSubClientMock(), - subCases: createSubCasesClientMock(), configure: createConfigureSubClientMock(), stats: createStatsSubClientMock(), metrics: createMetricsSubClientMock(), diff --git a/x-pack/plugins/cases/server/client/stats/client.ts b/x-pack/plugins/cases/server/client/stats/client.ts index a7716ba7a3da2..6cb945e0fead1 100644 --- a/x-pack/plugins/cases/server/client/stats/client.ts +++ b/x-pack/plugins/cases/server/client/stats/client.ts @@ -71,8 +71,7 @@ async function getStatusTotalsByType( }); return caseService.findCaseStatusStats({ unsecuredSavedObjectsClient, - caseOptions: statusQuery.case, - subCaseOptions: statusQuery.subCase, + caseOptions: statusQuery, ensureSavedObjectsAreAuthorized, }); }), diff --git a/x-pack/plugins/cases/server/client/sub_cases/client.ts b/x-pack/plugins/cases/server/client/sub_cases/client.ts deleted file mode 100644 index 8bb846d6b7a57..0000000000000 --- a/x-pack/plugins/cases/server/client/sub_cases/client.ts +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import pMap from 'p-map'; -import Boom from '@hapi/boom'; - -import { SavedObject } from 'kibana/server'; -import { - caseStatuses, - CommentAttributes, - SubCaseResponse, - SubCaseResponseRt, - SubCasesFindRequest, - SubCasesFindResponse, - SubCasesFindResponseRt, - SubCasesPatchRequest, -} from '../../../common/api'; -import { MAX_CONCURRENT_SEARCHES } from '../../../common/constants'; -import { CasesClientArgs } from '..'; -import { createCaseError } from '../../common/error'; -import { countAlertsForID, flattenSubCaseSavedObject, transformSubCases } from '../../common/utils'; -import { constructQueryOptions } from '../utils'; -import { defaultPage, defaultPerPage } from '../../routes/api'; -import { update } from './update'; -import { ISubCaseResponse, ISubCasesFindResponse, ISubCasesResponse } from '../typedoc_interfaces'; - -interface FindArgs { - /** - * The case ID for finding associated sub cases - */ - caseID: string; - /** - * Options for filtering the returned sub cases - */ - queryParams: SubCasesFindRequest; -} - -interface GetArgs { - /** - * A flag to include the attachments with the results - */ - includeComments: boolean; - /** - * The ID of the sub case to retrieve - */ - id: string; -} - -/** - * The API routes for interacting with sub cases. - * - * @public - */ -export interface SubCasesClient { - /** - * Deletes the specified entities and their attachments. - */ - delete(ids: string[]): Promise; - /** - * Retrieves the sub cases matching the search criteria. - */ - find(findArgs: FindArgs): Promise; - /** - * Retrieves a single sub case. - */ - get(getArgs: GetArgs): Promise; - /** - * Updates the specified sub cases to the new values included in the request. - */ - update(subCases: SubCasesPatchRequest): Promise; -} - -/** - * Creates a client for handling the different exposed API routes for interacting with sub cases. - * - * @ignore - */ -export function createSubCasesClient(clientArgs: CasesClientArgs): SubCasesClient { - return Object.freeze({ - delete: (ids: string[]) => deleteSubCase(ids, clientArgs), - find: (findArgs: FindArgs) => find(findArgs, clientArgs), - get: (getArgs: GetArgs) => get(getArgs, clientArgs), - update: (subCases: SubCasesPatchRequest) => update({ subCases, clientArgs }), - }); -} - -async function deleteSubCase(ids: string[], clientArgs: CasesClientArgs): Promise { - try { - const { unsecuredSavedObjectsClient, caseService, attachmentService } = clientArgs; - - const [comments, subCases] = await Promise.all([ - caseService.getAllSubCaseComments({ unsecuredSavedObjectsClient, id: ids }), - caseService.getSubCases({ unsecuredSavedObjectsClient, ids }), - ]); - - const subCaseErrors = subCases.saved_objects.filter((subCase) => subCase.error !== undefined); - - if (subCaseErrors.length > 0) { - throw Boom.notFound( - `These sub cases ${subCaseErrors - .map((c) => c.id) - .join(', ')} do not exist. Please check you have the correct ids.` - ); - } - - const deleteCommentMapper = async (comment: SavedObject) => - attachmentService.delete({ unsecuredSavedObjectsClient, attachmentId: comment.id }); - - const deleteSubCasesMapper = async (id: string) => - caseService.deleteSubCase(unsecuredSavedObjectsClient, id); - - // Ensuring we don't too many concurrent deletions running. - await pMap(comments.saved_objects, deleteCommentMapper, { - concurrency: MAX_CONCURRENT_SEARCHES, - }); - - await pMap(ids, deleteSubCasesMapper, { - concurrency: MAX_CONCURRENT_SEARCHES, - }); - } catch (error) { - throw createCaseError({ - message: `Failed to delete sub cases ids: ${JSON.stringify(ids)}: ${error}`, - error, - logger: clientArgs.logger, - }); - } -} - -async function find( - { caseID, queryParams }: FindArgs, - clientArgs: CasesClientArgs -): Promise { - try { - const { unsecuredSavedObjectsClient, caseService } = clientArgs; - - const ids = [caseID]; - const { subCase: subCaseQueryOptions } = constructQueryOptions({ - status: queryParams.status, - sortByField: queryParams.sortField, - }); - - const subCases = await caseService.findSubCasesGroupByCase({ - unsecuredSavedObjectsClient, - ids, - options: { - sortField: 'created_at', - page: defaultPage, - perPage: defaultPerPage, - ...queryParams, - ...subCaseQueryOptions, - }, - }); - - // casesStatuses are bounded by us. No need to limit concurrent calls. - const [open, inProgress, closed] = await Promise.all([ - ...caseStatuses.map((status) => { - const { subCase: statusQueryOptions } = constructQueryOptions({ - status, - sortByField: queryParams.sortField, - }); - return caseService.findSubCaseStatusStats({ - unsecuredSavedObjectsClient, - options: statusQueryOptions ?? {}, - ids, - }); - }), - ]); - - return SubCasesFindResponseRt.encode( - transformSubCases({ - page: subCases.page, - perPage: subCases.perPage, - total: subCases.total, - subCasesMap: subCases.subCasesMap, - open, - inProgress, - closed, - }) - ); - } catch (error) { - throw createCaseError({ - message: `Failed to find sub cases for case id: ${caseID}: ${error}`, - error, - logger: clientArgs.logger, - }); - } -} - -async function get( - { includeComments, id }: GetArgs, - clientArgs: CasesClientArgs -): Promise { - try { - const { unsecuredSavedObjectsClient, caseService } = clientArgs; - - const subCase = await caseService.getSubCase({ - unsecuredSavedObjectsClient, - id, - }); - - if (!includeComments) { - return SubCaseResponseRt.encode( - flattenSubCaseSavedObject({ - savedObject: subCase, - }) - ); - } - - const theComments = await caseService.getAllSubCaseComments({ - unsecuredSavedObjectsClient, - id, - options: { - sortField: 'created_at', - sortOrder: 'asc', - }, - }); - - return SubCaseResponseRt.encode( - flattenSubCaseSavedObject({ - savedObject: subCase, - comments: theComments.saved_objects, - totalComment: theComments.total, - totalAlerts: countAlertsForID({ - comments: theComments, - id, - }), - }) - ); - } catch (error) { - throw createCaseError({ - message: `Failed to get sub case id: ${id}: ${error}`, - error, - logger: clientArgs.logger, - }); - } -} diff --git a/x-pack/plugins/cases/server/client/sub_cases/update.ts b/x-pack/plugins/cases/server/client/sub_cases/update.ts deleted file mode 100644 index fa5ef4ec7f342..0000000000000 --- a/x-pack/plugins/cases/server/client/sub_cases/update.ts +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import Boom from '@hapi/boom'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { fold } from 'fp-ts/lib/Either'; -import { identity } from 'fp-ts/lib/function'; -import { - SavedObjectsClientContract, - SavedObject, - SavedObjectsFindResponse, - Logger, -} from 'kibana/server'; - -import { nodeBuilder } from '@kbn/es-query'; -import { AlertService, CasesService } from '../../services'; -import { - CaseStatuses, - CommentAttributes, - CommentType, - excess, - SubCaseAttributes, - SubCasePatchRequest, - SubCaseResponse, - SubCasesPatchRequest, - SubCasesPatchRequestRt, - SubCasesResponse, - SubCasesResponseRt, - throwErrors, - User, - CaseAttributes, -} from '../../../common/api'; -import { CASE_COMMENT_SAVED_OBJECT, SUB_CASE_SAVED_OBJECT } from '../../../common/constants'; -import { getCaseToUpdate } from '../utils'; -import { createCaseError } from '../../common/error'; -import { - createAlertUpdateRequest, - isCommentRequestTypeAlertOrGenAlert, - flattenSubCaseSavedObject, -} from '../../common/utils'; -import { UpdateAlertRequest } from '../../client/alerts/types'; -import { CasesClientArgs } from '../types'; - -function checkNonExistingOrConflict( - toUpdate: SubCasePatchRequest[], - fromStorage: Map> -) { - const nonExistingSubCases: SubCasePatchRequest[] = []; - const conflictedSubCases: SubCasePatchRequest[] = []; - for (const subCaseToUpdate of toUpdate) { - const bulkEntry = fromStorage.get(subCaseToUpdate.id); - - if (bulkEntry && bulkEntry.error) { - nonExistingSubCases.push(subCaseToUpdate); - } - - if (!bulkEntry || bulkEntry.version !== subCaseToUpdate.version) { - conflictedSubCases.push(subCaseToUpdate); - } - } - - if (nonExistingSubCases.length > 0) { - throw Boom.notFound( - `These sub cases ${nonExistingSubCases - .map((c) => c.id) - .join(', ')} do not exist. Please check you have the correct ids.` - ); - } - - if (conflictedSubCases.length > 0) { - throw Boom.conflict( - `These sub cases ${conflictedSubCases - .map((c) => c.id) - .join(', ')} has been updated. Please refresh before saving additional updates.` - ); - } -} - -interface GetParentIDsResult { - ids: string[]; - parentIDToSubID: Map; -} - -function getParentIDs({ - subCasesMap, - subCaseIDs, -}: { - subCasesMap: Map>; - subCaseIDs: string[]; -}): GetParentIDsResult { - return subCaseIDs.reduce( - (acc, id) => { - const subCase = subCasesMap.get(id); - if (subCase && subCase.references.length > 0) { - const parentID = subCase.references[0].id; - acc.ids.push(parentID); - let subIDs = acc.parentIDToSubID.get(parentID); - if (subIDs === undefined) { - subIDs = []; - } - subIDs.push(id); - acc.parentIDToSubID.set(parentID, subIDs); - } - return acc; - }, - { ids: [], parentIDToSubID: new Map() } - ); -} - -async function getParentCases({ - caseService, - unsecuredSavedObjectsClient, - subCaseIDs, - subCasesMap, -}: { - caseService: CasesService; - unsecuredSavedObjectsClient: SavedObjectsClientContract; - subCaseIDs: string[]; - subCasesMap: Map>; -}): Promise>> { - const parentIDInfo = getParentIDs({ subCaseIDs, subCasesMap }); - - const parentCases = await caseService.getCases({ - unsecuredSavedObjectsClient, - caseIds: parentIDInfo.ids, - }); - - const parentCaseErrors = parentCases.saved_objects.filter((so) => so.error !== undefined); - - if (parentCaseErrors.length > 0) { - throw Boom.badRequest( - `Unable to find parent cases: ${parentCaseErrors - .map((c) => c.id) - .join(', ')} for sub cases: ${subCaseIDs.join(', ')}` - ); - } - - return parentCases.saved_objects.reduce((acc, so) => { - const subCaseIDsWithParent = parentIDInfo.parentIDToSubID.get(so.id); - subCaseIDsWithParent?.forEach((subCaseId) => { - acc.set(subCaseId, so); - }); - return acc; - }, new Map>()); -} - -function getValidUpdateRequests( - toUpdate: SubCasePatchRequest[], - subCasesMap: Map> -): SubCasePatchRequest[] { - const validatedSubCaseAttributes: SubCasePatchRequest[] = toUpdate.map((updateCase) => { - const currentCase = subCasesMap.get(updateCase.id); - return currentCase != null - ? getCaseToUpdate(currentCase.attributes, { - ...updateCase, - }) - : { id: updateCase.id, version: updateCase.version }; - }); - - return validatedSubCaseAttributes.filter((updateCase: SubCasePatchRequest) => { - const { id, version, ...updateCaseAttributes } = updateCase; - return Object.keys(updateCaseAttributes).length > 0; - }); -} - -/** - * Get the id from a reference in a comment for a sub case - */ -function getID(comment: SavedObject): string | undefined { - return comment.references.find((ref) => ref.type === SUB_CASE_SAVED_OBJECT)?.id; -} - -/** - * Get all the alert comments for a set of sub cases - */ -async function getAlertComments({ - subCasesToSync, - caseService, - unsecuredSavedObjectsClient, -}: { - subCasesToSync: SubCasePatchRequest[]; - caseService: CasesService; - unsecuredSavedObjectsClient: SavedObjectsClientContract; -}): Promise> { - const ids = subCasesToSync.map((subCase) => subCase.id); - return caseService.getAllSubCaseComments({ - unsecuredSavedObjectsClient, - id: ids, - options: { - filter: nodeBuilder.or([ - nodeBuilder.is(`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, CommentType.alert), - nodeBuilder.is(`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, CommentType.generatedAlert), - ]), - }, - }); -} - -/** - * Updates the status of alerts for the specified sub cases. - */ -async function updateAlerts({ - caseService, - unsecuredSavedObjectsClient, - alertsService, - logger, - subCasesToSync, -}: { - caseService: CasesService; - unsecuredSavedObjectsClient: SavedObjectsClientContract; - alertsService: AlertService; - logger: Logger; - subCasesToSync: SubCasePatchRequest[]; -}) { - try { - const subCasesToSyncMap = subCasesToSync.reduce((acc, subCase) => { - acc.set(subCase.id, subCase); - return acc; - }, new Map()); - // get all the alerts for all sub cases that need to be synced - const totalAlerts = await getAlertComments({ - caseService, - unsecuredSavedObjectsClient, - subCasesToSync, - }); - // create a map of the status (open, closed, etc) to alert info that needs to be updated - const alertsToUpdate = totalAlerts.saved_objects.reduce( - (acc: UpdateAlertRequest[], alertComment) => { - if (isCommentRequestTypeAlertOrGenAlert(alertComment.attributes)) { - const id = getID(alertComment); - const status = - id !== undefined - ? subCasesToSyncMap.get(id)?.status ?? CaseStatuses.open - : CaseStatuses.open; - - acc.push(...createAlertUpdateRequest({ comment: alertComment.attributes, status })); - } - return acc; - }, - [] - ); - - await alertsService.updateAlertsStatus(alertsToUpdate); - } catch (error) { - throw createCaseError({ - message: `Failed to update alert status while updating sub cases: ${JSON.stringify( - subCasesToSync - )}: ${error}`, - logger, - error, - }); - } -} - -/** - * Handles updating the fields in a sub case. - */ -export async function update({ - subCases, - clientArgs, -}: { - subCases: SubCasesPatchRequest; - clientArgs: CasesClientArgs; -}): Promise { - const query = pipe( - excess(SubCasesPatchRequestRt).decode(subCases), - fold(throwErrors(Boom.badRequest), identity) - ); - - try { - const { unsecuredSavedObjectsClient, user, caseService, userActionService, alertsService } = - clientArgs; - - const bulkSubCases = await caseService.getSubCases({ - unsecuredSavedObjectsClient, - ids: query.subCases.map((q) => q.id), - }); - - const subCasesMap = bulkSubCases.saved_objects.reduce((acc, so) => { - acc.set(so.id, so); - return acc; - }, new Map>()); - - checkNonExistingOrConflict(query.subCases, subCasesMap); - - const nonEmptySubCaseRequests = getValidUpdateRequests(query.subCases, subCasesMap); - - if (nonEmptySubCaseRequests.length <= 0) { - throw Boom.notAcceptable('All update fields are identical to current version.'); - } - - const subIDToParentCase = await getParentCases({ - unsecuredSavedObjectsClient, - caseService, - subCaseIDs: nonEmptySubCaseRequests.map((subCase) => subCase.id), - subCasesMap, - }); - - const updatedAt = new Date().toISOString(); - const updatedCases = await caseService.patchSubCases({ - unsecuredSavedObjectsClient, - subCases: nonEmptySubCaseRequests.map((thisCase) => { - const { id: subCaseId, version, ...updateSubCaseAttributes } = thisCase; - let closedInfo: { closed_at: string | null; closed_by: User | null } = { - closed_at: null, - closed_by: null, - }; - - if ( - updateSubCaseAttributes.status && - updateSubCaseAttributes.status === CaseStatuses.closed - ) { - closedInfo = { - closed_at: updatedAt, - closed_by: user, - }; - } else if ( - updateSubCaseAttributes.status && - (updateSubCaseAttributes.status === CaseStatuses.open || - updateSubCaseAttributes.status === CaseStatuses['in-progress']) - ) { - closedInfo = { - closed_at: null, - closed_by: null, - }; - } - return { - subCaseId, - updatedAttributes: { - ...updateSubCaseAttributes, - ...closedInfo, - updated_at: updatedAt, - updated_by: user, - }, - version, - }; - }), - }); - - const subCasesToSyncAlertsFor = nonEmptySubCaseRequests.filter((subCaseToUpdate) => { - const storedSubCase = subCasesMap.get(subCaseToUpdate.id); - const parentCase = subIDToParentCase.get(subCaseToUpdate.id); - return ( - storedSubCase !== undefined && - subCaseToUpdate.status !== undefined && - storedSubCase.attributes.status !== subCaseToUpdate.status && - parentCase?.attributes.settings.syncAlerts - ); - }); - - await updateAlerts({ - caseService, - unsecuredSavedObjectsClient, - alertsService, - subCasesToSync: subCasesToSyncAlertsFor, - logger: clientArgs.logger, - }); - - const returnUpdatedSubCases = updatedCases.saved_objects.reduce( - (acc, updatedSO) => { - const originalSubCase = subCasesMap.get(updatedSO.id); - if (originalSubCase) { - acc.push( - flattenSubCaseSavedObject({ - savedObject: { - ...originalSubCase, - ...updatedSO, - attributes: { ...originalSubCase.attributes, ...updatedSO.attributes }, - references: originalSubCase.references, - version: updatedSO.version ?? originalSubCase.version, - }, - }) - ); - } - return acc; - }, - [] - ); - - await userActionService.bulkCreateUpdateCase({ - unsecuredSavedObjectsClient, - originalCases: bulkSubCases.saved_objects, - updatedCases: updatedCases.saved_objects, - user, - }); - - return SubCasesResponseRt.encode(returnUpdatedSubCases); - } catch (error) { - const idVersions = query.subCases.map((subCase) => ({ - id: subCase.id, - version: subCase.version, - })); - throw createCaseError({ - message: `Failed to update sub cases: ${JSON.stringify(idVersions)}: ${error}`, - error, - logger: clientArgs.logger, - }); - } -} diff --git a/x-pack/plugins/cases/server/client/typedoc_interfaces.ts b/x-pack/plugins/cases/server/client/typedoc_interfaces.ts index b1dd4c47219d8..22fb20f54321b 100644 --- a/x-pack/plugins/cases/server/client/typedoc_interfaces.ts +++ b/x-pack/plugins/cases/server/client/typedoc_interfaces.ts @@ -27,9 +27,6 @@ import { CasesResponse, CaseUserActionsResponse, CommentsResponse, - SubCaseResponse, - SubCasesFindResponse, - SubCasesResponse, } from '../../common/api'; /** @@ -52,8 +49,4 @@ export interface ICasesConfigurePatch extends CasesConfigurePatch {} export interface ICommentsResponse extends CommentsResponse {} export interface IAllCommentsResponse extends AllCommentsResponse {} -export interface ISubCasesFindResponse extends SubCasesFindResponse {} -export interface ISubCaseResponse extends SubCaseResponse {} -export interface ISubCasesResponse extends SubCasesResponse {} - export interface ICaseUserActionsResponse extends CaseUserActionsResponse {} diff --git a/x-pack/plugins/cases/server/client/user_actions/client.ts b/x-pack/plugins/cases/server/client/user_actions/client.ts index 1e2fe8d4f4fca..f2e5edf255812 100644 --- a/x-pack/plugins/cases/server/client/user_actions/client.ts +++ b/x-pack/plugins/cases/server/client/user_actions/client.ts @@ -17,10 +17,6 @@ export interface UserActionGet { * The ID of the case */ caseId: string; - /** - * If specified then a sub case will be used for finding all the user actions - */ - subCaseId?: string; } /** diff --git a/x-pack/plugins/cases/server/client/user_actions/get.test.ts b/x-pack/plugins/cases/server/client/user_actions/get.test.ts deleted file mode 100644 index c735c7d41dfcf..0000000000000 --- a/x-pack/plugins/cases/server/client/user_actions/get.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { CaseUserActionResponse } from '../../../common/api'; -import { SUB_CASE_SAVED_OBJECT } from '../../../common/constants'; -import { SUB_CASE_REF_NAME } from '../../common/constants'; -import { extractAttributesWithoutSubCases } from './get'; - -describe('get', () => { - describe('extractAttributesWithoutSubCases', () => { - it('returns an empty array when given an empty array', () => { - expect( - extractAttributesWithoutSubCases({ ...getFindResponseFields(), saved_objects: [] }) - ).toEqual([]); - }); - - it('filters out saved objects with a sub case reference', () => { - expect( - extractAttributesWithoutSubCases({ - ...getFindResponseFields(), - saved_objects: [ - { - type: 'a', - references: [{ name: SUB_CASE_REF_NAME, type: SUB_CASE_SAVED_OBJECT, id: '1' }], - id: 'b', - score: 0, - attributes: {} as CaseUserActionResponse, - }, - ], - }) - ).toEqual([]); - }); - - it('filters out saved objects with a sub case reference with other references', () => { - expect( - extractAttributesWithoutSubCases({ - ...getFindResponseFields(), - saved_objects: [ - { - type: 'a', - references: [ - { name: SUB_CASE_REF_NAME, type: SUB_CASE_SAVED_OBJECT, id: '1' }, - { name: 'a', type: 'b', id: '5' }, - ], - id: 'b', - score: 0, - attributes: {} as CaseUserActionResponse, - }, - ], - }) - ).toEqual([]); - }); - - it('keeps saved objects that do not have a sub case reference', () => { - expect( - extractAttributesWithoutSubCases({ - ...getFindResponseFields(), - saved_objects: [ - { - type: 'a', - references: [ - { name: SUB_CASE_REF_NAME, type: 'awesome', id: '1' }, - { name: 'a', type: 'b', id: '5' }, - ], - id: 'b', - score: 0, - attributes: { field: '1' } as unknown as CaseUserActionResponse, - }, - ], - }) - ).toEqual([{ field: '1' }]); - }); - - it('filters multiple saved objects correctly', () => { - expect( - extractAttributesWithoutSubCases({ - ...getFindResponseFields(), - saved_objects: [ - { - type: 'a', - references: [ - { name: SUB_CASE_REF_NAME, type: 'awesome', id: '1' }, - { name: 'a', type: 'b', id: '5' }, - ], - id: 'b', - score: 0, - attributes: { field: '2' } as unknown as CaseUserActionResponse, - }, - { - type: 'a', - references: [{ name: SUB_CASE_REF_NAME, type: SUB_CASE_SAVED_OBJECT, id: '1' }], - id: 'b', - score: 0, - attributes: { field: '1' } as unknown as CaseUserActionResponse, - }, - ], - }) - ).toEqual([{ field: '2' }]); - }); - }); -}); - -const getFindResponseFields = () => ({ page: 1, per_page: 1, total: 0 }); diff --git a/x-pack/plugins/cases/server/client/user_actions/get.ts b/x-pack/plugins/cases/server/client/user_actions/get.ts index 0d5ee29529f83..9b10d9df2b9a6 100644 --- a/x-pack/plugins/cases/server/client/user_actions/get.ts +++ b/x-pack/plugins/cases/server/client/user_actions/get.ts @@ -5,33 +5,27 @@ * 2.0. */ -import { SavedObjectReference, SavedObjectsFindResponse } from 'kibana/server'; +import { SavedObjectsFindResponse } from 'kibana/server'; import { CaseUserActionsResponse, CaseUserActionsResponseRt, CaseUserActionResponse, } from '../../../common/api'; -import { SUB_CASE_SAVED_OBJECT } from '../../../common/constants'; import { createCaseError } from '../../common/error'; -import { checkEnabledCaseConnectorOrThrow } from '../../common/utils'; -import { SUB_CASE_REF_NAME } from '../../common/constants'; import { CasesClientArgs } from '..'; import { Operations } from '../../authorization'; import { UserActionGet } from './client'; export const get = async ( - { caseId, subCaseId }: UserActionGet, + { caseId }: UserActionGet, clientArgs: CasesClientArgs ): Promise => { const { unsecuredSavedObjectsClient, userActionService, logger, authorization } = clientArgs; try { - checkEnabledCaseConnectorOrThrow(subCaseId); - const userActions = await userActionService.getAll({ unsecuredSavedObjectsClient, caseId, - subCaseId, }); await authorization.ensureAuthorized({ @@ -42,33 +36,18 @@ export const get = async ( operation: Operations.getUserActions, }); - const resultsToEncode = - subCaseId == null - ? extractAttributesWithoutSubCases(userActions) - : extractAttributes(userActions); + const resultsToEncode = extractAttributes(userActions); return CaseUserActionsResponseRt.encode(resultsToEncode); } catch (error) { throw createCaseError({ - message: `Failed to retrieve user actions case id: ${caseId} sub case id: ${subCaseId}: ${error}`, + message: `Failed to retrieve user actions case id: ${caseId}: ${error}`, error, logger, }); } }; -export function extractAttributesWithoutSubCases( - userActions: SavedObjectsFindResponse -): CaseUserActionsResponse { - // exclude user actions relating to sub cases from the results - const hasSubCaseReference = (references: SavedObjectReference[]) => - references.find((ref) => ref.type === SUB_CASE_SAVED_OBJECT && ref.name === SUB_CASE_REF_NAME); - - return userActions.saved_objects - .filter((so) => !hasSubCaseReference(so.references)) - .map((so) => so.attributes); -} - function extractAttributes( userActions: SavedObjectsFindResponse ): CaseUserActionsResponse { diff --git a/x-pack/plugins/cases/server/client/utils.test.ts b/x-pack/plugins/cases/server/client/utils.test.ts index 8089990ff89ff..4db98f7618715 100644 --- a/x-pack/plugins/cases/server/client/utils.test.ts +++ b/x-pack/plugins/cases/server/client/utils.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CaseConnector, CaseType, ConnectorTypes } from '../../common/api'; +import { CaseConnector, ConnectorTypes } from '../../common/api'; import { newCase } from '../routes/api/__mocks__/request_responses'; import { transformNewCase } from '../common/utils'; import { sortToSnake } from './utils'; @@ -55,7 +55,7 @@ describe('utils', () => { }; it('transform correctly', () => { const myCase = { - newCase: { ...newCase, type: CaseType.individual, connector }, + newCase: { ...newCase, connector }, user: { email: 'elastic@elastic.co', full_name: 'Elastic', @@ -97,7 +97,6 @@ describe('utils', () => { "case", ], "title": "My new case", - "type": "individual", "updated_at": null, "updated_by": null, } diff --git a/x-pack/plugins/cases/server/client/utils.ts b/x-pack/plugins/cases/server/client/utils.ts index a29e52b026a27..24f661b5f41fe 100644 --- a/x-pack/plugins/cases/server/client/utils.ts +++ b/x-pack/plugins/cases/server/client/utils.ts @@ -13,13 +13,12 @@ import { identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; import { nodeBuilder, fromKueryExpression, KueryNode } from '@kbn/es-query'; -import { CASE_SAVED_OBJECT, SUB_CASE_SAVED_OBJECT } from '../../common/constants'; +import { CASE_SAVED_OBJECT } from '../../common/constants'; import { OWNER_FIELD, AlertCommentRequestRt, ActionsCommentRequestRt, CaseStatuses, - CaseType, CommentRequest, ContextTypeUserRt, excess, @@ -28,7 +27,7 @@ import { import { combineFilterWithAuthorizationFilter } from '../authorization/utils'; import { getIDsAndIndicesAsArrays, - isCommentRequestTypeAlertOrGenAlert, + isCommentRequestTypeAlert, isCommentRequestTypeUser, isCommentRequestTypeActions, } from '../common/utils'; @@ -39,7 +38,7 @@ export const decodeCommentRequest = (comment: CommentRequest) => { pipe(excess(ContextTypeUserRt).decode(comment), fold(throwErrors(badRequest), identity)); } else if (isCommentRequestTypeActions(comment)) { pipe(excess(ActionsCommentRequestRt).decode(comment), fold(throwErrors(badRequest), identity)); - } else if (isCommentRequestTypeAlertOrGenAlert(comment)) { + } else if (isCommentRequestTypeAlert(comment)) { pipe(excess(AlertCommentRequestRt).decode(comment), fold(throwErrors(badRequest), identity)); const { ids, indices } = getIDsAndIndicesAsArrays(comment); @@ -90,7 +89,7 @@ export const decodeCommentRequest = (comment: CommentRequest) => { * Return the alert IDs from the comment if it is an alert style comment. Otherwise return an empty array. */ export const getAlertIds = (comment: CommentRequest): string[] => { - if (isCommentRequestTypeAlertOrGenAlert(comment)) { + if (isCommentRequestTypeAlert(comment)) { return Array.isArray(comment.alertId) ? comment.alertId : [comment.alertId]; } return []; @@ -184,38 +183,11 @@ export function stringToKueryNode(expression?: string): KueryNode | undefined { return fromKueryExpression(expression); } -/** - * Constructs the filters used for finding cases and sub cases. - * There are a few scenarios that this function tries to handle when constructing the filters used for finding cases - * and sub cases. - * - * Scenario 1: - * Type == Individual - * If the API request specifies that it wants only individual cases (aka not collections) then we need to add that - * specific filter when call the saved objects find api. This will filter out any collection cases. - * - * Scenario 2: - * Type == collection - * If the API request specifies that it only wants collection cases (cases that have sub cases) then we need to add - * the filter for collections AND we need to ignore any status filter for the case find call. This is because a - * collection's status is no longer relevant when it has sub cases. The user cannot change the status for a collection - * only for its sub cases. The status filter will be applied to the find request when looking for sub cases. - * - * Scenario 3: - * No Type is specified - * If the API request does not want to filter on type but instead get both collections and regular individual cases then - * we need to find all cases that match the other filter criteria and sub cases. To do this we construct the following query: - * - * ((status == some_status and type === individual) or type == collection) and (tags == blah) and (reporter == yo) - * This forces us to honor the status request for individual cases but gets us ALL collection cases that match the other - * filter criteria. When we search for sub cases we will use that status filter in that find call as well. - */ export const constructQueryOptions = ({ tags, reporters, status, sortByField, - caseType, owner, authorizationFilter, }: { @@ -223,10 +195,9 @@ export const constructQueryOptions = ({ reporters?: string | string[]; status?: CaseStatuses; sortByField?: string; - caseType?: CaseType; owner?: string | string[]; authorizationFilter?: KueryNode; -}): { case: SavedObjectFindOptionsKueryNode; subCase?: SavedObjectFindOptionsKueryNode } => { +}): SavedObjectFindOptionsKueryNode => { const kueryNodeExists = (filter: KueryNode | null | undefined): filter is KueryNode => filter != null; @@ -239,108 +210,18 @@ export const constructQueryOptions = ({ const sortField = sortToSnake(sortByField); const ownerFilter = buildFilter({ filters: owner ?? [], field: OWNER_FIELD, operator: 'or' }); - switch (caseType) { - case CaseType.individual: { - // The cases filter will result in this structure "status === oh and (type === individual) and (tags === blah) and (reporter === yo)" - // The subCase filter will be undefined because we don't need to find sub cases if type === individual - - // We do not want to support multiple type's being used, so force it to be a single filter value - const typeFilter = nodeBuilder.is( - `${CASE_SAVED_OBJECT}.attributes.type`, - CaseType.individual - ); - - const filters: KueryNode[] = [typeFilter, tagsFilter, reportersFilter, ownerFilter].filter( - kueryNodeExists - ); + const statusFilter = status != null ? addStatusFilter({ status }) : undefined; - const caseFilters = - status != null - ? addStatusFilter({ - status, - appendFilter: filters.length > 1 ? nodeBuilder.and(filters) : filters[0], - }) - : undefined; - - return { - case: { - filter: combineFilterWithAuthorizationFilter(caseFilters, authorizationFilter), - sortField, - }, - }; - } - case CaseType.collection: { - // The cases filter will result in this structure "(type == parent) and (tags == blah) and (reporter == yo)" - // The sub case filter will use the query.status if it exists - const typeFilter = nodeBuilder.is( - `${CASE_SAVED_OBJECT}.attributes.type`, - CaseType.collection - ); - - const filters: KueryNode[] = [typeFilter, tagsFilter, reportersFilter, ownerFilter].filter( - kueryNodeExists - ); - const caseFilters = filters.length > 1 ? nodeBuilder.and(filters) : filters[0]; - const subCaseFilters = - status != null ? addStatusFilter({ status, type: SUB_CASE_SAVED_OBJECT }) : undefined; - - return { - case: { - filter: combineFilterWithAuthorizationFilter(caseFilters, authorizationFilter), - sortField, - }, - subCase: { - filter: combineFilterWithAuthorizationFilter(subCaseFilters, authorizationFilter), - sortField, - }, - }; - } - default: { - /** - * In this scenario no type filter was sent, so we want to honor the status filter if one exists. - * To construct the filter and honor the status portion we need to find all individual cases that - * have that particular status. We also need to find cases that have sub cases but we want to ignore the - * case collection's status because it is not relevant. We only care about the status of the sub cases if the - * case is a collection. - * - * The cases filter will result in this structure "((status == open and type === individual) or type == parent) and (tags == blah) and (reporter == yo)" - * The sub case filter will use the query.status if it exists - */ - const typeIndividual = nodeBuilder.is( - `${CASE_SAVED_OBJECT}.attributes.type`, - CaseType.individual - ); - const typeParent = nodeBuilder.is( - `${CASE_SAVED_OBJECT}.attributes.type`, - CaseType.collection - ); + const filters: KueryNode[] = [statusFilter, tagsFilter, reportersFilter, ownerFilter].filter( + kueryNodeExists + ); - const statusFilter = - status != null - ? nodeBuilder.and([addStatusFilter({ status }), typeIndividual]) - : typeIndividual; - const statusAndType = nodeBuilder.or([statusFilter, typeParent]); + const caseFilters = filters.length > 1 ? nodeBuilder.and(filters) : filters[0]; - const filters: KueryNode[] = [statusAndType, tagsFilter, reportersFilter, ownerFilter].filter( - kueryNodeExists - ); - - const caseFilters = filters.length > 1 ? nodeBuilder.and(filters) : filters[0]; - const subCaseFilters = - status != null ? addStatusFilter({ status, type: SUB_CASE_SAVED_OBJECT }) : undefined; - - return { - case: { - filter: combineFilterWithAuthorizationFilter(caseFilters, authorizationFilter), - sortField, - }, - subCase: { - filter: combineFilterWithAuthorizationFilter(subCaseFilters, authorizationFilter), - sortField, - }, - }; - } - } + return { + filter: combineFilterWithAuthorizationFilter(caseFilters, authorizationFilter), + sortField, + }; }; interface CompareArrays { diff --git a/x-pack/plugins/cases/server/common/constants.ts b/x-pack/plugins/cases/server/common/constants.ts index db55ea8d77b5a..d782284cf2856 100644 --- a/x-pack/plugins/cases/server/common/constants.ts +++ b/x-pack/plugins/cases/server/common/constants.ts @@ -5,11 +5,7 @@ * 2.0. */ -import { - CASE_COMMENT_SAVED_OBJECT, - CASE_SAVED_OBJECT, - SUB_CASE_SAVED_OBJECT, -} from '../../common/constants'; +import { CASE_COMMENT_SAVED_OBJECT, CASE_SAVED_OBJECT } from '../../common/constants'; /** * The name of the saved object reference indicating the action connector ID. This is stored in the Saved Object reference @@ -31,8 +27,3 @@ export const CASE_REF_NAME = `associated-${CASE_SAVED_OBJECT}`; * The name of the saved object reference indicating the commentId reference */ export const COMMENT_REF_NAME = `associated-${CASE_COMMENT_SAVED_OBJECT}`; - -/** - * The name of the saved object reference indicating the subCaseId reference - */ -export const SUB_CASE_REF_NAME = `associated-${SUB_CASE_SAVED_OBJECT}`; diff --git a/x-pack/plugins/cases/server/common/models/commentable_case.ts b/x-pack/plugins/cases/server/common/models/commentable_case.ts index 1c6d5ad61000a..4afb427dea1f8 100644 --- a/x-pack/plugins/cases/server/common/models/commentable_case.ts +++ b/x-pack/plugins/cases/server/common/models/commentable_case.ts @@ -16,32 +16,24 @@ import { } from 'src/core/server'; import { LensServerPluginSetup } from '../../../../lens/server'; import { - AssociationType, CaseResponse, CaseResponseRt, CaseSettings, CaseStatuses, - CaseType, CommentAttributes, CommentPatchRequest, CommentRequest, CommentType, - SubCaseAttributes, User, CommentRequestUserType, CaseAttributes, } from '../../../common/api'; -import { - CASE_SAVED_OBJECT, - MAX_DOCS_PER_PAGE, - SUB_CASE_SAVED_OBJECT, -} from '../../../common/constants'; +import { CASE_SAVED_OBJECT, MAX_DOCS_PER_PAGE } from '../../../common/constants'; import { AttachmentService, CasesService } from '../../services'; import { createCaseError } from '../error'; import { countAlertsForID, flattenCommentSavedObjects, - flattenSubCaseSavedObject, transformNewComment, getOrUpdateLensReferences, } from '../utils'; @@ -57,8 +49,7 @@ interface NewCommentResp { } interface CommentableCaseParams { - collection: SavedObject; - subCase?: SavedObject; + caseInfo: SavedObject; unsecuredSavedObjectsClient: SavedObjectsClientContract; caseService: CasesService; attachmentService: AttachmentService; @@ -67,12 +58,10 @@ interface CommentableCaseParams { } /** - * This class represents a case that can have a comment attached to it. This includes - * a Sub Case, Case, and Collection. + * This class represents a case that can have a comment attached to it. */ export class CommentableCase { - private readonly collection: SavedObject; - private readonly subCase?: SavedObject; + private readonly caseInfo: SavedObject; private readonly unsecuredSavedObjectsClient: SavedObjectsClientContract; private readonly caseService: CasesService; private readonly attachmentService: AttachmentService; @@ -80,16 +69,14 @@ export class CommentableCase { private readonly lensEmbeddableFactory: LensServerPluginSetup['lensEmbeddableFactory']; constructor({ - collection, - subCase, + caseInfo, unsecuredSavedObjectsClient, caseService, attachmentService, logger, lensEmbeddableFactory, }: CommentableCaseParams) { - this.collection = collection; - this.subCase = subCase; + this.caseInfo = caseInfo; this.unsecuredSavedObjectsClient = unsecuredSavedObjectsClient; this.caseService = caseService; this.attachmentService = attachmentService; @@ -98,106 +85,57 @@ export class CommentableCase { } public get status(): CaseStatuses { - return this.subCase?.attributes.status ?? this.collection.attributes.status; + return this.caseInfo.attributes.status; } - /** - * This property is used to abstract away which element is actually being acted upon in this class. - * If the sub case was initialized then it will be the focus of creating comments. So if you want the id - * of the saved object that the comment is primarily being attached to use this property. - * - * This is a little confusing because the created comment will have references to both the sub case and the - * collection but from the UI's perspective only the sub case really has the comment attached to it. - */ public get id(): string { - return this.subCase?.id ?? this.collection.id; + return this.caseInfo.id; } public get settings(): CaseSettings { - return this.collection.attributes.settings; + return this.caseInfo.attributes.settings; } - /** - * These functions break the abstraction of this class but they are needed to build the comment user action item. - * Another potential solution would be to implement another function that handles creating the user action in this - * class so that we don't need to expose these properties. - */ public get caseId(): string { - return this.collection.id; - } - - public get subCaseId(): string | undefined { - return this.subCase?.id; + return this.caseInfo.id; } private get owner(): string { - return this.collection.attributes.owner; + return this.caseInfo.attributes.owner; } private buildRefsToCase(): SavedObjectReference[] { - const subCaseSOType = SUB_CASE_SAVED_OBJECT; - const caseSOType = CASE_SAVED_OBJECT; return [ { - type: caseSOType, - name: `associated-${caseSOType}`, - id: this.collection.id, + type: CASE_SAVED_OBJECT, + name: `associated-${CASE_SAVED_OBJECT}`, + id: this.caseInfo.id, }, - ...(this.subCase - ? [{ type: subCaseSOType, name: `associated-${subCaseSOType}`, id: this.subCase.id }] - : []), ]; } private async update({ date, user }: { date: string; user: User }): Promise { try { - let updatedSubCaseAttributes: SavedObject | undefined; - - if (this.subCase) { - const updatedSubCase = await this.caseService.patchSubCase({ - unsecuredSavedObjectsClient: this.unsecuredSavedObjectsClient, - subCaseId: this.subCase.id, - updatedAttributes: { - updated_at: date, - updated_by: { - ...user, - }, - }, - version: this.subCase.version, - }); - - updatedSubCaseAttributes = { - ...this.subCase, - attributes: { - ...this.subCase.attributes, - ...updatedSubCase.attributes, - }, - version: updatedSubCase.version ?? this.subCase.version, - }; - } - const updatedCase = await this.caseService.patchCase({ - originalCase: this.collection, + originalCase: this.caseInfo, unsecuredSavedObjectsClient: this.unsecuredSavedObjectsClient, - caseId: this.collection.id, + caseId: this.caseInfo.id, updatedAttributes: { updated_at: date, updated_by: { ...user }, }, - version: this.collection.version, + version: this.caseInfo.version, }); - // this will contain the updated sub case information if the sub case was defined initially return new CommentableCase({ - collection: { - ...this.collection, + caseInfo: { + ...this.caseInfo, attributes: { - ...this.collection.attributes, + ...this.caseInfo.attributes, ...updatedCase.attributes, }, - version: updatedCase.version ?? this.collection.version, + version: updatedCase.version ?? this.caseInfo.version, }, - subCase: updatedSubCaseAttributes, unsecuredSavedObjectsClient: this.unsecuredSavedObjectsClient, caseService: this.caseService, attachmentService: this.attachmentService, @@ -206,7 +144,7 @@ export class CommentableCase { }); } catch (error) { throw createCaseError({ - message: `Failed to update commentable case, sub case id: ${this.subCaseId} case id: ${this.caseId}: ${error}`, + message: `Failed to update commentable case, case id: ${this.caseId}: ${error}`, error, logger: this.logger, }); @@ -264,7 +202,7 @@ export class CommentableCase { }; } catch (error) { throw createCaseError({ - message: `Failed to update comment in commentable case, sub case id: ${this.subCaseId} case id: ${this.caseId}: ${error}`, + message: `Failed to update comment in commentable case, case id: ${this.caseId}: ${error}`, error, logger: this.logger, }); @@ -290,10 +228,6 @@ export class CommentableCase { if (this.status === CaseStatuses.closed) { throw Boom.badRequest('Alert cannot be attached to a closed case'); } - - if (!this.subCase && this.collection.attributes.type === CaseType.collection) { - throw Boom.badRequest('Alert cannot be attached to a collection case'); - } } if (commentReq.owner !== this.owner) { @@ -314,7 +248,6 @@ export class CommentableCase { this.attachmentService.create({ unsecuredSavedObjectsClient: this.unsecuredSavedObjectsClient, attributes: transformNewComment({ - associationType: this.subCase ? AssociationType.subCase : AssociationType.case, createdDate, ...commentReq, ...user, @@ -330,27 +263,27 @@ export class CommentableCase { }; } catch (error) { throw createCaseError({ - message: `Failed creating a comment on a commentable case, sub case id: ${this.subCaseId} case id: ${this.caseId}: ${error}`, + message: `Failed creating a comment on a commentable case, case id: ${this.caseId}: ${error}`, error, logger: this.logger, }); } } - private formatCollectionForEncoding(totalComment: number) { + private formatForEncoding(totalComment: number) { return { - id: this.collection.id, - version: this.collection.version ?? '0', + id: this.caseInfo.id, + version: this.caseInfo.version ?? '0', totalComment, - ...this.collection.attributes, + ...this.caseInfo.attributes, }; } public async encode(): Promise { try { - const collectionComments = await this.caseService.getAllCaseComments({ + const comments = await this.caseService.getAllCaseComments({ unsecuredSavedObjectsClient: this.unsecuredSavedObjectsClient, - id: this.collection.id, + id: this.caseInfo.id, options: { fields: [], page: 1, @@ -358,50 +291,18 @@ export class CommentableCase { }, }); - const collectionTotalAlerts = - countAlertsForID({ comments: collectionComments, id: this.collection.id }) ?? 0; + const totalAlerts = countAlertsForID({ comments, id: this.caseInfo.id }) ?? 0; const caseResponse = { - comments: flattenCommentSavedObjects(collectionComments.saved_objects), - totalAlerts: collectionTotalAlerts, - ...this.formatCollectionForEncoding(collectionComments.total), + comments: flattenCommentSavedObjects(comments.saved_objects), + totalAlerts, + ...this.formatForEncoding(comments.total), }; - if (this.subCase) { - const subCaseComments = await this.caseService.getAllSubCaseComments({ - unsecuredSavedObjectsClient: this.unsecuredSavedObjectsClient, - id: this.subCase.id, - }); - const totalAlerts = - countAlertsForID({ comments: subCaseComments, id: this.subCase.id }) ?? 0; - - return CaseResponseRt.encode({ - ...caseResponse, - /** - * For now we need the sub case comments and totals to be exposed on the top level of the response so that the UI - * functionality can stay the same. Ideally in the future we can refactor this so that the UI will look for the - * comments either in the top level for a case or a collection or in the subCases field if it is a sub case. - * - * If we ever need to return both the collection's comments and the sub case comments we'll need to refactor it then - * as well. - */ - comments: flattenCommentSavedObjects(subCaseComments.saved_objects), - totalComment: subCaseComments.saved_objects.length, - totalAlerts, - subCases: [ - flattenSubCaseSavedObject({ - savedObject: this.subCase, - totalComment: subCaseComments.saved_objects.length, - totalAlerts, - }), - ], - }); - } - return CaseResponseRt.encode(caseResponse); } catch (error) { throw createCaseError({ - message: `Failed encoding the commentable case, sub case id: ${this.subCaseId} case id: ${this.caseId}: ${error}`, + message: `Failed encoding the commentable case, case id: ${this.caseId}: ${error}`, error, logger: this.logger, }); diff --git a/x-pack/plugins/cases/server/common/utils.test.ts b/x-pack/plugins/cases/server/common/utils.test.ts index f13139605afda..2f0b1ba2fc44e 100644 --- a/x-pack/plugins/cases/server/common/utils.test.ts +++ b/x-pack/plugins/cases/server/common/utils.test.ts @@ -9,7 +9,6 @@ import { SavedObject, SavedObjectsFindResponse } from 'kibana/server'; import { makeLensEmbeddableFactory } from '../../../lens/server/embeddable/make_lens_embeddable_factory'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; import { - AssociationType, CaseResponse, CommentAttributes, CommentRequest, @@ -56,7 +55,6 @@ function createCommentFindResponse( type: '', attributes: transformNewComment({ ...comment, - associationType: AssociationType.case, createdDate: '', }), }); @@ -111,15 +109,12 @@ describe('common utils', () => { "syncAlerts": true, }, "status": "open", - "subCaseIds": undefined, - "subCases": undefined, "tags": Array [ "defacement", ], "title": "Super Bad Security Issue", "totalAlerts": 0, "totalComment": 2, - "type": "individual", "updated_at": "2019-11-25T21:54:48.952Z", "updated_by": Object { "email": "testemail@elastic.co", @@ -152,15 +147,12 @@ describe('common utils', () => { "syncAlerts": true, }, "status": "open", - "subCaseIds": undefined, - "subCases": undefined, "tags": Array [ "Data Destruction", ], "title": "Damaging Data Destruction Detected", "totalAlerts": 0, "totalComment": 2, - "type": "individual", "updated_at": "2019-11-25T22:32:00.900Z", "updated_by": Object { "email": "testemail@elastic.co", @@ -197,15 +189,12 @@ describe('common utils', () => { "syncAlerts": true, }, "status": "open", - "subCaseIds": undefined, - "subCases": undefined, "tags": Array [ "LOLBins", ], "title": "Another bad one", "totalAlerts": 0, "totalComment": 2, - "type": "individual", "updated_at": "2019-11-25T22:32:17.947Z", "updated_by": Object { "email": "testemail@elastic.co", @@ -246,15 +235,12 @@ describe('common utils', () => { "syncAlerts": true, }, "status": "closed", - "subCaseIds": undefined, - "subCases": undefined, "tags": Array [ "LOLBins", ], "title": "Another bad one", "totalAlerts": 0, "totalComment": 2, - "type": "individual", "updated_at": "2019-11-25T22:32:17.947Z", "updated_by": Object { "email": "testemail@elastic.co", @@ -312,15 +298,12 @@ describe('common utils', () => { "syncAlerts": true, }, "status": "open", - "subCaseIds": undefined, - "subCases": undefined, "tags": Array [ "LOLBins", ], "title": "Another bad one", "totalAlerts": 0, "totalComment": 2, - "type": "individual", "updated_at": "2019-11-25T22:32:17.947Z", "updated_by": Object { "email": "testemail@elastic.co", @@ -369,15 +352,12 @@ describe('common utils', () => { "syncAlerts": true, }, "status": "open", - "subCaseIds": undefined, - "subCases": undefined, "tags": Array [ "LOLBins", ], "title": "Another bad one", "totalAlerts": 0, "totalComment": 2, - "type": "individual", "updated_at": "2019-11-25T22:32:17.947Z", "updated_by": Object { "email": "testemail@elastic.co", @@ -404,7 +384,6 @@ describe('common utils', () => { "closed_by": null, "comments": Array [ Object { - "associationType": "case", "comment": "Wow, good luck catching that bad meanie!", "created_at": "2019-11-25T21:55:00.177Z", "created_by": Object { @@ -450,15 +429,12 @@ describe('common utils', () => { "syncAlerts": true, }, "status": "open", - "subCaseIds": undefined, - "subCases": undefined, "tags": Array [ "LOLBins", ], "title": "Another bad one", "totalAlerts": 0, "totalComment": 2, - "type": "individual", "updated_at": "2019-11-25T22:32:17.947Z", "updated_by": Object { "email": "testemail@elastic.co", @@ -505,15 +481,12 @@ describe('common utils', () => { "syncAlerts": true, }, "status": "open", - "subCaseIds": undefined, - "subCases": undefined, "tags": Array [ "defacement", ], "title": "Super Bad Security Issue", "totalAlerts": 0, "totalComment": 2, - "type": "individual", "updated_at": "2019-11-25T21:54:48.952Z", "updated_by": Object { "email": "testemail@elastic.co", @@ -588,14 +561,12 @@ describe('common utils', () => { email: 'elastic@elastic.co', full_name: 'Elastic', username: 'elastic', - associationType: AssociationType.case, owner: SECURITY_SOLUTION_OWNER, }; const res = transformNewComment(comment); expect(res).toMatchInlineSnapshot(` Object { - "associationType": "case", "comment": "A comment", "created_at": "2020-04-09T09:43:51.778Z", "created_by": Object { @@ -619,14 +590,12 @@ describe('common utils', () => { type: CommentType.user as const, createdDate: '2020-04-09T09:43:51.778Z', owner: SECURITY_SOLUTION_OWNER, - associationType: AssociationType.case, }; const res = transformNewComment(comment); expect(res).toMatchInlineSnapshot(` Object { - "associationType": "case", "comment": "A comment", "created_at": "2020-04-09T09:43:51.778Z", "created_by": Object { @@ -653,14 +622,12 @@ describe('common utils', () => { full_name: null, username: null, owner: SECURITY_SOLUTION_OWNER, - associationType: AssociationType.case, }; const res = transformNewComment(comment); expect(res).toMatchInlineSnapshot(` Object { - "associationType": "case", "comment": "A comment", "created_at": "2020-04-09T09:43:51.778Z", "created_by": Object { @@ -693,30 +660,6 @@ describe('common utils', () => { ).toBe(0); }); - it('returns 3 alerts for a single generated alert comment', () => { - expect( - countAlerts( - createCommentFindResponse([ - { - ids: ['1'], - comments: [ - { - alertId: ['a', 'b', 'c'], - index: '', - type: CommentType.generatedAlert, - rule: { - id: 'rule-id-1', - name: 'rule-name-1', - }, - owner: SECURITY_SOLUTION_OWNER, - }, - ], - }, - ]).saved_objects[0] - ) - ).toBe(3); - }); - it('returns 3 alerts for a single alert comment', () => { expect( countAlerts( diff --git a/x-pack/plugins/cases/server/common/utils.ts b/x-pack/plugins/cases/server/common/utils.ts index 3d4b0db39f513..ef04136b0b4a1 100644 --- a/x-pack/plugins/cases/server/common/utils.ts +++ b/x-pack/plugins/cases/server/common/utils.ts @@ -5,22 +5,20 @@ * 2.0. */ -import Boom from '@hapi/boom'; import { SavedObjectsFindResult, SavedObjectsFindResponse, SavedObject, SavedObjectReference, } from 'kibana/server'; -import { flatMap, uniqWith, isEmpty, xorWith } from 'lodash'; +import { flatMap, uniqWith, xorWith } from 'lodash'; import { AlertInfo } from './types'; import { LensServerPluginSetup } from '../../../lens/server'; import { - AssociationType, CaseAttributes, + CasePostRequest, CaseResponse, - CasesClientPostRequest, CasesFindResponse, CaseStatuses, CommentAttributes, @@ -31,12 +29,8 @@ import { CommentsResponse, CommentType, ConnectorTypes, - SubCaseAttributes, - SubCaseResponse, - SubCasesFindResponse, User, } from '../../common/api'; -import { ENABLE_CASE_CONNECTOR } from '../../common/constants'; import { UpdateAlertRequest } from '../client/alerts/types'; import { parseCommentString, @@ -58,7 +52,7 @@ export const transformNewCase = ({ newCase, }: { user: User; - newCase: CasesClientPostRequest; + newCase: CasePostRequest; }): CaseAttributes => ({ ...newCase, closed_at: null, @@ -97,47 +91,16 @@ export const transformCases = ({ count_closed_cases: countClosedCases, }); -export const transformSubCases = ({ - subCasesMap, - open, - inProgress, - closed, - page, - perPage, - total, -}: { - subCasesMap: Map; - open: number; - inProgress: number; - closed: number; - page: number; - perPage: number; - total: number; -}): SubCasesFindResponse => ({ - page, - per_page: perPage, - total, - // Squish all the entries in the map together as one array - subCases: Array.from(subCasesMap.values()).flat(), - count_open_cases: open, - count_in_progress_cases: inProgress, - count_closed_cases: closed, -}); - export const flattenCaseSavedObject = ({ savedObject, comments = [], totalComment = comments.length, totalAlerts = 0, - subCases, - subCaseIds, }: { savedObject: SavedObject; comments?: Array>; totalComment?: number; totalAlerts?: number; - subCases?: SubCaseResponse[]; - subCaseIds?: string[]; }): CaseResponse => ({ id: savedObject.id, version: savedObject.version ?? '0', @@ -145,27 +108,6 @@ export const flattenCaseSavedObject = ({ totalComment, totalAlerts, ...savedObject.attributes, - subCases, - subCaseIds: !isEmpty(subCaseIds) ? subCaseIds : undefined, -}); - -export const flattenSubCaseSavedObject = ({ - savedObject, - comments = [], - totalComment = comments.length, - totalAlerts = 0, -}: { - savedObject: SavedObject; - comments?: Array>; - totalComment?: number; - totalAlerts?: number; -}): SubCaseResponse => ({ - id: savedObject.id, - version: savedObject.version ?? '0', - comments: flattenCommentSavedObjects(comments), - totalComment, - totalAlerts, - ...savedObject.attributes, }); export const transformComments = ( @@ -210,7 +152,7 @@ export const getIDsAndIndicesAsArrays = ( * To reformat the alert comment request requires a migration and a breaking API change. */ const getAndValidateAlertInfoFromComment = (comment: CommentRequest): AlertInfo[] => { - if (!isCommentRequestTypeAlertOrGenAlert(comment)) { + if (!isCommentRequestTypeAlert(comment)) { return []; } @@ -234,7 +176,6 @@ export const getAlertInfoFromComments = (comments: CommentRequest[] = []): Alert }, []); type NewCommentArgs = CommentRequest & { - associationType: AssociationType; createdDate: string; owner: string; email?: string | null; @@ -243,7 +184,6 @@ type NewCommentArgs = CommentRequest & { }; export const transformNewComment = ({ - associationType, createdDate, email, // eslint-disable-next-line @typescript-eslint/naming-convention @@ -252,7 +192,6 @@ export const transformNewComment = ({ ...comment }: NewCommentArgs): CommentAttributes => { return { - associationType, ...comment, created_at: createdDate, created_by: { email, full_name, username }, @@ -284,23 +223,10 @@ export const isCommentRequestTypeActions = ( /** * A type narrowing function for alert comments. Exporting so integration tests can use it. */ -export const isCommentRequestTypeAlertOrGenAlert = ( - context: CommentRequest -): context is CommentRequestAlertType => { - return context.type === CommentType.alert || context.type === CommentType.generatedAlert; -}; - -/** - * This is used to test if the posted comment is an generated alert. A generated alert will have one or many alerts. - * An alert is essentially an object with a _id field. This differs from a regular attached alert because the _id is - * passed directly in the request, it won't be in an object. Internally case will strip off the outer object and store - * both a generated and user attached alert in the same structure but this function is useful to determine which - * structure the new alert in the request has. - */ -export const isCommentRequestTypeGenAlert = ( +export const isCommentRequestTypeAlert = ( context: CommentRequest ): context is CommentRequestAlertType => { - return context.type === CommentType.generatedAlert; + return context.type === CommentType.alert; }; /** @@ -321,10 +247,7 @@ export function createAlertUpdateRequest({ */ export const countAlerts = (comment: SavedObjectsFindResult) => { let totalAlerts = 0; - if ( - comment.attributes.type === CommentType.alert || - comment.attributes.type === CommentType.generatedAlert - ) { + if (comment.attributes.type === CommentType.alert) { if (Array.isArray(comment.attributes.alertId)) { totalAlerts += comment.attributes.alertId.length; } else { @@ -335,9 +258,7 @@ export const countAlerts = (comment: SavedObjectsFindResult) }; /** - * Count the number of alerts for each id in the alert's references. This will result - * in a map with entries for both the collection and the individual sub cases. So the resulting - * size of the map will not equal the total number of sub cases. + * Count the number of alerts for each id in the alert's references. */ export const groupTotalAlertsByID = ({ comments, @@ -363,7 +284,7 @@ export const groupTotalAlertsByID = ({ }; /** - * Counts the total alert IDs for a single case or sub case ID. + * Counts the total alert IDs for a single case. */ export const countAlertsForID = ({ comments, @@ -375,17 +296,6 @@ export const countAlertsForID = ({ return groupTotalAlertsByID({ comments }).get(id); }; -/** - * If subCaseID is defined and the case connector feature is disabled this throws an error. - */ -export function checkEnabledCaseConnectorOrThrow(subCaseID: string | undefined) { - if (!ENABLE_CASE_CONNECTOR && subCaseID !== undefined) { - throw Boom.badRequest( - 'The sub case parameters are not supported when the case connector feature is disabled' - ); - } -} - /** * Returns a connector that indicates that no connector was set. * diff --git a/x-pack/plugins/cases/server/connectors/case/index.test.ts b/x-pack/plugins/cases/server/connectors/case/index.test.ts deleted file mode 100644 index e5d8dbf3bb38d..0000000000000 --- a/x-pack/plugins/cases/server/connectors/case/index.test.ts +++ /dev/null @@ -1,1190 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { omit } from 'lodash/fp'; -import { Logger } from '../../../../../../src/core/server'; -import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; -import { actionsMock } from '../../../../actions/server/mocks'; -import { validateParams } from '../../../../actions/server/lib'; -import { - ConnectorTypes, - CommentType, - CaseStatuses, - CaseType, - AssociationType, - CaseResponse, - CasesResponse, -} from '../../../common/api'; -import { CaseActionType, CaseActionTypeExecutorOptions, CaseExecutorParams } from './types'; -import { getActionType } from '.'; - -import { - CasesClientMock, - createCasesClientFactory, - createCasesClientMock, -} from '../../client/mocks'; -import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; - -const services = actionsMock.createServices(); -let caseActionType: CaseActionType; - -describe('case connector', () => { - let mockCasesClient: CasesClientMock; - - beforeEach(() => { - const logger = loggingSystemMock.create().get() as jest.Mocked; - - mockCasesClient = createCasesClientMock(); - - const factory = createCasesClientFactory(); - factory.create.mockReturnValue(Promise.resolve(mockCasesClient)); - caseActionType = getActionType({ - logger, - factory, - }); - }); - - describe('params validation', () => { - describe('create', () => { - it('succeeds when params is valid', () => { - const params: Record = { - subAction: 'create', - subActionParams: { - title: 'Case from case connector!!', - tags: ['case', 'connector'], - description: 'Yo fields!!', - connector: { - id: 'jira', - name: 'Jira', - type: ConnectorTypes.jira, - fields: { - issueType: '10006', - priority: 'High', - parent: null, - }, - }, - settings: { - syncAlerts: true, - }, - }, - }; - - expect(validateParams(caseActionType, params)).toEqual(params); - }); - - it('fails when params is not valid', () => { - const params: Record = { - subAction: 'create', - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow(); - }); - - describe('connector', () => { - const connectorTests = [ - { - test: 'jira', - params: { - subAction: 'create', - subActionParams: { - title: 'Case from case connector!!', - tags: ['case', 'connector'], - description: 'Yo fields!!', - connector: { - id: 'jira', - name: 'Jira', - type: ConnectorTypes.jira, - fields: { - issueType: '10006', - priority: 'High', - parent: null, - }, - }, - settings: { - syncAlerts: true, - }, - }, - }, - }, - { - test: 'resilient', - params: { - subAction: 'create', - subActionParams: { - title: 'Case from case connector!!', - tags: ['case', 'connector'], - description: 'Yo fields!!', - connector: { - id: 'resilient', - name: 'Resilient', - type: '.resilient', - fields: { - incidentTypes: ['13'], - severityCode: '3', - }, - }, - settings: { - syncAlerts: true, - }, - }, - }, - }, - { - test: 'servicenow', - params: { - subAction: 'create', - subActionParams: { - title: 'Case from case connector!!', - tags: ['case', 'connector'], - description: 'Yo fields!!', - connector: { - id: 'servicenow', - name: 'Servicenow', - type: '.servicenow', - fields: { - impact: 'Medium', - severity: 'Medium', - urgency: 'Medium', - category: 'software', - subcategory: 'os', - }, - }, - settings: { - syncAlerts: true, - }, - }, - }, - }, - { - test: 'servicenow-sir', - params: { - subAction: 'create', - subActionParams: { - title: 'Case from case connector!!', - tags: ['case', 'connector'], - description: 'Yo fields!!', - connector: { - id: 'servicenow-sir', - name: 'Servicenow SIR', - type: '.servicenow-sir', - fields: { - destIp: true, - sourceIp: true, - malwareHash: true, - malwareUrl: true, - category: 'ddos', - subcategory: '15', - priority: '1', - }, - }, - settings: { - syncAlerts: true, - }, - }, - }, - }, - { - test: 'none', - params: { - subAction: 'create', - subActionParams: { - title: 'Case from case connector!!', - tags: ['case', 'connector'], - description: 'Yo fields!!', - connector: { - id: 'none', - name: 'None', - type: '.none', - fields: null, - }, - settings: { - syncAlerts: true, - }, - }, - }, - }, - ]; - - connectorTests.forEach(({ params, test }) => { - it(`succeeds when ${test} fields are valid`, () => { - expect(validateParams(caseActionType, params)).toEqual(params); - }); - }); - - it('set fields to null if they are missing', () => { - const params: Record = { - subAction: 'create', - subActionParams: { - title: 'Case from case connector!!', - tags: ['case', 'connector'], - description: 'Yo fields!!', - connector: { - id: 'servicenow', - name: 'Servicenow', - type: '.servicenow', - fields: {}, - }, - settings: { - syncAlerts: true, - }, - }, - }; - - expect(validateParams(caseActionType, params)).toEqual({ - ...params, - subActionParams: { - title: 'Case from case connector!!', - tags: ['case', 'connector'], - description: 'Yo fields!!', - connector: { - id: 'servicenow', - name: 'Servicenow', - type: '.servicenow', - fields: { - impact: null, - severity: null, - urgency: null, - category: null, - subcategory: null, - }, - }, - settings: { - syncAlerts: true, - }, - }, - }); - }); - - it('succeeds when none fields are valid', () => { - const params: Record = { - subAction: 'create', - subActionParams: { - title: 'Case from case connector!!', - tags: ['case', 'connector'], - description: 'Yo fields!!', - connector: { - id: 'none', - name: 'None', - type: '.none', - fields: null, - }, - settings: { - syncAlerts: true, - }, - }, - }; - - expect(validateParams(caseActionType, params)).toEqual(params); - }); - - it('fails when issueType is not provided', () => { - const params: Record = { - subAction: 'create', - subActionParams: { - title: 'Case from case connector!!', - tags: ['case', 'connector'], - description: 'Yo fields!!', - connector: { - id: 'jira', - name: 'Jira', - type: ConnectorTypes.jira, - fields: { - priority: 'High', - parent: null, - }, - }, - settings: { - syncAlerts: true, - }, - }, - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow( - '[0.subActionParams.connector.fields.issueType]: expected value of type [string] but got [undefined]' - ); - }); - - it('fails with excess fields', () => { - const params: Record = { - subAction: 'create', - subActionParams: { - title: 'Case from case connector!!', - tags: ['case', 'connector'], - description: 'Yo fields!!', - connector: { - id: 'servicenow', - name: 'Servicenow', - type: '.servicenow', - fields: { - impact: 'Medium', - severity: 'Medium', - urgency: 'Medium', - category: 'software', - subcategory: 'os', - excess: null, - }, - }, - settings: { - syncAlerts: true, - }, - }, - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow( - '[0.subActionParams.connector.fields.excess]: definition for this key is missing' - ); - }); - - it('fails with valid fields but wrong type', () => { - const params: Record = { - subAction: 'create', - subActionParams: { - title: 'Case from case connector!!', - tags: ['case', 'connector'], - description: 'Yo fields!!', - connector: { - id: 'resilient', - name: 'Resilient', - type: '.resilient', - fields: { - issueType: '10006', - priority: 'High', - parent: null, - }, - }, - settings: { - syncAlerts: true, - }, - }, - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow( - '[0.subActionParams.connector.fields.issueType]: definition for this key is missing' - ); - }); - - it('fails when fields are not null and the type is none', () => { - const params: Record = { - subAction: 'create', - subActionParams: { - title: 'Case from case connector!!', - tags: ['case', 'connector'], - description: 'Yo fields!!', - connector: { - id: 'none', - name: 'None', - type: '.none', - fields: {}, - }, - settings: { - syncAlerts: true, - }, - }, - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow( - '[0.subActionParams.connector]: Fields must be set to null for connectors of type .none' - ); - }); - }); - }); - - describe('update', () => { - it('succeeds when params is valid', () => { - const params: Record = { - subAction: 'update', - subActionParams: { - id: 'case-id', - version: '123', - title: 'Update title', - }, - }; - - expect(validateParams(caseActionType, params)).toEqual({ - ...params, - subActionParams: { - description: null, - tags: null, - title: null, - status: null, - connector: null, - settings: null, - ...(params.subActionParams as Record), - }, - }); - }); - - describe('connector', () => { - it('succeeds when jira fields are valid', () => { - const params: Record = { - subAction: 'update', - subActionParams: { - id: 'case-id', - version: '123', - connector: { - id: 'jira', - name: 'Jira', - type: ConnectorTypes.jira, - fields: { - issueType: '10006', - priority: 'High', - parent: null, - }, - }, - }, - }; - - expect(validateParams(caseActionType, params)).toEqual({ - ...params, - subActionParams: { - description: null, - tags: null, - title: null, - status: null, - settings: null, - ...(params.subActionParams as Record), - }, - }); - }); - - it('succeeds when resilient fields are valid', () => { - const params: Record = { - subAction: 'update', - subActionParams: { - id: 'case-id', - version: '123', - connector: { - id: 'resilient', - name: 'Resilient', - type: '.resilient', - fields: { - incidentTypes: ['13'], - severityCode: '3', - }, - }, - }, - }; - - expect(validateParams(caseActionType, params)).toEqual({ - ...params, - subActionParams: { - description: null, - tags: null, - title: null, - status: null, - settings: null, - ...(params.subActionParams as Record), - }, - }); - }); - - it('succeeds when servicenow ITMSM fields are valid', () => { - const params: Record = { - subAction: 'update', - subActionParams: { - id: 'case-id', - version: '123', - connector: { - id: 'servicenow', - name: 'Servicenow', - type: '.servicenow', - fields: { - impact: 'Medium', - severity: 'Medium', - urgency: 'Medium', - category: 'software', - subcategory: 'os', - }, - }, - }, - }; - - expect(validateParams(caseActionType, params)).toEqual({ - ...params, - subActionParams: { - description: null, - tags: null, - title: null, - status: null, - settings: null, - ...(params.subActionParams as Record), - }, - }); - }); - - it('succeeds when servicenow SIR fields are valid', () => { - const params: Record = { - subAction: 'update', - subActionParams: { - id: 'case-id', - version: '123', - connector: { - id: 'servicenow-sir', - name: 'Servicenow SIR', - type: '.servicenow-sir', - fields: { - destIp: true, - sourceIp: true, - malwareHash: true, - malwareUrl: true, - category: 'ddos', - subcategory: '15', - priority: '1', - }, - }, - }, - }; - - expect(validateParams(caseActionType, params)).toEqual({ - ...params, - subActionParams: { - description: null, - tags: null, - title: null, - status: null, - settings: null, - ...(params.subActionParams as Record), - }, - }); - }); - - it('set fields to null if they are missing', () => { - const params: Record = { - subAction: 'update', - subActionParams: { - id: 'case-id', - version: '123', - connector: { - id: 'servicenow', - name: 'Servicenow', - type: '.servicenow', - fields: {}, - }, - }, - }; - - expect(validateParams(caseActionType, params)).toEqual({ - ...params, - subActionParams: { - id: 'case-id', - version: '123', - description: null, - tags: null, - title: null, - status: null, - settings: null, - connector: { - id: 'servicenow', - name: 'Servicenow', - type: '.servicenow', - fields: { - impact: null, - severity: null, - urgency: null, - category: null, - subcategory: null, - }, - }, - }, - }); - }); - - it('succeeds when none fields are valid', () => { - const params: Record = { - subAction: 'update', - subActionParams: { - id: 'case-id', - version: '123', - connector: { - id: 'none', - name: 'None', - type: '.none', - fields: null, - }, - }, - }; - - expect(validateParams(caseActionType, params)).toEqual({ - ...params, - subActionParams: { - description: null, - tags: null, - title: null, - status: null, - settings: null, - ...(params.subActionParams as Record), - }, - }); - }); - - it('fails when issueType is not provided', () => { - const params: Record = { - subAction: 'update', - subActionParams: { - id: 'case-id', - version: '123', - connector: { - id: 'jira', - name: 'Jira', - type: ConnectorTypes.jira, - fields: { - priority: 'High', - parent: null, - }, - }, - }, - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow( - '[subActionParams.connector.0.fields.issueType]: expected value of type [string] but got [undefined]' - ); - }); - - it('fails with excess fields', () => { - const params: Record = { - subAction: 'update', - subActionParams: { - id: 'case-id', - version: '123', - connector: { - id: 'servicenow', - name: 'Servicenow', - type: '.servicenow', - fields: { - impact: 'Medium', - severity: 'Medium', - urgency: 'Medium', - category: 'software', - subcategory: 'os', - excess: null, - }, - }, - }, - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow( - '[subActionParams.connector.0.fields.excess]: definition for this key is missing' - ); - }); - - it('fails with valid fields but wrong type', () => { - const params: Record = { - subAction: 'update', - subActionParams: { - id: 'case-id', - version: '123', - connector: { - id: 'resilient', - name: 'Resilient', - type: '.resilient', - fields: { - issueType: '10006', - priority: 'High', - parent: null, - }, - }, - }, - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow( - '[subActionParams.connector.0.fields.issueType]: definition for this key is missing' - ); - }); - - it('fails when fields are not null and the type is none', () => { - const params: Record = { - subAction: 'update', - subActionParams: { - id: 'case-id', - version: '123', - connector: { - id: 'none', - name: 'None', - type: '.none', - fields: {}, - }, - }, - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow( - '[subActionParams.connector.0]: Fields must be set to null for connectors of type .none' - ); - }); - }); - - it('fails when params is not valid', () => { - const params: Record = { - subAction: 'update', - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow(); - }); - }); - - describe('add comment', () => { - it('succeeds when type is user', () => { - const params: Record = { - subAction: 'addComment', - subActionParams: { - caseId: 'case-id', - comment: { - comment: 'a comment', - type: CommentType.user, - owner: SECURITY_SOLUTION_OWNER, - }, - }, - }; - - expect(validateParams(caseActionType, params)).toEqual(params); - }); - - it('succeeds when type is an alert', () => { - const params: Record = { - subAction: 'addComment', - subActionParams: { - caseId: 'case-id', - comment: { - type: CommentType.alert, - alertId: 'test-id', - index: 'test-index', - rule: { - id: null, - name: null, - }, - owner: SECURITY_SOLUTION_OWNER, - }, - }, - }; - - expect(validateParams(caseActionType, params)).toEqual(params); - }); - - it('fails when params is not valid', () => { - const params: Record = { - subAction: 'addComment', - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow(); - }); - - it('fails when missing attributes: type user', () => { - const allParams = { - type: CommentType.user, - comment: 'a comment', - }; - - ['comment'].forEach((attribute) => { - const comment = omit(attribute, allParams); - const params: Record = { - subAction: 'addComment', - subActionParams: { - caseId: 'case-id', - comment, - }, - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow(); - }); - }); - - it('fails when missing attributes: type alert', () => { - const allParams = { - type: CommentType.alert, - comment: 'a comment', - alertId: 'test-id', - index: 'test-index', - }; - - ['alertId', 'index'].forEach((attribute) => { - const comment = omit(attribute, allParams); - const params: Record = { - subAction: 'addComment', - subActionParams: { - caseId: 'case-id', - comment, - }, - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow(); - }); - }); - - it('fails when excess attributes are provided: type user', () => { - ['alertId', 'index'].forEach((attribute) => { - const params: Record = { - subAction: 'addComment', - subActionParams: { - caseId: 'case-id', - [attribute]: attribute, - type: CommentType.user, - comment: 'a comment', - }, - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow(); - }); - }); - - it('fails when excess attributes are provided: type alert', () => { - ['comment'].forEach((attribute) => { - const params: Record = { - subAction: 'addComment', - subActionParams: { - caseId: 'case-id', - [attribute]: attribute, - type: CommentType.alert, - alertId: 'test-id', - index: 'test-index', - }, - }; - - expect(() => { - validateParams(caseActionType, params); - }).toThrow(); - }); - }); - }); - }); - - it('should throw an error when executing the connector', async () => { - expect.assertions(2); - const actionId = 'some-id'; - const params: CaseExecutorParams = { - // @ts-expect-error - subAction: 'not-supported', - // @ts-expect-error - subActionParams: {}, - }; - - const executorOptions: CaseActionTypeExecutorOptions = { - actionId, - config: {}, - params, - secrets: {}, - services, - }; - - try { - await caseActionType.executor(executorOptions); - } catch (e) { - expect(e).not.toBeNull(); - expect(e.message).toBe('[Action][Case] connector not supported'); - } - }); - - // Enable these when the actions framework provides a request and a saved objects service - // ENABLE_CASE_CONNECTOR: enable these tests after the case connector feature is completed - describe.skip('execute', () => { - it('allows only supported sub-actions', async () => { - expect.assertions(2); - const actionId = 'some-id'; - const params: CaseExecutorParams = { - // @ts-expect-error - subAction: 'not-supported', - // @ts-expect-error - subActionParams: {}, - }; - - const executorOptions: CaseActionTypeExecutorOptions = { - actionId, - config: {}, - params, - secrets: {}, - services, - }; - - caseActionType.executor(executorOptions).catch((e) => { - expect(e).not.toBeNull(); - expect(e.message).toBe('[Action][Case] subAction not-supported not implemented.'); - }); - }); - - describe('create', () => { - it('executes correctly', async () => { - const createReturn: CaseResponse = { - id: 'mock-it', - comments: [], - totalComment: 0, - totalAlerts: 0, - closed_at: null, - closed_by: null, - connector: { id: 'none', name: 'none', type: ConnectorTypes.none, fields: null }, - created_at: '2019-11-25T21:54:48.952Z', - created_by: { - full_name: 'Awesome D00d', - email: 'd00d@awesome.com', - username: 'awesome', - }, - title: 'Case from case connector!!', - tags: ['case', 'connector'], - type: CaseType.collection, - description: 'Yo fields!!', - external_service: null, - status: CaseStatuses.open, - updated_at: null, - updated_by: null, - version: 'WzksMV0=', - settings: { - syncAlerts: true, - }, - owner: SECURITY_SOLUTION_OWNER, - }; - - mockCasesClient.cases.create.mockReturnValue(Promise.resolve(createReturn)); - - const actionId = 'some-id'; - const params: CaseExecutorParams = { - subAction: 'create', - subActionParams: { - title: 'Case from case connector!!', - tags: ['case', 'connector'], - description: 'Yo fields!!', - connector: { - id: 'jira', - name: 'Jira', - type: ConnectorTypes.jira, - fields: { - issueType: '10006', - priority: 'High', - parent: null, - }, - }, - settings: { - syncAlerts: true, - }, - }, - }; - - const executorOptions: CaseActionTypeExecutorOptions = { - actionId, - config: {}, - params, - secrets: {}, - services, - }; - - const result = await caseActionType.executor(executorOptions); - - expect(result).toEqual({ actionId, status: 'ok', data: createReturn }); - expect(mockCasesClient.cases.create).toHaveBeenCalledWith({ - ...params.subActionParams, - connector: { - id: 'jira', - name: 'Jira', - type: ConnectorTypes.jira, - fields: { - issueType: '10006', - priority: 'High', - parent: null, - }, - }, - }); - }); - }); - - describe('update', () => { - it('executes correctly', async () => { - const updateReturn: CasesResponse = [ - { - closed_at: '2019-11-25T21:54:48.952Z', - closed_by: { - email: 'd00d@awesome.com', - full_name: 'Awesome D00d', - username: 'awesome', - }, - comments: [], - connector: { - id: 'none', - name: 'none', - type: ConnectorTypes.none, - fields: null, - }, - created_at: '2019-11-25T21:54:48.952Z', - created_by: { - email: 'testemail@elastic.co', - full_name: 'elastic', - username: 'elastic', - }, - description: 'This is a brand new case of a bad meanie defacing data', - id: 'mock-id-1', - external_service: null, - status: CaseStatuses.open, - tags: ['defacement'], - title: 'Update title', - totalComment: 0, - totalAlerts: 0, - type: CaseType.collection, - updated_at: '2019-11-25T21:54:48.952Z', - updated_by: { - email: 'd00d@awesome.com', - full_name: 'Awesome D00d', - username: 'awesome', - }, - version: 'WzE3LDFd', - settings: { - syncAlerts: true, - }, - owner: SECURITY_SOLUTION_OWNER, - }, - ]; - - mockCasesClient.cases.update.mockReturnValue(Promise.resolve(updateReturn)); - - const actionId = 'some-id'; - const params: CaseExecutorParams = { - subAction: 'update', - subActionParams: { - id: 'case-id', - version: '123', - title: 'Update title', - description: null, - tags: null, - status: null, - connector: null, - settings: null, - }, - }; - - const executorOptions: CaseActionTypeExecutorOptions = { - actionId, - config: {}, - params, - secrets: {}, - services, - }; - - const result = await caseActionType.executor(executorOptions); - - expect(result).toEqual({ actionId, status: 'ok', data: updateReturn }); - expect(mockCasesClient.cases.update).toHaveBeenCalledWith({ - // Null values have been striped out. - cases: [ - { - id: 'case-id', - version: '123', - title: 'Update title', - }, - ], - }); - }); - }); - - describe('addComment', () => { - it('executes correctly', async () => { - const commentReturn: CaseResponse = { - id: 'mock-it', - totalComment: 0, - totalAlerts: 0, - version: 'WzksMV0=', - closed_at: null, - closed_by: null, - connector: { id: 'none', name: 'none', type: ConnectorTypes.none, fields: null }, - created_at: '2019-11-25T21:54:48.952Z', - created_by: { - full_name: 'Awesome D00d', - email: 'd00d@awesome.com', - username: 'awesome', - }, - description: 'This is a brand new case of a bad meanie defacing data', - external_service: null, - title: 'Super Bad Security Issue', - status: CaseStatuses.open, - tags: ['defacement'], - type: CaseType.collection, - updated_at: null, - updated_by: null, - comments: [ - { - associationType: AssociationType.case, - comment: 'a comment', - type: CommentType.user as const, - created_at: '2020-10-23T21:54:48.952Z', - created_by: { - email: 'd00d@awesome.com', - full_name: 'Awesome D00d', - username: 'awesome', - }, - id: 'mock-comment', - owner: SECURITY_SOLUTION_OWNER, - pushed_at: null, - pushed_by: null, - updated_at: null, - updated_by: null, - version: 'WzksMV0=', - }, - ], - settings: { - syncAlerts: true, - }, - owner: SECURITY_SOLUTION_OWNER, - }; - - mockCasesClient.attachments.add.mockReturnValue(Promise.resolve(commentReturn)); - - const actionId = 'some-id'; - const params: CaseExecutorParams = { - subAction: 'addComment', - subActionParams: { - caseId: 'case-id', - comment: { - comment: 'a comment', - type: CommentType.user, - owner: SECURITY_SOLUTION_OWNER, - }, - }, - }; - - const executorOptions: CaseActionTypeExecutorOptions = { - actionId, - config: {}, - params, - secrets: {}, - services, - }; - - const result = await caseActionType.executor(executorOptions); - - expect(result).toEqual({ actionId, status: 'ok', data: commentReturn }); - expect(mockCasesClient.attachments.add).toHaveBeenCalledWith({ - caseId: 'case-id', - comment: { - comment: 'a comment', - type: CommentType.user, - }, - }); - }); - }); - }); -}); diff --git a/x-pack/plugins/cases/server/connectors/case/index.ts b/x-pack/plugins/cases/server/connectors/case/index.ts deleted file mode 100644 index f40a04349068e..0000000000000 --- a/x-pack/plugins/cases/server/connectors/case/index.ts +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { curry } from 'lodash'; -import { Logger } from 'src/core/server'; -import { ActionTypeExecutorResult } from '../../../../actions/common'; -import { - CasePatchRequest, - CasePostRequest, - CommentRequest, - CommentType, -} from '../../../common/api'; -import { ENABLE_CASE_CONNECTOR } from '../../../common/constants'; -import { CaseExecutorParamsSchema, CaseConfigurationSchema, CommentSchemaType } from './schema'; -import { - CaseExecutorResponse, - ExecutorSubActionAddCommentParams, - CaseActionType, - CaseActionTypeExecutorOptions, -} from './types'; -import * as i18n from './translations'; - -import { GetActionTypeParams, isCommentGeneratedAlert, separator } from '..'; -import { createCaseError } from '../../common/error'; -import { CasesClient } from '../../client'; - -const supportedSubActions: string[] = ['create', 'update', 'addComment']; - -// action type definition -export function getActionType({ logger, factory }: GetActionTypeParams): CaseActionType { - return { - id: '.case', - minimumLicenseRequired: 'basic', - name: i18n.NAME, - validate: { - config: CaseConfigurationSchema, - params: CaseExecutorParamsSchema, - }, - executor: curry(executor)({ - factory, - logger, - }), - }; -} - -// action executor -async function executor( - { logger, factory }: GetActionTypeParams, - execOptions: CaseActionTypeExecutorOptions -): Promise> { - if (!ENABLE_CASE_CONNECTOR) { - const msg = '[Action][Case] connector not supported'; - logger.error(msg); - throw new Error(msg); - } - - const { actionId, params } = execOptions; - const { subAction, subActionParams } = params; - let data: CaseExecutorResponse | null = null; - - let casesClient: CasesClient | undefined; - - if (!supportedSubActions.includes(subAction)) { - const errorMessage = `[Action][Case] subAction ${subAction} not implemented.`; - logger.error(errorMessage); - throw new Error(errorMessage); - } - - // When the actions framework provides the request and a way to retrieve the saved objects client with access to our - // hidden types then remove this outer if block and initialize the casesClient using the factory. - if (casesClient) { - if (subAction === 'create') { - try { - data = await casesClient.cases.create({ - ...(subActionParams as CasePostRequest), - }); - } catch (error) { - throw createCaseError({ - message: `Failed to create a case using connector: ${error}`, - error, - logger, - }); - } - } - - if (subAction === 'update') { - const updateParamsWithoutNullValues = Object.entries(subActionParams).reduce( - (acc, [key, value]) => ({ - ...acc, - ...(value != null ? { [key]: value } : {}), - }), - {} as CasePatchRequest - ); - - try { - data = await casesClient.cases.update({ cases: [updateParamsWithoutNullValues] }); - } catch (error) { - throw createCaseError({ - message: `Failed to update case using connector id: ${updateParamsWithoutNullValues?.id} version: ${updateParamsWithoutNullValues?.version}: ${error}`, - error, - logger, - }); - } - } - - if (subAction === 'addComment') { - const { caseId, comment } = subActionParams as ExecutorSubActionAddCommentParams; - try { - const formattedComment = transformConnectorComment(comment, logger); - data = await casesClient.attachments.add({ caseId, comment: formattedComment }); - } catch (error) { - throw createCaseError({ - message: `Failed to create comment using connector case id: ${caseId}: ${error}`, - error, - logger, - }); - } - } - } - return { status: 'ok', data: data ?? {}, actionId }; -} - -/** - * This converts a connector style generated alert ({_id: string} | {_id: string}[]) to the expected format of addComment. - */ -interface AttachmentAlerts { - ids: string[]; - indices: string[]; - rule: { id: string | null; name: string | null }; -} - -/** - * Convert a connector style comment passed through the action plugin to the expected format for the add comment functionality. - * - * @param comment an object defining the comment to be attached to a case/sub case - * @param logger an optional logger to handle logging an error if parsing failed - * - * Note: This is exported so that the integration tests can use it. - */ -export const transformConnectorComment = ( - comment: CommentSchemaType, - logger?: Logger -): CommentRequest => { - if (isCommentGeneratedAlert(comment)) { - try { - const genAlerts: Array<{ - _id: string; - _index: string; - ruleId: string | undefined; - ruleName: string | undefined; - }> = JSON.parse( - `${comment.alerts.substring(0, comment.alerts.lastIndexOf(separator))}]`.replace( - new RegExp(separator, 'g'), - ',' - ) - ); - - const { ids, indices, rule } = genAlerts.reduce( - (acc, { _id, _index, ruleId, ruleName }) => { - // Mutation is faster than destructing. - // Mutation usually leads to side effects but for this scenario it's ok to do it. - acc.ids.push(_id); - acc.indices.push(_index); - // We assume one rule per batch of alerts, this will use the rule information from the last entry in the array - acc.rule = { id: ruleId ?? null, name: ruleName ?? null }; - return acc; - }, - { ids: [], indices: [], rule: { id: null, name: null } } - ); - - return { - type: CommentType.generatedAlert, - alertId: ids, - index: indices, - rule, - owner: comment.owner, - }; - } catch (e) { - throw createCaseError({ - message: `Error parsing generated alert in case connector -> ${e}`, - error: e, - logger, - }); - } - } else { - return comment; - } -}; diff --git a/x-pack/plugins/cases/server/connectors/case/schema.ts b/x-pack/plugins/cases/server/connectors/case/schema.ts deleted file mode 100644 index 86ee34284a661..0000000000000 --- a/x-pack/plugins/cases/server/connectors/case/schema.ts +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { CommentType, ConnectorTypes } from '../../../common/api'; -import { validateConnector } from './validators'; - -// Reserved for future implementation -export const CaseConfigurationSchema = schema.object({}); - -const ContextTypeUserSchema = schema.object({ - type: schema.literal(CommentType.user), - comment: schema.string(), - owner: schema.string(), -}); - -const ContextTypeAlertGroupSchema = schema.object({ - type: schema.literal(CommentType.generatedAlert), - alerts: schema.string(), - owner: schema.string(), -}); - -export type ContextTypeGeneratedAlertType = typeof ContextTypeAlertGroupSchema.type; - -const ContextTypeAlertSchema = schema.object({ - type: schema.literal(CommentType.alert), - // allowing either an array or a single value to preserve the previous API of attaching a single alert ID - alertId: schema.oneOf([schema.arrayOf(schema.string()), schema.string()]), - index: schema.string(), - rule: schema.object({ - id: schema.nullable(schema.string()), - name: schema.nullable(schema.string()), - }), - owner: schema.string(), -}); - -export type ContextTypeAlertSchemaType = typeof ContextTypeAlertSchema.type; - -export const CommentSchema = schema.oneOf([ - ContextTypeUserSchema, - ContextTypeAlertSchema, - ContextTypeAlertGroupSchema, -]); - -export type CommentSchemaType = typeof CommentSchema.type; - -const JiraFieldsSchema = schema.object({ - issueType: schema.string(), - priority: schema.nullable(schema.string()), - parent: schema.nullable(schema.string()), -}); - -const ResilientFieldsSchema = schema.object({ - incidentTypes: schema.nullable(schema.arrayOf(schema.string())), - severityCode: schema.nullable(schema.string()), -}); - -const ServiceNowITSMFieldsSchema = schema.object({ - impact: schema.nullable(schema.string()), - severity: schema.nullable(schema.string()), - urgency: schema.nullable(schema.string()), - category: schema.nullable(schema.string()), - subcategory: schema.nullable(schema.string()), -}); - -const ServiceNowSIRFieldsSchema = schema.object({ - destIp: schema.nullable(schema.boolean()), - sourceIp: schema.nullable(schema.boolean()), - malwareHash: schema.nullable(schema.boolean()), - malwareUrl: schema.nullable(schema.boolean()), - priority: schema.nullable(schema.string()), - category: schema.nullable(schema.string()), - subcategory: schema.nullable(schema.string()), -}); - -const SwimlaneFieldsSchema = schema.object({ - caseId: schema.nullable(schema.string()), -}); - -const NoneFieldsSchema = schema.nullable(schema.object({})); - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const ReducedConnectorFieldsSchema: { [x: string]: any } = { - [ConnectorTypes.jira]: JiraFieldsSchema, - [ConnectorTypes.resilient]: ResilientFieldsSchema, - [ConnectorTypes.serviceNowSIR]: ServiceNowSIRFieldsSchema, - [ConnectorTypes.swimlane]: SwimlaneFieldsSchema, -}; - -export const ConnectorProps = { - id: schema.string(), - name: schema.string(), - type: schema.oneOf([ - schema.literal(ConnectorTypes.jira), - schema.literal(ConnectorTypes.none), - schema.literal(ConnectorTypes.resilient), - schema.literal(ConnectorTypes.serviceNowITSM), - schema.literal(ConnectorTypes.serviceNowSIR), - schema.literal(ConnectorTypes.swimlane), - ]), - // Chain of conditional schemes - fields: Object.keys(ReducedConnectorFieldsSchema).reduce( - (conditionalSchema, key) => - schema.conditional( - schema.siblingRef('type'), - key, - ReducedConnectorFieldsSchema[key], - conditionalSchema - ), - schema.conditional( - schema.siblingRef('type'), - ConnectorTypes.serviceNowITSM, - ServiceNowITSMFieldsSchema, - NoneFieldsSchema - ) - ), -}; - -export const ConnectorSchema = schema.object(ConnectorProps); - -const CaseBasicProps = { - description: schema.string(), - title: schema.string(), - tags: schema.arrayOf(schema.string()), - connector: schema.object(ConnectorProps, { validate: validateConnector }), - settings: schema.object({ syncAlerts: schema.boolean() }), -}; - -const CaseUpdateRequestProps = { - id: schema.string(), - version: schema.string(), - description: schema.nullable(CaseBasicProps.description), - title: schema.nullable(CaseBasicProps.title), - tags: schema.nullable(CaseBasicProps.tags), - connector: schema.nullable(CaseBasicProps.connector), - settings: schema.nullable(CaseBasicProps.settings), - status: schema.nullable(schema.string()), -}; - -const CaseAddCommentRequestProps = { - caseId: schema.string(), - comment: CommentSchema, -}; - -export const ExecutorSubActionCreateParamsSchema = schema.object(CaseBasicProps); -export const ExecutorSubActionUpdateParamsSchema = schema.object(CaseUpdateRequestProps); -export const ExecutorSubActionAddCommentParamsSchema = schema.object(CaseAddCommentRequestProps); - -export const CaseExecutorParamsSchema = schema.oneOf([ - schema.object({ - subAction: schema.literal('create'), - subActionParams: ExecutorSubActionCreateParamsSchema, - }), - schema.object({ - subAction: schema.literal('update'), - subActionParams: ExecutorSubActionUpdateParamsSchema, - }), - schema.object({ - subAction: schema.literal('addComment'), - subActionParams: ExecutorSubActionAddCommentParamsSchema, - }), -]); diff --git a/x-pack/plugins/cases/server/connectors/case/types.ts b/x-pack/plugins/cases/server/connectors/case/types.ts deleted file mode 100644 index 6a7dfd9c2e687..0000000000000 --- a/x-pack/plugins/cases/server/connectors/case/types.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { TypeOf } from '@kbn/config-schema'; -import { ActionType, ActionTypeExecutorOptions } from '../../../../actions/server'; -import { - CaseExecutorParamsSchema, - ExecutorSubActionCreateParamsSchema, - ExecutorSubActionUpdateParamsSchema, - CaseConfigurationSchema, - ExecutorSubActionAddCommentParamsSchema, - ConnectorSchema, - CommentSchema, -} from './schema'; -import { CaseResponse, CasesResponse } from '../../../common/api'; - -export type CaseConfiguration = TypeOf; -export type Connector = TypeOf; -export type Comment = TypeOf; - -export type ExecutorSubActionCreateParams = TypeOf; -export type ExecutorSubActionUpdateParams = TypeOf; -export type ExecutorSubActionAddCommentParams = TypeOf< - typeof ExecutorSubActionAddCommentParamsSchema ->; - -export type CaseExecutorParams = TypeOf; -export type CaseExecutorResponse = CaseResponse | CasesResponse; - -export type CaseActionType = ActionType< - CaseConfiguration, - {}, - CaseExecutorParams, - CaseExecutorResponse | {} ->; - -export type CaseActionTypeExecutorOptions = ActionTypeExecutorOptions< - CaseConfiguration, - {}, - CaseExecutorParams ->; diff --git a/x-pack/plugins/cases/server/connectors/case/validators.ts b/x-pack/plugins/cases/server/connectors/case/validators.ts deleted file mode 100644 index 163959eec4a6a..0000000000000 --- a/x-pack/plugins/cases/server/connectors/case/validators.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { Connector } from './types'; -import { ConnectorTypes } from '../../../common/api'; - -export const validateConnector = (connector: Connector) => { - if (connector.type === ConnectorTypes.none && connector.fields !== null) { - return 'Fields must be set to null for connectors of type .none'; - } -}; diff --git a/x-pack/plugins/cases/server/connectors/index.ts b/x-pack/plugins/cases/server/connectors/index.ts index b5dc1cc4a8ff9..78b83223a3d66 100644 --- a/x-pack/plugins/cases/server/connectors/index.ts +++ b/x-pack/plugins/cases/server/connectors/index.ts @@ -5,69 +5,5 @@ * 2.0. */ -import { - RegisterConnectorsArgs, - CommentSchemaType, - ContextTypeGeneratedAlertType, - ContextTypeAlertSchemaType, -} from './types'; -import { getActionType as getCaseConnector } from './case'; -import { CommentRequest, CommentType } from '../../common/api'; - export * from './types'; -export { transformConnectorComment } from './case'; export { casesConnectors } from './factory'; - -/** - * Separator used for creating a json parsable array from the mustache syntax that the alerting framework - * sends. - */ -export const separator = '__SEPARATOR__'; - -export const registerConnectors = ({ - registerActionType, - logger, - factory, -}: RegisterConnectorsArgs) => { - registerActionType( - getCaseConnector({ - logger, - factory, - }) - ); -}; - -export const isCommentGeneratedAlert = ( - comment: CommentSchemaType | CommentRequest -): comment is ContextTypeGeneratedAlertType => { - return ( - comment.type === CommentType.generatedAlert && - 'alerts' in comment && - comment.alerts !== undefined - ); -}; - -export const isCommentAlert = ( - comment: CommentSchemaType -): comment is ContextTypeAlertSchemaType => { - return comment.type === CommentType.alert; -}; - -interface AlertIDIndex { - _id: string; - _index: string; - ruleId: string; - ruleName: string; -} - -/** - * Creates the format that the connector's parser is expecting, it should result in something like this: - * [{"_id":"1","_index":"index1"}__SEPARATOR__{"_id":"id2","_index":"index2"}__SEPARATOR__] - * - * This should only be used for testing purposes. - */ -export function createAlertsString(alerts: AlertIDIndex[]) { - return `[${alerts.reduce((acc, alert) => { - return `${acc}${JSON.stringify(alert)}${separator}`; - }, '')}]`; -} diff --git a/x-pack/plugins/cases/server/connectors/types.ts b/x-pack/plugins/cases/server/connectors/types.ts index 3754dfd62b7c5..16f4efa3b1327 100644 --- a/x-pack/plugins/cases/server/connectors/types.ts +++ b/x-pack/plugins/cases/server/connectors/types.ts @@ -11,12 +11,6 @@ import { CasesClientGetAlertsResponse } from '../client/alerts/types'; import { CasesClientFactory } from '../client/factory'; import { RegisterActionType } from '../types'; -export type { - ContextTypeGeneratedAlertType, - CommentSchemaType, - ContextTypeAlertSchemaType, -} from './case/schema'; - export interface GetActionTypeParams { logger: Logger; factory: CasesClientFactory; diff --git a/x-pack/plugins/cases/server/plugin.ts b/x-pack/plugins/cases/server/plugin.ts index 21ee1313ddb11..8d2582d9c5857 100644 --- a/x-pack/plugins/cases/server/plugin.ts +++ b/x-pack/plugins/cases/server/plugin.ts @@ -13,7 +13,7 @@ import { PluginSetupContract as ActionsPluginSetup, PluginStartContract as ActionsPluginStart, } from '../../actions/server'; -import { APP_ID, ENABLE_CASE_CONNECTOR } from '../common/constants'; +import { APP_ID } from '../common/constants'; import { initCaseApi } from './routes/api'; import { @@ -22,11 +22,9 @@ import { caseConnectorMappingsSavedObjectType, createCaseSavedObjectType, caseUserActionSavedObjectType, - subCaseSavedObjectType, } from './saved_object_types'; import { CasesClient } from './client'; -import { registerConnectors } from './connectors'; import type { CasesRequestHandlerContext } from './types'; import { CasesClientFactory } from './client/factory'; import { SpacesPluginStart } from '../../spaces/server'; @@ -104,15 +102,6 @@ export class CasePlugin { logger: this.log, router, }); - - if (ENABLE_CASE_CONNECTOR) { - core.savedObjects.registerType(subCaseSavedObjectType); - registerConnectors({ - registerActionType: plugins.actions.registerType, - logger: this.log, - factory: this.clientFactory, - }); - } } public start(core: CoreStart, plugins: PluginsStart): PluginStartContract { diff --git a/x-pack/plugins/cases/server/routes/api/__fixtures__/mock_saved_objects.ts b/x-pack/plugins/cases/server/routes/api/__fixtures__/mock_saved_objects.ts index 6bff6c7d21725..a05c9e320d897 100644 --- a/x-pack/plugins/cases/server/routes/api/__fixtures__/mock_saved_objects.ts +++ b/x-pack/plugins/cases/server/routes/api/__fixtures__/mock_saved_objects.ts @@ -7,10 +7,8 @@ import { SavedObject } from 'kibana/server'; import { - AssociationType, CaseAttributes, CaseStatuses, - CaseType, CommentAttributes, CommentType, ConnectorTypes, @@ -41,7 +39,6 @@ export const mockCases: Array> = [ title: 'Super Bad Security Issue', status: CaseStatuses.open, tags: ['defacement'], - type: CaseType.individual, updated_at: '2019-11-25T21:54:48.952Z', updated_by: { full_name: 'elastic', @@ -80,7 +77,6 @@ export const mockCases: Array> = [ title: 'Damaging Data Destruction Detected', status: CaseStatuses.open, tags: ['Data Destruction'], - type: CaseType.individual, updated_at: '2019-11-25T22:32:00.900Z', updated_by: { full_name: 'elastic', @@ -119,7 +115,6 @@ export const mockCases: Array> = [ title: 'Another bad one', status: CaseStatuses.open, tags: ['LOLBins'], - type: CaseType.individual, updated_at: '2019-11-25T22:32:17.947Z', updated_by: { full_name: 'elastic', @@ -162,7 +157,6 @@ export const mockCases: Array> = [ status: CaseStatuses.closed, title: 'Another bad one', tags: ['LOLBins'], - type: CaseType.individual, updated_at: '2019-11-25T22:32:17.947Z', updated_by: { full_name: 'elastic', @@ -194,7 +188,6 @@ export const mockCaseComments: Array> = [ type: 'cases-comment', id: 'mock-comment-1', attributes: { - associationType: AssociationType.case, comment: 'Wow, good luck catching that bad meanie!', type: CommentType.user, created_at: '2019-11-25T21:55:00.177Z', @@ -227,7 +220,6 @@ export const mockCaseComments: Array> = [ type: 'cases-comment', id: 'mock-comment-2', attributes: { - associationType: AssociationType.case, comment: 'Well I decided to update my comment. So what? Deal with it.', type: CommentType.user, created_at: '2019-11-25T21:55:14.633Z', @@ -261,7 +253,6 @@ export const mockCaseComments: Array> = [ type: 'cases-comment', id: 'mock-comment-3', attributes: { - associationType: AssociationType.case, comment: 'Wow, good luck catching that bad meanie!', type: CommentType.user, created_at: '2019-11-25T22:32:30.608Z', @@ -294,7 +285,6 @@ export const mockCaseComments: Array> = [ type: 'cases-comment', id: 'mock-comment-4', attributes: { - associationType: AssociationType.case, type: CommentType.alert, index: 'test-index', alertId: 'test-id', @@ -332,7 +322,6 @@ export const mockCaseComments: Array> = [ type: 'cases-comment', id: 'mock-comment-5', attributes: { - associationType: AssociationType.case, type: CommentType.alert, index: 'test-index-2', alertId: 'test-id-2', @@ -370,8 +359,7 @@ export const mockCaseComments: Array> = [ type: 'cases-comment', id: 'mock-comment-6', attributes: { - associationType: AssociationType.case, - type: CommentType.generatedAlert, + type: CommentType.alert, index: 'test-index', alertId: 'test-id', created_at: '2019-11-25T22:32:30.608Z', diff --git a/x-pack/plugins/cases/server/routes/api/cases/get_case.ts b/x-pack/plugins/cases/server/routes/api/cases/get_case.ts index b9c50a86fb8fe..f8b85313482f4 100644 --- a/x-pack/plugins/cases/server/routes/api/cases/get_case.ts +++ b/x-pack/plugins/cases/server/routes/api/cases/get_case.ts @@ -21,7 +21,6 @@ export function initGetCaseApi({ router, logger }: RouteDeps) { }), query: schema.object({ includeComments: schema.boolean({ defaultValue: true }), - includeSubCaseComments: schema.maybe(schema.boolean({ defaultValue: false })), }), }, }, @@ -34,12 +33,11 @@ export function initGetCaseApi({ router, logger }: RouteDeps) { body: await casesClient.cases.get({ id, includeComments: request.query.includeComments, - includeSubCaseComments: request.query.includeSubCaseComments, }), }); } catch (error) { logger.error( - `Failed to retrieve case in route case id: ${request.params.case_id} \ninclude comments: ${request.query.includeComments} \ninclude sub comments: ${request.query.includeSubCaseComments}: ${error}` + `Failed to retrieve case in route case id: ${request.params.case_id} \ninclude comments: ${request.query.includeComments}: ${error}` ); return response.customError(wrapError(error)); } @@ -55,7 +53,6 @@ export function initGetCaseApi({ router, logger }: RouteDeps) { }), query: schema.object({ includeComments: schema.boolean({ defaultValue: true }), - includeSubCaseComments: schema.maybe(schema.boolean({ defaultValue: false })), }), }, }, @@ -68,12 +65,11 @@ export function initGetCaseApi({ router, logger }: RouteDeps) { body: await casesClient.cases.resolve({ id, includeComments: request.query.includeComments, - includeSubCaseComments: request.query.includeSubCaseComments, }), }); } catch (error) { logger.error( - `Failed to retrieve case in resolve route case id: ${request.params.case_id} \ninclude comments: ${request.query.includeComments} \ninclude sub comments: ${request.query.includeSubCaseComments}: ${error}` + `Failed to retrieve case in resolve route case id: ${request.params.case_id} \ninclude comments: ${request.query.includeComments}: ${error}` ); return response.customError(wrapError(error)); } diff --git a/x-pack/plugins/cases/server/routes/api/comments/delete_all_comments.ts b/x-pack/plugins/cases/server/routes/api/comments/delete_all_comments.ts index a41d4683af2d0..d79f90ac43935 100644 --- a/x-pack/plugins/cases/server/routes/api/comments/delete_all_comments.ts +++ b/x-pack/plugins/cases/server/routes/api/comments/delete_all_comments.ts @@ -18,11 +18,6 @@ export function initDeleteAllCommentsApi({ router, logger }: RouteDeps) { params: schema.object({ case_id: schema.string(), }), - query: schema.maybe( - schema.object({ - subCaseId: schema.maybe(schema.string()), - }) - ), }, }, async (context, request, response) => { @@ -31,13 +26,12 @@ export function initDeleteAllCommentsApi({ router, logger }: RouteDeps) { await client.attachments.deleteAll({ caseID: request.params.case_id, - subCaseID: request.query?.subCaseId, }); return response.noContent(); } catch (error) { logger.error( - `Failed to delete all comments in route case id: ${request.params.case_id} sub case id: ${request.query?.subCaseId}: ${error}` + `Failed to delete all comments in route case id: ${request.params.case_id}: ${error}` ); return response.customError(wrapError(error)); } diff --git a/x-pack/plugins/cases/server/routes/api/comments/delete_comment.ts b/x-pack/plugins/cases/server/routes/api/comments/delete_comment.ts index f145fc62efc8a..b27be46d7220d 100644 --- a/x-pack/plugins/cases/server/routes/api/comments/delete_comment.ts +++ b/x-pack/plugins/cases/server/routes/api/comments/delete_comment.ts @@ -20,11 +20,6 @@ export function initDeleteCommentApi({ router, logger }: RouteDeps) { case_id: schema.string(), comment_id: schema.string(), }), - query: schema.maybe( - schema.object({ - subCaseId: schema.maybe(schema.string()), - }) - ), }, }, async (context, request, response) => { @@ -32,14 +27,13 @@ export function initDeleteCommentApi({ router, logger }: RouteDeps) { const client = await context.cases.getCasesClient(); await client.attachments.delete({ attachmentID: request.params.comment_id, - subCaseID: request.query?.subCaseId, caseID: request.params.case_id, }); return response.noContent(); } catch (error) { logger.error( - `Failed to delete comment in route case id: ${request.params.case_id} comment id: ${request.params.comment_id} sub case id: ${request.query?.subCaseId}: ${error}` + `Failed to delete comment in route case id: ${request.params.case_id} comment id: ${request.params.comment_id}: ${error}` ); return response.customError(wrapError(error)); } diff --git a/x-pack/plugins/cases/server/routes/api/comments/get_all_comment.ts b/x-pack/plugins/cases/server/routes/api/comments/get_all_comment.ts index b916e22c6b0ed..d7f95d503c394 100644 --- a/x-pack/plugins/cases/server/routes/api/comments/get_all_comment.ts +++ b/x-pack/plugins/cases/server/routes/api/comments/get_all_comment.ts @@ -19,12 +19,6 @@ export function initGetAllCommentsApi({ router, logger }: RouteDeps) { params: schema.object({ case_id: schema.string(), }), - query: schema.maybe( - schema.object({ - includeSubCaseComments: schema.maybe(schema.boolean()), - subCaseId: schema.maybe(schema.string()), - }) - ), }, }, async (context, request, response) => { @@ -34,13 +28,11 @@ export function initGetAllCommentsApi({ router, logger }: RouteDeps) { return response.ok({ body: await client.attachments.getAll({ caseID: request.params.case_id, - includeSubCaseComments: request.query?.includeSubCaseComments, - subCaseID: request.query?.subCaseId, }), }); } catch (error) { logger.error( - `Failed to get all comments in route case id: ${request.params.case_id} include sub case comments: ${request.query?.includeSubCaseComments} sub case id: ${request.query?.subCaseId}: ${error}` + `Failed to get all comments in route case id: ${request.params.case_id}: ${error}` ); return response.customError(wrapError(error)); } diff --git a/x-pack/plugins/cases/server/routes/api/comments/patch_comment.ts b/x-pack/plugins/cases/server/routes/api/comments/patch_comment.ts index d6ac39f11b91e..5f9d885178404 100644 --- a/x-pack/plugins/cases/server/routes/api/comments/patch_comment.ts +++ b/x-pack/plugins/cases/server/routes/api/comments/patch_comment.ts @@ -24,11 +24,6 @@ export function initPatchCommentApi({ router, logger }: RouteDeps) { params: schema.object({ case_id: schema.string(), }), - query: schema.maybe( - schema.object({ - subCaseId: schema.maybe(schema.string()), - }) - ), body: escapeHatch, }, }, @@ -44,13 +39,12 @@ export function initPatchCommentApi({ router, logger }: RouteDeps) { return response.ok({ body: await client.attachments.update({ caseID: request.params.case_id, - subCaseID: request.query?.subCaseId, updateRequest: query, }), }); } catch (error) { logger.error( - `Failed to patch comment in route case id: ${request.params.case_id} sub case id: ${request.query?.subCaseId}: ${error}` + `Failed to patch comment in route case id: ${request.params.case_id}: ${error}` ); return response.customError(wrapError(error)); } diff --git a/x-pack/plugins/cases/server/routes/api/comments/post_comment.ts b/x-pack/plugins/cases/server/routes/api/comments/post_comment.ts index 1919aef7b72b4..ed9c917008417 100644 --- a/x-pack/plugins/cases/server/routes/api/comments/post_comment.ts +++ b/x-pack/plugins/cases/server/routes/api/comments/post_comment.ts @@ -5,11 +5,10 @@ * 2.0. */ -import Boom from '@hapi/boom'; import { schema } from '@kbn/config-schema'; import { escapeHatch, wrapError } from '../utils'; import { RouteDeps } from '../types'; -import { CASE_COMMENTS_URL, ENABLE_CASE_CONNECTOR } from '../../../../common/constants'; +import { CASE_COMMENTS_URL } from '../../../../common/constants'; import { CommentRequest } from '../../../../common/api'; export function initPostCommentApi({ router, logger }: RouteDeps) { @@ -20,28 +19,17 @@ export function initPostCommentApi({ router, logger }: RouteDeps) { params: schema.object({ case_id: schema.string(), }), - query: schema.maybe( - schema.object({ - subCaseId: schema.maybe(schema.string()), - }) - ), body: escapeHatch, }, }, async (context, request, response) => { try { - if (!ENABLE_CASE_CONNECTOR && request.query?.subCaseId !== undefined) { - throw Boom.badRequest( - 'The `subCaseId` is not supported when the case connector feature is disabled' - ); - } - if (!context.cases) { return response.badRequest({ body: 'RouteHandlerContext is not registered for cases' }); } const casesClient = await context.cases.getCasesClient(); - const caseId = request.query?.subCaseId ?? request.params.case_id; + const caseId = request.params.case_id; const comment = request.body as CommentRequest; return response.ok({ @@ -49,7 +37,7 @@ export function initPostCommentApi({ router, logger }: RouteDeps) { }); } catch (error) { logger.error( - `Failed to post comment in route case id: ${request.params.case_id} sub case id: ${request.query?.subCaseId}: ${error}` + `Failed to post comment in route case id: ${request.params.case_id}: ${error}` ); return response.customError(wrapError(error)); } diff --git a/x-pack/plugins/cases/server/routes/api/index.ts b/x-pack/plugins/cases/server/routes/api/index.ts index f844505369f93..8298f7469f236 100644 --- a/x-pack/plugins/cases/server/routes/api/index.ts +++ b/x-pack/plugins/cases/server/routes/api/index.ts @@ -14,10 +14,7 @@ import { initPushCaseApi } from './cases/push_case'; import { initGetReportersApi } from './cases/reporters/get_reporters'; import { initGetCasesStatusApi } from './stats/get_status'; import { initGetTagsApi } from './cases/tags/get_tags'; -import { - initGetAllCaseUserActionsApi, - initGetAllSubCaseUserActionsApi, -} from './user_actions/get_all_user_actions'; +import { initGetAllCaseUserActionsApi } from './user_actions/get_all_user_actions'; import { initDeleteCommentApi } from './comments/delete_comment'; import { initDeleteAllCommentsApi } from './comments/delete_all_comments'; @@ -33,11 +30,6 @@ import { initPatchCaseConfigure } from './configure/patch_configure'; import { initPostCaseConfigure } from './configure/post_configure'; import { RouteDeps } from './types'; -import { initGetSubCaseApi } from './sub_case/get_sub_case'; -import { initPatchSubCasesApi } from './sub_case/patch_sub_cases'; -import { initFindSubCasesApi } from './sub_case/find_sub_cases'; -import { initDeleteSubCasesApi } from './sub_case/delete_sub_cases'; -import { ENABLE_CASE_CONNECTOR } from '../../../common/constants'; import { initGetCasesByAlertIdApi } from './cases/alerts/get_cases'; import { initGetAllAlertsAttachToCaseApi } from './comments/get_alerts'; import { initGetCaseMetricsApi } from './metrics/get_case_metrics'; @@ -61,15 +53,6 @@ export function initCaseApi(deps: RouteDeps) { initPushCaseApi(deps); initGetAllCaseUserActionsApi(deps); - if (ENABLE_CASE_CONNECTOR) { - // Sub cases - initGetAllSubCaseUserActionsApi(deps); - initGetSubCaseApi(deps); - initPatchSubCasesApi(deps); - initFindSubCasesApi(deps); - initDeleteSubCasesApi(deps); - } - // Comments initDeleteCommentApi(deps); initDeleteAllCommentsApi(deps); diff --git a/x-pack/plugins/cases/server/routes/api/sub_case/delete_sub_cases.ts b/x-pack/plugins/cases/server/routes/api/sub_case/delete_sub_cases.ts deleted file mode 100644 index 11b68b70390fe..0000000000000 --- a/x-pack/plugins/cases/server/routes/api/sub_case/delete_sub_cases.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { RouteDeps } from '../types'; -import { wrapError } from '../utils'; -import { SUB_CASES_PATCH_DEL_URL } from '../../../../common/constants'; - -export function initDeleteSubCasesApi({ router, logger }: RouteDeps) { - router.delete( - { - path: SUB_CASES_PATCH_DEL_URL, - validate: { - query: schema.object({ - ids: schema.arrayOf(schema.string()), - }), - }, - }, - async (context, request, response) => { - try { - const client = await context.cases.getCasesClient(); - await client.subCases.delete(request.query.ids); - - return response.noContent(); - } catch (error) { - logger.error( - `Failed to delete sub cases in route ids: ${JSON.stringify(request.query.ids)}: ${error}` - ); - return response.customError(wrapError(error)); - } - } - ); -} diff --git a/x-pack/plugins/cases/server/routes/api/sub_case/find_sub_cases.ts b/x-pack/plugins/cases/server/routes/api/sub_case/find_sub_cases.ts deleted file mode 100644 index 8ee5fa21c3a3e..0000000000000 --- a/x-pack/plugins/cases/server/routes/api/sub_case/find_sub_cases.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import Boom from '@hapi/boom'; - -import { pipe } from 'fp-ts/lib/pipeable'; -import { fold } from 'fp-ts/lib/Either'; -import { identity } from 'fp-ts/lib/function'; - -import { SUB_CASES_URL } from '../../../../common/constants'; -import { SubCasesFindRequestRt, throwErrors } from '../../../../common/api'; -import { RouteDeps } from '../types'; -import { escapeHatch, wrapError } from '../utils'; - -export function initFindSubCasesApi({ router, logger }: RouteDeps) { - router.get( - { - path: `${SUB_CASES_URL}/_find`, - validate: { - params: schema.object({ - case_id: schema.string(), - }), - query: escapeHatch, - }, - }, - async (context, request, response) => { - try { - const queryParams = pipe( - SubCasesFindRequestRt.decode(request.query), - fold(throwErrors(Boom.badRequest), identity) - ); - - const client = await context.cases.getCasesClient(); - return response.ok({ - body: await client.subCases.find({ - caseID: request.params.case_id, - queryParams, - }), - }); - } catch (error) { - logger.error( - `Failed to find sub cases in route case id: ${request.params.case_id}: ${error}` - ); - return response.customError(wrapError(error)); - } - } - ); -} diff --git a/x-pack/plugins/cases/server/routes/api/sub_case/get_sub_case.ts b/x-pack/plugins/cases/server/routes/api/sub_case/get_sub_case.ts deleted file mode 100644 index db3e29f5ed96e..0000000000000 --- a/x-pack/plugins/cases/server/routes/api/sub_case/get_sub_case.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; - -import { RouteDeps } from '../types'; -import { wrapError } from '../utils'; -import { SUB_CASE_DETAILS_URL } from '../../../../common/constants'; - -export function initGetSubCaseApi({ router, logger }: RouteDeps) { - router.get( - { - path: SUB_CASE_DETAILS_URL, - validate: { - params: schema.object({ - case_id: schema.string(), - sub_case_id: schema.string(), - }), - query: schema.object({ - includeComments: schema.boolean({ defaultValue: true }), - }), - }, - }, - async (context, request, response) => { - try { - const client = await context.cases.getCasesClient(); - - return response.ok({ - body: await client.subCases.get({ - id: request.params.sub_case_id, - includeComments: request.query.includeComments, - }), - }); - } catch (error) { - logger.error( - `Failed to get sub case in route case id: ${request.params.case_id} sub case id: ${request.params.sub_case_id} include comments: ${request.query?.includeComments}: ${error}` - ); - return response.customError(wrapError(error)); - } - } - ); -} diff --git a/x-pack/plugins/cases/server/routes/api/sub_case/patch_sub_cases.ts b/x-pack/plugins/cases/server/routes/api/sub_case/patch_sub_cases.ts deleted file mode 100644 index 1fb260453d188..0000000000000 --- a/x-pack/plugins/cases/server/routes/api/sub_case/patch_sub_cases.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { SubCasesPatchRequest } from '../../../../common/api'; -import { SUB_CASES_PATCH_DEL_URL } from '../../../../common/constants'; -import { RouteDeps } from '../types'; -import { escapeHatch, wrapError } from '../utils'; - -export function initPatchSubCasesApi({ router, logger }: RouteDeps) { - router.patch( - { - path: SUB_CASES_PATCH_DEL_URL, - validate: { - body: escapeHatch, - }, - }, - async (context, request, response) => { - try { - const casesClient = await context.cases.getCasesClient(); - const subCases = request.body as SubCasesPatchRequest; - return response.ok({ - body: await casesClient.subCases.update(subCases), - }); - } catch (error) { - logger.error(`Failed to patch sub cases in route: ${error}`); - return response.customError(wrapError(error)); - } - } - ); -} diff --git a/x-pack/plugins/cases/server/routes/api/user_actions/get_all_user_actions.ts b/x-pack/plugins/cases/server/routes/api/user_actions/get_all_user_actions.ts index 5944ff6176d78..cf258c284568b 100644 --- a/x-pack/plugins/cases/server/routes/api/user_actions/get_all_user_actions.ts +++ b/x-pack/plugins/cases/server/routes/api/user_actions/get_all_user_actions.ts @@ -9,7 +9,7 @@ import { schema } from '@kbn/config-schema'; import { RouteDeps } from '../types'; import { wrapError } from '../utils'; -import { CASE_USER_ACTIONS_URL, SUB_CASE_USER_ACTIONS_URL } from '../../../../common/constants'; +import { CASE_USER_ACTIONS_URL } from '../../../../common/constants'; export function initGetAllCaseUserActionsApi({ router, logger }: RouteDeps) { router.get( @@ -42,37 +42,3 @@ export function initGetAllCaseUserActionsApi({ router, logger }: RouteDeps) { } ); } - -export function initGetAllSubCaseUserActionsApi({ router, logger }: RouteDeps) { - router.get( - { - path: SUB_CASE_USER_ACTIONS_URL, - validate: { - params: schema.object({ - case_id: schema.string(), - sub_case_id: schema.string(), - }), - }, - }, - async (context, request, response) => { - try { - if (!context.cases) { - return response.badRequest({ body: 'RouteHandlerContext is not registered for cases' }); - } - - const casesClient = await context.cases.getCasesClient(); - const caseId = request.params.case_id; - const subCaseId = request.params.sub_case_id; - - return response.ok({ - body: await casesClient.userActions.getAll({ caseId, subCaseId }), - }); - } catch (error) { - logger.error( - `Failed to retrieve sub case user actions in route case id: ${request.params.case_id} sub case id: ${request.params.sub_case_id}: ${error}` - ); - return response.customError(wrapError(error)); - } - } - ); -} diff --git a/x-pack/plugins/cases/server/saved_object_types/cases.ts b/x-pack/plugins/cases/server/saved_object_types/cases.ts index b94b387798262..31eadd9bd5142 100644 --- a/x-pack/plugins/cases/server/saved_object_types/cases.ts +++ b/x-pack/plugins/cases/server/saved_object_types/cases.ts @@ -126,10 +126,6 @@ export const createCaseSavedObjectType = ( tags: { type: 'keyword', }, - // collection or individual - type: { - type: 'keyword', - }, updated_at: { type: 'date', }, diff --git a/x-pack/plugins/cases/server/saved_object_types/comments.ts b/x-pack/plugins/cases/server/saved_object_types/comments.ts index bc0993a345a5b..06a15fab14e43 100644 --- a/x-pack/plugins/cases/server/saved_object_types/comments.ts +++ b/x-pack/plugins/cases/server/saved_object_types/comments.ts @@ -20,9 +20,6 @@ export const createCaseCommentSavedObjectType = ({ convertToMultiNamespaceTypeVersion: '8.0.0', mappings: { properties: { - associationType: { - type: 'keyword', - }, comment: { type: 'text', }, diff --git a/x-pack/plugins/cases/server/saved_object_types/index.ts b/x-pack/plugins/cases/server/saved_object_types/index.ts index f6b87d1d480c1..490c618930d30 100644 --- a/x-pack/plugins/cases/server/saved_object_types/index.ts +++ b/x-pack/plugins/cases/server/saved_object_types/index.ts @@ -6,7 +6,6 @@ */ export { createCaseSavedObjectType } from './cases'; -export { subCaseSavedObjectType } from './sub_case'; export { caseConfigureSavedObjectType } from './configure'; export { createCaseCommentSavedObjectType } from './comments'; export { caseUserActionSavedObjectType } from './user_actions'; diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/cases.test.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/cases.test.ts index 385ea69fd843b..2510a80e62b3a 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/cases.test.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/cases.test.ts @@ -15,7 +15,7 @@ import { import { CASE_SAVED_OBJECT } from '../../../common/constants'; import { getNoneCaseConnector } from '../../common/utils'; import { createExternalService, ESCaseConnectorWithId } from '../../services/test_utils'; -import { caseConnectorIdMigration } from './cases'; +import { caseConnectorIdMigration, removeCaseType } from './cases'; // eslint-disable-next-line @typescript-eslint/naming-convention const create_7_14_0_case = ({ @@ -350,4 +350,25 @@ describe('case migrations', () => { `); }); }); + + describe('removeCaseType', () => { + it('removes the type field from the document', () => { + const doc = { + id: '123', + attributes: { + type: 'individual', + title: 'case', + }, + type: 'abc', + references: [], + }; + + expect(removeCaseType(doc)).toEqual({ + ...doc, + attributes: { + title: doc.attributes.title, + }, + }); + }); + }); }); diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/cases.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/cases.ts index 9e315d90372d0..7ab22781d77e6 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/cases.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/cases.ts @@ -7,13 +7,14 @@ /* eslint-disable @typescript-eslint/naming-convention */ +import { cloneDeep, unset } from 'lodash'; import { addOwnerToSO, SanitizedCaseOwner } from '.'; import { SavedObjectUnsanitizedDoc, SavedObjectSanitizedDoc, } from '../../../../../../src/core/server'; import { ESConnectorFields } from '../../services'; -import { ConnectorTypes, CaseType } from '../../../common/api'; +import { ConnectorTypes } from '../../../common/api'; import { CONNECTOR_ID_REFERENCE_NAME, PUSH_CONNECTOR_ID_REFERENCE_NAME, @@ -22,6 +23,7 @@ import { transformConnectorIdToReference, transformPushConnectorIdToReference, } from './user_actions/connector_id'; +import { CASE_TYPE_INDIVIDUAL } from './constants'; interface UnsanitizedCaseConnector { connector_id: string; @@ -78,6 +80,15 @@ export const caseConnectorIdMigration = ( }; }; +export const removeCaseType = ( + doc: SavedObjectUnsanitizedDoc> +): SavedObjectSanitizedDoc => { + const docCopy = cloneDeep(doc); + unset(docCopy, 'attributes.type'); + + return { ...docCopy, references: doc.references ?? [] }; +}; + export const caseMigrations = { '7.10.0': ( doc: SavedObjectUnsanitizedDoc @@ -120,7 +131,7 @@ export const caseMigrations = { ...doc, attributes: { ...doc.attributes, - type: CaseType.individual, + type: CASE_TYPE_INDIVIDUAL, connector: { ...doc.attributes.connector, fields: @@ -138,4 +149,5 @@ export const caseMigrations = { return addOwnerToSO(doc); }, '7.15.0': caseConnectorIdMigration, + '8.1.0': removeCaseType, }; diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/comments.test.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/comments.test.ts index 77a9382f12389..dcc7b63e53bde 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/comments.test.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/comments.test.ts @@ -9,6 +9,7 @@ import { createCommentsMigrations, mergeMigrationFunctionMaps, migrateByValueLensVisualizations, + removeAssociationType, removeRuleInformation, stringifyCommentWithoutTrailingNewline, } from './comments'; @@ -31,6 +32,7 @@ import { MigrateFunctionsObject, } from '../../../../../../src/plugins/kibana_utils/common'; import { SerializableRecord } from '@kbn/utility-types'; +import { GENERATED_ALERT, SUB_CASE_SAVED_OBJECT } from './constants'; describe('comments migrations', () => { const migrations = createCommentsMigrations({ @@ -438,7 +440,7 @@ describe('comments migrations', () => { id: '123', type: 'abc', attributes: { - type: CommentType.generatedAlert, + type: GENERATED_ALERT, rule: { id: '123', name: 'hello', @@ -473,4 +475,62 @@ describe('comments migrations', () => { }); }); }); + + describe('removeAssociationType', () => { + it('removes the associationType field from the document', () => { + const doc = { + id: '123', + attributes: { + type: 'user', + associationType: 'case', + }, + type: 'abc', + references: [], + }; + + expect(removeAssociationType(doc)).toEqual({ + ...doc, + attributes: { + type: doc.attributes.type, + }, + }); + }); + + it('removes the sub case reference', () => { + const doc = { + id: '123', + attributes: { + type: 'user', + associationType: 'case', + }, + type: 'abc', + references: [ + { + type: SUB_CASE_SAVED_OBJECT, + id: 'test-id', + name: 'associated-sub-case', + }, + { + type: 'action', + id: 'action-id', + name: 'action-name', + }, + ], + }; + + expect(removeAssociationType(doc)).toEqual({ + ...doc, + attributes: { + type: doc.attributes.type, + }, + references: [ + { + type: 'action', + id: 'action-id', + name: 'action-name', + }, + ], + }); + }); + }); }); diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/comments.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/comments.ts index 4ca28cedb494b..e30d138cc657f 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/comments.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/comments.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { mapValues, trimEnd, mergeWith } from 'lodash'; +import { mapValues, trimEnd, mergeWith, cloneDeep, unset } from 'lodash'; import type { SerializableRecord } from '@kbn/utility-types'; import { MigrateFunction, @@ -19,7 +19,7 @@ import { SavedObjectMigrationContext, } from '../../../../../../src/core/server'; import { LensServerPluginSetup } from '../../../../lens/server'; -import { CommentType, AssociationType } from '../../../common/api'; +import { CommentType } from '../../../common/api'; import { isLensMarkdownNode, LensMarkdownNode, @@ -29,6 +29,7 @@ import { } from '../../../common/utils/markdown_plugins/utils'; import { addOwnerToSO, SanitizedCaseOwner } from '.'; import { logError } from './utils'; +import { GENERATED_ALERT, SUB_CASE_SAVED_OBJECT } from './constants'; interface UnsanitizedComment { comment: string; @@ -40,7 +41,11 @@ interface SanitizedComment { type: CommentType; } -interface SanitizedCommentForSubCases { +enum AssociationType { + case = 'case', +} + +interface SanitizedCommentWithAssociation { associationType: AssociationType; rule?: { id: string | null; name: string | null }; } @@ -75,8 +80,8 @@ export const createCommentsMigrations = ( }, '7.12.0': ( doc: SavedObjectUnsanitizedDoc - ): SavedObjectSanitizedDoc => { - let attributes: SanitizedCommentForSubCases & UnsanitizedComment = { + ): SavedObjectSanitizedDoc => { + let attributes: SanitizedCommentWithAssociation & UnsanitizedComment = { ...doc.attributes, associationType: AssociationType.case, }; @@ -107,6 +112,7 @@ export const createCommentsMigrations = ( * The downside is it incurs extra query overhead. **/ '8.0.0': removeRuleInformation, + '8.1.0': removeAssociationType, }; return mergeMigrationFunctionMaps(commentsMigrations, embeddableMigrations); @@ -188,10 +194,7 @@ export const mergeMigrationFunctionMaps = ( export const removeRuleInformation = ( doc: SavedObjectUnsanitizedDoc> ): SavedObjectSanitizedDoc => { - if ( - doc.attributes.type === CommentType.alert || - doc.attributes.type === CommentType.generatedAlert - ) { + if (doc.attributes.type === CommentType.alert || doc.attributes.type === GENERATED_ALERT) { return { ...doc, attributes: { @@ -210,3 +213,16 @@ export const removeRuleInformation = ( references: doc.references ?? [], }; }; + +export const removeAssociationType = ( + doc: SavedObjectUnsanitizedDoc> +): SavedObjectSanitizedDoc> => { + const docCopy = cloneDeep(doc); + unset(docCopy, 'attributes.associationType'); + + return { + ...docCopy, + references: + docCopy.references?.filter((reference) => reference.type !== SUB_CASE_SAVED_OBJECT) ?? [], + }; +}; diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/constants.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/constants.ts new file mode 100644 index 0000000000000..9f428af939a06 --- /dev/null +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/constants.ts @@ -0,0 +1,14 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* + * Before 8.0.0 we had a few types of cases, comments, and other fields that were never actually used, I'm preserving them here for the migrations + */ +export const GENERATED_ALERT = 'generated_alert'; +export const COMMENT_ASSOCIATION_TYPE = 'case'; +export const CASE_TYPE_INDIVIDUAL = 'individual'; +export const SUB_CASE_SAVED_OBJECT = 'cases-sub-case'; diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/index.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/index.ts index 105692b667fb5..be656abb2d42c 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/index.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/index.ts @@ -39,11 +39,3 @@ export const connectorMappingsMigrations = { return addOwnerToSO(doc); }, }; - -export const subCasesMigrations = { - '7.14.0': ( - doc: SavedObjectUnsanitizedDoc> - ): SavedObjectSanitizedDoc => { - return addOwnerToSO(doc); - }, -}; diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/alerts.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/alerts.ts index b2a825b80fd6e..697514b1777f6 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/alerts.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/alerts.ts @@ -11,6 +11,7 @@ import { SavedObjectUnsanitizedDoc, } from 'kibana/server'; import { CommentRequestAlertType, CommentType } from '../../../../common/api'; +import { GENERATED_ALERT } from '../constants'; import { logError } from '../utils'; import { UserActionVersion800 } from './types'; @@ -85,7 +86,9 @@ function isCreateComment(action?: string, actionFields?: string[]): boolean { ); } -type AlertCommentOptional = Partial; +type AlertCommentOptional = Partial> & { + type: CommentType.alert | typeof GENERATED_ALERT; +}; function isAlertObject(data?: unknown | null): boolean { const unsafeAlertData = data as AlertCommentOptional; @@ -93,7 +96,6 @@ function isAlertObject(data?: unknown | null): boolean { return ( unsafeAlertData !== undefined && unsafeAlertData !== null && - (unsafeAlertData.type === CommentType.generatedAlert || - unsafeAlertData.type === CommentType.alert) + (unsafeAlertData.type === GENERATED_ALERT || unsafeAlertData.type === CommentType.alert) ); } diff --git a/x-pack/plugins/cases/server/saved_object_types/sub_case.ts b/x-pack/plugins/cases/server/saved_object_types/sub_case.ts deleted file mode 100644 index 469b27d4b40ba..0000000000000 --- a/x-pack/plugins/cases/server/saved_object_types/sub_case.ts +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { SavedObjectsType } from 'src/core/server'; -import { SUB_CASE_SAVED_OBJECT } from '../../common/constants'; -import { subCasesMigrations } from './migrations'; - -export const subCaseSavedObjectType: SavedObjectsType = { - name: SUB_CASE_SAVED_OBJECT, - hidden: true, - namespaceType: 'multiple-isolated', - convertToMultiNamespaceTypeVersion: '8.0.0', - mappings: { - properties: { - closed_at: { - type: 'date', - }, - closed_by: { - properties: { - username: { - type: 'keyword', - }, - full_name: { - type: 'keyword', - }, - email: { - type: 'keyword', - }, - }, - }, - created_at: { - type: 'date', - }, - created_by: { - properties: { - username: { - type: 'keyword', - }, - full_name: { - type: 'keyword', - }, - email: { - type: 'keyword', - }, - }, - }, - owner: { - type: 'keyword', - }, - status: { - type: 'keyword', - }, - updated_at: { - type: 'date', - }, - updated_by: { - properties: { - username: { - type: 'keyword', - }, - full_name: { - type: 'keyword', - }, - email: { - type: 'keyword', - }, - }, - }, - }, - }, - migrations: subCasesMigrations, -}; diff --git a/x-pack/plugins/cases/server/scripts/sub_cases/README.md b/x-pack/plugins/cases/server/scripts/sub_cases/README.md deleted file mode 100644 index 389fc53856db8..0000000000000 --- a/x-pack/plugins/cases/server/scripts/sub_cases/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# Sub Cases Helper Script - -This script makes interacting with sub cases easier (creating, deleting, retrieving, etc). - -To run the script, first `cd x-pack/plugins/cases/server/scripts` - -## Showing the help - -```bash -yarn test:sub-cases help -``` - -Sub command help - -```bash -yarn test:sub-cases help -``` - -## Generating alerts - -This will generate a new case and sub case if one does not exist and then attach a group -of alerts to it. - -```bash -yarn test:sub-cases alerts --ids id1 id2 id3 -``` - -## Deleting a collection - -This will delete a case that has sub cases. - -```bash -yarn test:sub-cases delete -``` - -## Find sub cases - -This will find sub cases attached to a collection. - -```bash -yarn test:sub-cases find [status] -``` - -Example: - -```bash -yarn test:sub-cases find 6c9e0490-64dc-11eb-92be-09d246866276 -``` - -Response: - -```bash -{ - "page": 1, - "per_page": 1, - "total": 1, - "subCases": [ - { - "id": "6dd6d2b0-64dc-11eb-92be-09d246866276", - "version": "WzUzNDMsMV0=", - "comments": [], - "totalComment": 0, - "totalAlerts": 0, - "closed_at": null, - "closed_by": null, - "created_at": "2021-02-01T22:25:46.323Z", - "status": "open", - "updated_at": "2021-02-01T22:25:46.323Z", - "updated_by": { - "full_name": null, - "email": null, - "username": "elastic" - } - } - ], - "count_open_cases": 0, - "count_in_progress_cases": 0, - "count_closed_cases": 0 -} -``` diff --git a/x-pack/plugins/cases/server/scripts/sub_cases/index.ts b/x-pack/plugins/cases/server/scripts/sub_cases/index.ts deleted file mode 100644 index 75a896a4b81fd..0000000000000 --- a/x-pack/plugins/cases/server/scripts/sub_cases/index.ts +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable no-console */ -/* eslint-disable no-process-exit */ - -import yargs from 'yargs'; -import { ToolingLog } from '@kbn/dev-utils'; -import { KbnClient } from '@kbn/test'; -import { CaseResponse, CaseType, CommentType, ConnectorTypes } from '../../../common/api'; -import { CASES_URL, SECURITY_SOLUTION_OWNER } from '../../../common/constants'; -import { ActionResult, ActionTypeExecutorResult } from '../../../../actions/common'; -import { ContextTypeGeneratedAlertType, createAlertsString } from '../../connectors'; -import { - getCreateConnectorUrl, - getExecuteConnectorUrl, -} from '../../../common/utils/connectors_api'; - -main(); - -function createClient(argv: any): KbnClient { - return new KbnClient({ - log: new ToolingLog({ - level: 'info', - writeTo: process.stdout, - }), - url: argv.kibana, - }); -} - -async function handleFind(argv: any) { - const client = createClient(argv); - - try { - const res = await client.request({ - path: `${CASES_URL}/${argv.caseID}/sub_cases/_find`, - method: 'GET', - query: { - status: argv.status, - }, - }); - console.log(JSON.stringify(res.data, null, 2)); - } catch (e) { - console.error(e); - throw e; - } -} - -async function handleDelete(argv: any) { - const client = createClient(argv); - - try { - await client.request({ - path: `${CASES_URL}?ids=["${argv.id}"]`, - method: 'DELETE', - query: { - force: true, - }, - }); - } catch (e) { - console.error(e); - throw e; - } -} - -async function handleGenGroupAlerts(argv: any) { - const client = createClient(argv); - - try { - const createdAction = await client.request({ - path: getCreateConnectorUrl(), - method: 'POST', - body: { - name: 'A case connector', - actionTypeId: '.case', - config: {}, - }, - }); - - let caseID: string | undefined = argv.caseID as string | undefined; - - if (!caseID) { - console.log('Creating new case'); - const newCase = await client.request({ - path: CASES_URL, - method: 'POST', - body: { - description: 'This is a brand new case from generator script', - type: CaseType.collection, - title: 'Super Bad Security Issue', - tags: ['defacement'], - connector: { - id: 'none', - name: 'none', - type: ConnectorTypes.none, - fields: null, - }, - settings: { - syncAlerts: true, - }, - }, - }); - caseID = newCase.data.id; - } - - console.log('Case id: ', caseID); - const comment: ContextTypeGeneratedAlertType = { - owner: SECURITY_SOLUTION_OWNER, - type: CommentType.generatedAlert, - alerts: createAlertsString( - argv.ids.map((id: string) => ({ - _id: id, - _index: argv.signalsIndex, - ruleId: argv.ruleID, - ruleName: argv.ruleName, - })) - ), - }; - - const executeResp = await client.request>({ - path: getExecuteConnectorUrl(createdAction.data.id), - method: 'POST', - body: { - params: { - subAction: 'addComment', - subActionParams: { - caseId: caseID, - comment, - }, - }, - }, - }); - - if (executeResp.data.status !== 'ok') { - console.log( - 'Error received from actions api during execute: ', - JSON.stringify(executeResp.data, null, 2) - ); - process.exit(1); - } - - console.log('Execution response ', JSON.stringify(executeResp.data, null, 2)); - } catch (e) { - console.error(e); - throw e; - } -} - -async function main() { - // This returns before the async handlers do - // We need to convert this to commander instead I think - yargs(process.argv.slice(2)) - .help() - .options({ - kibana: { - alias: 'k', - describe: 'kibana url', - default: 'http://elastic:changeme@localhost:5601', - type: 'string', - }, - }) - .command({ - command: 'alerts', - aliases: ['gen', 'genAlerts'], - describe: 'generate a group of alerts', - builder: (args) => { - return args - .options({ - caseID: { - alias: 'c', - describe: 'case ID', - }, - ids: { - alias: 'a', - describe: 'alert ids', - type: 'array', - }, - signalsIndex: { - alias: 'i', - describe: 'siem signals index', - type: 'string', - default: '.siem-signals-default', - }, - ruleID: { - alias: 'ri', - describe: 'siem signals rule id', - type: 'string', - default: 'rule-id', - }, - ruleName: { - alias: 'rn', - describe: 'siem signals rule name', - type: 'string', - default: 'rule-name', - }, - }) - .demandOption(['ids']); - }, - handler: async (args) => { - return handleGenGroupAlerts(args); - }, - }) - .command({ - command: 'delete ', - describe: 'deletes a case', - builder: (args) => { - return args.positional('id', { - describe: 'case id', - type: 'string', - }); - }, - handler: async (args) => { - return handleDelete(args); - }, - }) - .command({ - command: 'find [status]', - describe: 'gets all sub cases', - builder: (args) => { - return args - .positional('caseID', { describe: 'case id', type: 'string' }) - .positional('status', { - describe: 'filter by status', - type: 'string', - }); - }, - handler: async (args) => { - return handleFind(args); - }, - }) - .demandCommand() - .parse(); - - console.log('completed'); -} diff --git a/x-pack/plugins/cases/server/services/alerts/index.ts b/x-pack/plugins/cases/server/services/alerts/index.ts index e52c83df6ce6f..7444159a00bb0 100644 --- a/x-pack/plugins/cases/server/services/alerts/index.ts +++ b/x-pack/plugins/cases/server/services/alerts/index.ts @@ -10,7 +10,7 @@ import { isEmpty } from 'lodash'; import { ElasticsearchClient, Logger } from 'kibana/server'; import { CaseStatuses } from '../../../common/api'; -import { MAX_ALERTS_PER_SUB_CASE, MAX_CONCURRENT_SEARCHES } from '../../../common/constants'; +import { MAX_ALERTS_PER_CASE, MAX_CONCURRENT_SEARCHES } from '../../../common/constants'; import { createCaseError } from '../../common/error'; import { AlertInfo } from '../../common/types'; import { UpdateAlertRequest } from '../../client/alerts/types'; @@ -183,7 +183,7 @@ export class AlertService { try { const docs = alertsInfo .filter((alert) => !AlertService.isEmptyAlert(alert)) - .slice(0, MAX_ALERTS_PER_SUB_CASE) + .slice(0, MAX_ALERTS_PER_CASE) .map((alert) => ({ _id: alert.id, _index: alert.index })); if (docs.length <= 0) { diff --git a/x-pack/plugins/cases/server/services/attachments/index.ts b/x-pack/plugins/cases/server/services/attachments/index.ts index 504576184166c..eb09ddac95dd8 100644 --- a/x-pack/plugins/cases/server/services/attachments/index.ts +++ b/x-pack/plugins/cases/server/services/attachments/index.ts @@ -73,7 +73,7 @@ export class AttachmentService { try { this.log.debug(`Attempting to count alerts for case id ${caseId}`); const alertsFilter = buildFilter({ - filters: [CommentType.alert, CommentType.generatedAlert], + filters: [CommentType.alert], field: 'type', operator: 'or', type: CASE_COMMENT_SAVED_OBJECT, @@ -122,7 +122,7 @@ export class AttachmentService { try { this.log.debug(`Attempting to GET all alerts for case id ${caseId}`); const alertsFilter = buildFilter({ - filters: [CommentType.alert, CommentType.generatedAlert], + filters: [CommentType.alert], field: 'type', operator: 'or', type: CASE_COMMENT_SAVED_OBJECT, diff --git a/x-pack/plugins/cases/server/services/cases/index.test.ts b/x-pack/plugins/cases/server/services/cases/index.test.ts index 041a6e613b58c..10026682e68c8 100644 --- a/x-pack/plugins/cases/server/services/cases/index.test.ts +++ b/x-pack/plugins/cases/server/services/cases/index.test.ts @@ -164,7 +164,6 @@ describe('CasesService', () => { "defacement", ], "title": "Super Bad Security Issue", - "type": "individual", "updated_at": "2019-11-25T21:54:48.952Z", "updated_by": Object { "email": "testemail@elastic.co", @@ -528,7 +527,6 @@ describe('CasesService', () => { "defacement", ], "title": "Super Bad Security Issue", - "type": "individual", "updated_at": "2019-11-25T21:54:48.952Z", "updated_by": Object { "email": "testemail@elastic.co", diff --git a/x-pack/plugins/cases/server/services/cases/index.ts b/x-pack/plugins/cases/server/services/cases/index.ts index 412c45ee734d2..3e23a3989eed3 100644 --- a/x-pack/plugins/cases/server/services/cases/index.ts +++ b/x-pack/plugins/cases/server/services/cases/index.ts @@ -26,33 +26,20 @@ import { SecurityPluginSetup } from '../../../../security/server'; import { CASE_COMMENT_SAVED_OBJECT, CASE_SAVED_OBJECT, - ENABLE_CASE_CONNECTOR, MAX_CONCURRENT_SEARCHES, MAX_DOCS_PER_PAGE, - SUB_CASE_SAVED_OBJECT, } from '../../../common/constants'; import { GetCaseIdsByAlertIdAggs, - AssociationType, CaseResponse, CasesFindRequest, - CaseStatuses, - CaseType, - caseTypeField, CommentAttributes, CommentType, - SubCaseAttributes, - SubCaseResponse, User, CaseAttributes, } from '../../../common/api'; import { SavedObjectFindOptionsKueryNode } from '../../common/types'; -import { - defaultSortField, - flattenCaseSavedObject, - flattenSubCaseSavedObject, - groupTotalAlertsByID, -} from '../../common/utils'; +import { defaultSortField, flattenCaseSavedObject, groupTotalAlertsByID } from '../../common/utils'; import { defaultPage, defaultPerPage } from '../../routes/api'; import { ClientArgs } from '..'; import { combineFilters } from '../../client/utils'; @@ -86,10 +73,6 @@ interface GetCasesArgs extends ClientArgs { caseIds: string[]; } -interface GetSubCasesArgs extends ClientArgs { - ids: string[]; -} - interface FindCommentsArgs { unsecuredSavedObjectsClient: SavedObjectsClientContract; id: string | string[]; @@ -100,40 +83,17 @@ interface FindCaseCommentsArgs { unsecuredSavedObjectsClient: SavedObjectsClientContract; id: string | string[]; options?: SavedObjectFindOptionsKueryNode; - includeSubCaseComments?: boolean; -} - -interface FindSubCaseCommentsArgs { - unsecuredSavedObjectsClient: SavedObjectsClientContract; - id: string | string[]; - options?: SavedObjectFindOptionsKueryNode; } interface FindCasesArgs extends ClientArgs { options?: SavedObjectFindOptionsKueryNode; } -interface FindSubCasesByIDArgs extends FindCasesArgs { - ids: string[]; -} - -interface FindSubCasesStatusStats { - unsecuredSavedObjectsClient: SavedObjectsClientContract; - options: SavedObjectFindOptionsKueryNode; - ids: string[]; -} - interface PostCaseArgs extends ClientArgs { attributes: CaseAttributes; id: string; } -interface CreateSubCaseArgs extends ClientArgs { - createdAt: string; - caseId: string; - createdBy: User; -} - interface PatchCase { caseId: string; updatedAttributes: Partial; @@ -146,46 +106,15 @@ interface PatchCasesArgs extends ClientArgs { cases: PatchCase[]; } -interface PatchSubCase { - unsecuredSavedObjectsClient: SavedObjectsClientContract; - subCaseId: string; - updatedAttributes: Partial; - version?: string; -} - -interface PatchSubCases { - unsecuredSavedObjectsClient: SavedObjectsClientContract; - subCases: Array>; -} - interface GetUserArgs { request: KibanaRequest; } -interface SubCasesMapWithPageInfo { - subCasesMap: Map; - page: number; - perPage: number; - total: number; -} - interface CaseCommentStats { commentTotals: Map; alertTotals: Map; } -interface FindCommentsByAssociationArgs { - unsecuredSavedObjectsClient: SavedObjectsClientContract; - id: string | string[]; - associationType: AssociationType; - options?: SavedObjectFindOptionsKueryNode; -} - -interface Collection { - case: SavedObjectsFindResult; - subCases?: SubCaseResponse[]; -} - interface CasesMapWithPageInfo { casesMap: Map; page: number; @@ -205,27 +134,6 @@ interface GetReportersArgs { filter?: KueryNode; } -const transformNewSubCase = ({ - createdAt, - createdBy, - owner, -}: { - createdAt: string; - createdBy: User; - owner: string; -}): SubCaseAttributes => { - return { - closed_at: null, - closed_by: null, - created_at: createdAt, - created_by: createdBy, - status: CaseStatuses.open, - updated_at: null, - updated_by: null, - owner, - }; -}; - export class CasesService { constructor( private readonly log: Logger, @@ -293,68 +201,28 @@ export class CasesService { } /** - * Returns a map of all cases combined with their sub cases if they are collections. + * Returns a map of all cases. */ public async findCasesGroupedByID({ unsecuredSavedObjectsClient, caseOptions, - subCaseOptions, }: { unsecuredSavedObjectsClient: SavedObjectsClientContract; caseOptions: FindCaseOptions; - subCaseOptions?: SavedObjectFindOptionsKueryNode; }): Promise { const cases = await this.findCases({ unsecuredSavedObjectsClient, options: caseOptions, }); - const subCasesResp = ENABLE_CASE_CONNECTOR - ? await this.findSubCasesGroupByCase({ - unsecuredSavedObjectsClient, - options: subCaseOptions, - ids: cases.saved_objects - .filter((caseInfo) => caseInfo.attributes.type === CaseType.collection) - .map((caseInfo) => caseInfo.id), - }) - : { subCasesMap: new Map(), page: 0, perPage: 0 }; - const casesMap = cases.saved_objects.reduce((accMap, caseInfo) => { - const subCasesForCase = subCasesResp.subCasesMap.get(caseInfo.id); - - /** - * If this case is an individual add it to the return map - * If it is a collection and it has sub cases add it to the return map - * If it is a collection and it does not have sub cases, check and see if we're filtering on a status, - * if we're filtering on a status then exclude the empty collection from the results - * if we're not filtering on a status then include the empty collection (that way we can display all the collections - * when the UI isn't doing any filtering) - */ - if ( - caseInfo.attributes.type === CaseType.individual || - subCasesForCase !== undefined || - !caseOptions.status - ) { - accMap.set(caseInfo.id, { case: caseInfo, subCases: subCasesForCase }); - } + accMap.set(caseInfo.id, caseInfo); return accMap; - }, new Map()); + }, new Map>()); - /** - * One potential optimization here is to get all comment stats for individual cases, parent cases, and sub cases - * in a single request. This can be done because comments that are for sub cases have a reference to both the sub case - * and the parent. The associationType field allows us to determine which type of case the comment is attached to. - * - * So we could use the ids for all the valid cases (individual cases and parents with sub cases) to grab everything. - * Once we have it we can build the maps. - * - * Currently we get all comment stats for all sub cases in one go and we get all comment stats for cases (individual and parent) - * in another request (the one below this comment). - */ const totalCommentsForCases = await this.getCaseCommentStats({ unsecuredSavedObjectsClient, ids: Array.from(casesMap.keys()), - associationType: AssociationType.case, }); const casesWithComments = new Map(); @@ -362,10 +230,9 @@ export class CasesService { casesWithComments.set( id, flattenCaseSavedObject({ - savedObject: caseInfo.case, + savedObject: caseInfo, totalComment: totalCommentsForCases.commentTotals.get(id) ?? 0, totalAlerts: totalCommentsForCases.alertTotals.get(id) ?? 0, - subCases: caseInfo.subCases, }) ); } @@ -380,44 +247,20 @@ export class CasesService { /** * Retrieves the number of cases that exist with a given status (open, closed, etc). - * This also counts sub cases. Parent cases are excluded from the statistics. */ public async findCaseStatusStats({ unsecuredSavedObjectsClient, caseOptions, - subCaseOptions, ensureSavedObjectsAreAuthorized, }: { unsecuredSavedObjectsClient: SavedObjectsClientContract; caseOptions: SavedObjectFindOptionsKueryNode; ensureSavedObjectsAreAuthorized: EnsureSOAuthCallback; - subCaseOptions?: SavedObjectFindOptionsKueryNode; }): Promise { - /** - * This could be made more performant. What we're doing here is retrieving all cases - * that match the API request's filters instead of just counts. This is because we need to grab - * the ids for the parent cases that match those filters. Then we use those IDS to count how many - * sub cases those parents have to calculate the total amount of cases that are open, closed, or in-progress. - * - * Another solution would be to store ALL filterable fields on both a case and sub case. That we could do a single - * query for each type to calculate the totals using the filters. This has drawbacks though: - * - * We'd have to sync up the parent case's editable attributes with the sub case any time they were change to avoid - * them getting out of sync and causing issues when we do these types of stats aggregations. This would result in a lot - * of update requests if the user is editing their case details often. Which could potentially cause conflict failures. - * - * Another option is to prevent the ability from update the parent case's details all together once it's created. A user - * could instead modify the sub case details directly. This could be weird though because individual sub cases for the same - * parent would have different titles, tags, etc. - * - * Another potential issue with this approach is when you push a case and all its sub case information. If the sub cases - * don't have the same title and tags, we'd need to account for that as well. - */ const cases = await this.findCases({ unsecuredSavedObjectsClient, options: { ...caseOptions, - fields: includeFieldsRequiredForAuthentication([caseTypeField]), page: 1, perPage: MAX_DOCS_PER_PAGE, }, @@ -428,62 +271,18 @@ export class CasesService { cases.saved_objects.map((caseInfo) => ({ id: caseInfo.id, owner: caseInfo.attributes.owner })) ); - const caseIds = cases.saved_objects - .filter((caseInfo) => caseInfo.attributes.type === CaseType.collection) - .map((caseInfo) => caseInfo.id); - - let subCasesTotal = 0; - - if (ENABLE_CASE_CONNECTOR && subCaseOptions) { - subCasesTotal = await this.findSubCaseStatusStats({ - unsecuredSavedObjectsClient, - options: subCaseOptions, - ids: caseIds, - }); - } - - const total = - cases.saved_objects.filter((caseInfo) => caseInfo.attributes.type !== CaseType.collection) - .length + subCasesTotal; - - return total; - } - - /** - * Retrieves the comments attached to a case or sub case. - */ - public async getCommentsByAssociation({ - unsecuredSavedObjectsClient, - id, - associationType, - options, - }: FindCommentsByAssociationArgs): Promise> { - if (associationType === AssociationType.subCase) { - return this.getAllSubCaseComments({ - unsecuredSavedObjectsClient, - id, - options, - }); - } else { - return this.getAllCaseComments({ - unsecuredSavedObjectsClient, - id, - options, - }); - } + return cases.saved_objects.length; } /** - * Returns the number of total comments and alerts for a case (or sub case) + * Returns the number of total comments and alerts for a case */ public async getCaseCommentStats({ unsecuredSavedObjectsClient, ids, - associationType, }: { unsecuredSavedObjectsClient: SavedObjectsClientContract; ids: string[]; - associationType: AssociationType; }): Promise { if (ids.length <= 0) { return { @@ -492,40 +291,29 @@ export class CasesService { }; } - const refType = - associationType === AssociationType.case ? CASE_SAVED_OBJECT : SUB_CASE_SAVED_OBJECT; - const getCommentsMapper = async (id: string) => - this.getCommentsByAssociation({ + this.getAllCaseComments({ unsecuredSavedObjectsClient, - associationType, id, options: { page: 1, perPage: 1 }, }); - // Ensuring we don't too many concurrent get running. + // Ensuring we don't do too many concurrent get running. const allComments = await pMap(ids, getCommentsMapper, { concurrency: MAX_CONCURRENT_SEARCHES, }); - const alerts = await this.getCommentsByAssociation({ + const alerts = await this.getAllCaseComments({ unsecuredSavedObjectsClient, - associationType, id: ids, options: { - filter: nodeBuilder.or([ - nodeBuilder.is(`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, CommentType.alert), - nodeBuilder.is( - `${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, - CommentType.generatedAlert - ), - ]), + filter: nodeBuilder.is(`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, CommentType.alert), }, }); const getID = (comments: SavedObjectsFindResponse) => { return comments.saved_objects.length > 0 - ? comments.saved_objects[0].references.find((ref) => ref.type === refType)?.id + ? comments.saved_objects[0].references.find((ref) => ref.type === CASE_SAVED_OBJECT)?.id : undefined; }; @@ -541,179 +329,6 @@ export class CasesService { return { commentTotals: groupedComments, alertTotals: groupedAlerts }; } - /** - * Returns all the sub cases for a set of case IDs. Comment statistics are also returned. - */ - public async findSubCasesGroupByCase({ - unsecuredSavedObjectsClient, - options, - ids, - }: { - unsecuredSavedObjectsClient: SavedObjectsClientContract; - options?: SavedObjectFindOptionsKueryNode; - ids: string[]; - }): Promise { - const getCaseID = (subCase: SavedObjectsFindResult): string | undefined => { - return subCase.references.length > 0 ? subCase.references[0].id : undefined; - }; - - const emptyResponse = { - subCasesMap: new Map(), - page: 0, - perPage: 0, - total: 0, - }; - - if (!options) { - return emptyResponse; - } - - if (ids.length <= 0) { - return emptyResponse; - } - - const subCases = await this.findSubCases({ - unsecuredSavedObjectsClient, - options: { - ...options, - hasReference: ids.map((id) => { - return { - id, - type: CASE_SAVED_OBJECT, - }; - }), - }, - }); - - const subCaseComments = await this.getCaseCommentStats({ - unsecuredSavedObjectsClient, - ids: subCases.saved_objects.map((subCase) => subCase.id), - associationType: AssociationType.subCase, - }); - - const subCasesMap = subCases.saved_objects.reduce((accMap, subCase) => { - const parentCaseID = getCaseID(subCase); - if (parentCaseID) { - const subCaseFromMap = accMap.get(parentCaseID); - - if (subCaseFromMap === undefined) { - const subCasesForID = [ - flattenSubCaseSavedObject({ - savedObject: subCase, - totalComment: subCaseComments.commentTotals.get(subCase.id) ?? 0, - totalAlerts: subCaseComments.alertTotals.get(subCase.id) ?? 0, - }), - ]; - accMap.set(parentCaseID, subCasesForID); - } else { - subCaseFromMap.push( - flattenSubCaseSavedObject({ - savedObject: subCase, - totalComment: subCaseComments.commentTotals.get(subCase.id) ?? 0, - totalAlerts: subCaseComments.alertTotals.get(subCase.id) ?? 0, - }) - ); - } - } - return accMap; - }, new Map()); - - return { subCasesMap, page: subCases.page, perPage: subCases.per_page, total: subCases.total }; - } - - /** - * Calculates the number of sub cases for a given set of options for a set of case IDs. - */ - public async findSubCaseStatusStats({ - unsecuredSavedObjectsClient, - options, - ids, - }: FindSubCasesStatusStats): Promise { - if (ids.length <= 0) { - return 0; - } - - const subCases = await this.findSubCases({ - unsecuredSavedObjectsClient, - options: { - ...options, - page: 1, - perPage: 1, - fields: [], - hasReference: ids.map((id) => { - return { - id, - type: CASE_SAVED_OBJECT, - }; - }), - }, - }); - - return subCases.total; - } - - public async createSubCase({ - unsecuredSavedObjectsClient, - createdAt, - caseId, - createdBy, - }: CreateSubCaseArgs): Promise> { - try { - this.log.debug(`Attempting to POST a new sub case`); - return unsecuredSavedObjectsClient.create( - SUB_CASE_SAVED_OBJECT, - // ENABLE_CASE_CONNECTOR: populate the owner field correctly - transformNewSubCase({ createdAt, createdBy, owner: '' }), - { - references: [ - { - type: CASE_SAVED_OBJECT, - name: `associated-${CASE_SAVED_OBJECT}`, - id: caseId, - }, - ], - } - ); - } catch (error) { - this.log.error(`Error on POST a new sub case for id ${caseId}: ${error}`); - throw error; - } - } - - public async getMostRecentSubCase( - unsecuredSavedObjectsClient: SavedObjectsClientContract, - caseId: string - ) { - try { - this.log.debug(`Attempting to find most recent sub case for caseID: ${caseId}`); - const subCases = await unsecuredSavedObjectsClient.find({ - perPage: 1, - sortField: 'created_at', - sortOrder: 'desc', - type: SUB_CASE_SAVED_OBJECT, - hasReference: { type: CASE_SAVED_OBJECT, id: caseId }, - }); - if (subCases.saved_objects.length <= 0) { - return; - } - - return subCases.saved_objects[0]; - } catch (error) { - this.log.error(`Error finding the most recent sub case for case: ${caseId}: ${error}`); - throw error; - } - } - - public async deleteSubCase(unsecuredSavedObjectsClient: SavedObjectsClientContract, id: string) { - try { - this.log.debug(`Attempting to DELETE sub case ${id}`); - return await unsecuredSavedObjectsClient.delete(SUB_CASE_SAVED_OBJECT, id); - } catch (error) { - this.log.error(`Error on DELETE sub case ${id}: ${error}`); - throw error; - } - } - public async deleteCase({ unsecuredSavedObjectsClient, id: caseId }: GetCaseArgs) { try { this.log.debug(`Attempting to DELETE case ${caseId}`); @@ -761,34 +376,6 @@ export class CasesService { } } - public async getSubCase({ - unsecuredSavedObjectsClient, - id, - }: GetCaseArgs): Promise> { - try { - this.log.debug(`Attempting to GET sub case ${id}`); - return await unsecuredSavedObjectsClient.get(SUB_CASE_SAVED_OBJECT, id); - } catch (error) { - this.log.error(`Error on GET sub case ${id}: ${error}`); - throw error; - } - } - - public async getSubCases({ - unsecuredSavedObjectsClient, - ids, - }: GetSubCasesArgs): Promise> { - try { - this.log.debug(`Attempting to GET sub cases ${ids.join(', ')}`); - return await unsecuredSavedObjectsClient.bulkGet( - ids.map((id) => ({ type: SUB_CASE_SAVED_OBJECT, id })) - ); - } catch (error) { - this.log.error(`Error on GET cases ${ids.join(', ')}: ${error}`); - throw error; - } - } - public async getCases({ unsecuredSavedObjectsClient, caseIds, @@ -823,75 +410,6 @@ export class CasesService { } } - public async findSubCases({ - unsecuredSavedObjectsClient, - options, - }: FindCasesArgs): Promise> { - try { - this.log.debug(`Attempting to find sub cases`); - // if the page or perPage options are set then respect those instead of trying to - // grab all sub cases - if (options?.page !== undefined || options?.perPage !== undefined) { - return unsecuredSavedObjectsClient.find({ - sortField: defaultSortField, - ...options, - type: SUB_CASE_SAVED_OBJECT, - }); - } - - return unsecuredSavedObjectsClient.find({ - page: 1, - perPage: MAX_DOCS_PER_PAGE, - sortField: defaultSortField, - ...options, - type: SUB_CASE_SAVED_OBJECT, - }); - } catch (error) { - this.log.error(`Error on find sub cases: ${error}`); - throw error; - } - } - - /** - * Find sub cases using a collection's ID. This would try to retrieve the maximum amount of sub cases - * by default. - * - * @param id the saved object ID of the parent collection to find sub cases for. - */ - public async findSubCasesByCaseId({ - unsecuredSavedObjectsClient, - ids, - options, - }: FindSubCasesByIDArgs): Promise> { - if (ids.length <= 0) { - return { - total: 0, - saved_objects: [], - page: options?.page ?? defaultPage, - per_page: options?.perPage ?? defaultPerPage, - }; - } - - try { - this.log.debug(`Attempting to GET sub cases for case collection id ${ids.join(', ')}`); - return this.findSubCases({ - unsecuredSavedObjectsClient, - options: { - ...options, - hasReference: ids.map((id) => ({ - type: CASE_SAVED_OBJECT, - id, - })), - }, - }); - } catch (error) { - this.log.error( - `Error on GET all sub cases for case collection id ${ids.join(', ')}: ${error}` - ); - throw error; - } - } - private asArray(id: string | string[] | undefined): string[] { if (id === undefined) { return []; @@ -933,15 +451,11 @@ export class CasesService { /** * Default behavior is to retrieve all comments that adhere to a given filter (if one is included). * to override this pass in the either the page or perPage options. - * - * @param includeSubCaseComments is a flag to indicate that sub case comments should be included as well, by default - * sub case comments are excluded. If the `filter` field is included in the options, it will override this behavior */ public async getAllCaseComments({ unsecuredSavedObjectsClient, id, options, - includeSubCaseComments = false, }: FindCaseCommentsArgs): Promise> { try { const refs = this.asArray(id).map((caseID) => ({ type: CASE_SAVED_OBJECT, id: caseID })); @@ -954,20 +468,6 @@ export class CasesService { }; } - let filter: KueryNode | undefined; - if (!includeSubCaseComments) { - // if other filters were passed in then combine them to filter out sub case comments - const associationTypeFilter = nodeBuilder.is( - `${CASE_COMMENT_SAVED_OBJECT}.attributes.associationType`, - AssociationType.case - ); - - filter = - options?.filter != null - ? nodeBuilder.and([options.filter, associationTypeFilter]) - : associationTypeFilter; - } - this.log.debug(`Attempting to GET all comments for case caseID ${JSON.stringify(id)}`); return await this.getAllComments({ unsecuredSavedObjectsClient, @@ -975,7 +475,7 @@ export class CasesService { options: { hasReferenceOperator: 'OR', hasReference: refs, - filter, + filter: options?.filter, ...options, }, }); @@ -985,38 +485,6 @@ export class CasesService { } } - public async getAllSubCaseComments({ - unsecuredSavedObjectsClient, - id, - options, - }: FindSubCaseCommentsArgs): Promise> { - try { - const refs = this.asArray(id).map((caseID) => ({ type: SUB_CASE_SAVED_OBJECT, id: caseID })); - if (refs.length <= 0) { - return { - saved_objects: [], - total: 0, - per_page: options?.perPage ?? defaultPerPage, - page: options?.page ?? defaultPage, - }; - } - - this.log.debug(`Attempting to GET all comments for sub case caseID ${JSON.stringify(id)}`); - return await this.getAllComments({ - unsecuredSavedObjectsClient, - id, - options: { - hasReferenceOperator: 'OR', - hasReference: refs, - ...options, - }, - }); - } catch (error) { - this.log.error(`Error on GET all comments for sub case ${JSON.stringify(id)}: ${error}`); - throw error; - } - } - public async getReporters({ unsecuredSavedObjectsClient, filter, @@ -1211,45 +679,4 @@ export class CasesService { throw error; } } - - public async patchSubCase({ - unsecuredSavedObjectsClient, - subCaseId, - updatedAttributes, - version, - }: PatchSubCase) { - try { - this.log.debug(`Attempting to UPDATE sub case ${subCaseId}`); - return await unsecuredSavedObjectsClient.update( - SUB_CASE_SAVED_OBJECT, - subCaseId, - { ...updatedAttributes }, - { version } - ); - } catch (error) { - this.log.error(`Error on UPDATE sub case ${subCaseId}: ${error}`); - throw error; - } - } - - public async patchSubCases({ unsecuredSavedObjectsClient, subCases }: PatchSubCases) { - try { - this.log.debug( - `Attempting to UPDATE sub case ${subCases.map((c) => c.subCaseId).join(', ')}` - ); - return await unsecuredSavedObjectsClient.bulkUpdate( - subCases.map((c) => ({ - type: SUB_CASE_SAVED_OBJECT, - id: c.subCaseId, - attributes: c.updatedAttributes, - version: c.version, - })) - ); - } catch (error) { - this.log.error( - `Error on UPDATE sub case ${subCases.map((c) => c.subCaseId).join(', ')}: ${error}` - ); - throw error; - } - } } diff --git a/x-pack/plugins/cases/server/services/cases/transform.test.ts b/x-pack/plugins/cases/server/services/cases/transform.test.ts index 729ffd89f7c23..7235bc26bcf73 100644 --- a/x-pack/plugins/cases/server/services/cases/transform.test.ts +++ b/x-pack/plugins/cases/server/services/cases/transform.test.ts @@ -267,7 +267,6 @@ describe('case transforms', () => { it('creates an empty references array to delete the connector_id when connector_id is null and the original references is undefined', () => { const transformedAttributes = transformAttributesToESModel({ - // TODO: It was null. Check if it is correct external_service: createExternalService({ connector_id: 'none' }), }); @@ -390,7 +389,6 @@ describe('case transforms', () => { it('sets external_service.connector_id to none when a reference cannot be found', () => { const transformedSO = transformSavedObjectToExternalModel( createCaseSavedObjectResponse({ - // TODO: It was null. Check if it is correct externalService: createExternalService({ connector_id: 'none' }), }) ); diff --git a/x-pack/plugins/cases/server/services/mocks.ts b/x-pack/plugins/cases/server/services/mocks.ts index 169e3bd5dc8e0..4c7210224c929 100644 --- a/x-pack/plugins/cases/server/services/mocks.ts +++ b/x-pack/plugins/cases/server/services/mocks.ts @@ -24,33 +24,20 @@ export type AttachmentServiceMock = jest.Mocked; export const createCaseServiceMock = (): CaseServiceMock => { const service: PublicMethodsOf = { - createSubCase: jest.fn(), deleteCase: jest.fn(), - deleteSubCase: jest.fn(), findCases: jest.fn(), - findSubCases: jest.fn(), - findSubCasesByCaseId: jest.fn(), getAllCaseComments: jest.fn(), - getAllSubCaseComments: jest.fn(), getCase: jest.fn(), getCases: jest.fn(), getCaseIdsByAlertId: jest.fn(), - getMostRecentSubCase: jest.fn(), getResolveCase: jest.fn(), - getSubCase: jest.fn(), - getSubCases: jest.fn(), getTags: jest.fn(), getReporters: jest.fn(), getUser: jest.fn(), postNewCase: jest.fn(), patchCase: jest.fn(), patchCases: jest.fn(), - patchSubCase: jest.fn(), - patchSubCases: jest.fn(), - findSubCaseStatusStats: jest.fn(), - getCommentsByAssociation: jest.fn(), getCaseCommentStats: jest.fn(), - findSubCasesGroupByCase: jest.fn(), findCaseStatusStats: jest.fn(), findCasesGroupedByID: jest.fn(), }; diff --git a/x-pack/plugins/cases/server/services/test_utils.ts b/x-pack/plugins/cases/server/services/test_utils.ts index 2ad8189eaf657..c2b24c42c8a69 100644 --- a/x-pack/plugins/cases/server/services/test_utils.ts +++ b/x-pack/plugins/cases/server/services/test_utils.ts @@ -13,7 +13,6 @@ import { CaseExternalServiceBasic, CaseFullExternalService, CaseStatuses, - CaseType, ConnectorTypes, NONE_CONNECTOR_ID, } from '../../common/api'; @@ -110,7 +109,6 @@ export const basicCaseFields = { title: 'Super Bad Security Issue', status: CaseStatuses.open, tags: ['defacement'], - type: CaseType.individual, updated_at: '2019-11-25T21:54:48.952Z', updated_by: { full_name: 'elastic', diff --git a/x-pack/plugins/cases/server/services/user_actions/abstract_builder.ts b/x-pack/plugins/cases/server/services/user_actions/abstract_builder.ts index b62a8edd6e020..90eddb80361b8 100644 --- a/x-pack/plugins/cases/server/services/user_actions/abstract_builder.ts +++ b/x-pack/plugins/cases/server/services/user_actions/abstract_builder.ts @@ -6,17 +6,12 @@ */ import { SavedObjectReference } from 'kibana/server'; -import { - CASE_COMMENT_SAVED_OBJECT, - CASE_SAVED_OBJECT, - SUB_CASE_SAVED_OBJECT, -} from '../../../common/constants'; +import { CASE_COMMENT_SAVED_OBJECT, CASE_SAVED_OBJECT } from '../../../common/constants'; import { CASE_REF_NAME, COMMENT_REF_NAME, CONNECTOR_ID_REFERENCE_NAME, PUSH_CONNECTOR_ID_REFERENCE_NAME, - SUB_CASE_REF_NAME, } from '../../common/constants'; import { ActionTypes, @@ -47,22 +42,13 @@ export abstract class UserActionBuilder { return restConnector; } - protected createCaseReferences(caseId: string, subCaseId?: string): SavedObjectReference[] { + protected createCaseReferences(caseId: string): SavedObjectReference[] { return [ { type: CASE_SAVED_OBJECT, name: CASE_REF_NAME, id: caseId, }, - ...(subCaseId - ? [ - { - type: SUB_CASE_SAVED_OBJECT, - name: SUB_CASE_REF_NAME, - id: subCaseId, - }, - ] - : []), ]; } @@ -106,7 +92,6 @@ export abstract class UserActionBuilder { value, valueKey, caseId, - subCaseId, attachmentId, connectorId, type, @@ -119,7 +104,7 @@ export abstract class UserActionBuilder { type, }, references: [ - ...this.createCaseReferences(caseId, subCaseId), + ...this.createCaseReferences(caseId), ...this.createCommentReferences(attachmentId ?? null), ...(type === ActionTypes.connector ? this.createConnectorReference(connectorId ?? null) diff --git a/x-pack/plugins/cases/server/services/user_actions/builders/create_case.ts b/x-pack/plugins/cases/server/services/user_actions/builders/create_case.ts index c0703ce937ac7..9261746d00cc0 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builders/create_case.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builders/create_case.ts @@ -11,7 +11,7 @@ import { UserActionParameters, BuilderReturnValue } from '../types'; export class CreateCaseUserActionBuilder extends UserActionBuilder { build(args: UserActionParameters<'create_case'>): BuilderReturnValue { - const { payload, caseId, subCaseId, owner, user } = args; + const { payload, caseId, owner, user } = args; const connectorWithoutId = this.extractConnectorId(payload.connector); return { attributes: { @@ -21,7 +21,7 @@ export class CreateCaseUserActionBuilder extends UserActionBuilder { type: ActionTypes.create_case, }, references: [ - ...this.createCaseReferences(caseId, subCaseId), + ...this.createCaseReferences(caseId), ...this.createConnectorReference(payload.connector.id), ], }; diff --git a/x-pack/plugins/cases/server/services/user_actions/index.test.ts b/x-pack/plugins/cases/server/services/user_actions/index.test.ts index 2ccfaf54dd9fe..eb1e69a3014ab 100644 --- a/x-pack/plugins/cases/server/services/user_actions/index.test.ts +++ b/x-pack/plugins/cases/server/services/user_actions/index.test.ts @@ -23,14 +23,12 @@ import { CASE_SAVED_OBJECT, CASE_USER_ACTION_SAVED_OBJECT, SECURITY_SOLUTION_OWNER, - SUB_CASE_SAVED_OBJECT, } from '../../../common/constants'; import { CASE_REF_NAME, COMMENT_REF_NAME, CONNECTOR_ID_REFERENCE_NAME, PUSH_CONNECTOR_ID_REFERENCE_NAME, - SUB_CASE_REF_NAME, } from '../../common/constants'; import { @@ -50,7 +48,6 @@ import { import { CaseUserActionService, transformFindResponseToExternalModel } from '.'; const createConnectorUserAction = ( - subCaseId?: string, overrides?: Partial ): SavedObject => { const { id, ...restConnector } = createConnectorObject().connector; @@ -59,7 +56,6 @@ const createConnectorUserAction = ( action: Actions.create, payload: { connector: restConnector }, type: 'connector', - subCaseId, connectorId: id, }), ...(overrides && { ...overrides }), @@ -67,10 +63,8 @@ const createConnectorUserAction = ( }; const updateConnectorUserAction = ({ - subCaseId, overrides, }: { - subCaseId?: string; overrides?: Partial; } = {}): SavedObject => { const { id, ...restConnector } = createJiraConnector(); @@ -79,7 +73,6 @@ const updateConnectorUserAction = ({ action: Actions.update, payload: { connector: restConnector }, type: 'connector', - subCaseId, connectorId: id, }), ...(overrides && { ...overrides }), @@ -87,10 +80,8 @@ const updateConnectorUserAction = ({ }; const pushConnectorUserAction = ({ - subCaseId, overrides, }: { - subCaseId?: string; overrides?: Partial; } = {}): SavedObject => { const { connector_id: connectorId, ...restExternalService } = createExternalService(); @@ -98,7 +89,6 @@ const pushConnectorUserAction = ({ ...createUserActionSO({ action: Actions.push_to_service, payload: { externalService: restExternalService }, - subCaseId, pushedConnectorId: connectorId, type: 'pushed', }), @@ -135,7 +125,6 @@ const createUserActionFindSO = ( const createUserActionSO = ({ action, - subCaseId, attributesOverrides, commentId, connectorId, @@ -144,7 +133,6 @@ const createUserActionSO = ({ type, }: { action: UserAction; - subCaseId?: string; type?: string; payload?: Record; attributesOverrides?: Partial; @@ -178,15 +166,6 @@ const createUserActionSO = ({ name: CASE_REF_NAME, id: '1', }, - ...(subCaseId - ? [ - { - type: SUB_CASE_SAVED_OBJECT, - name: SUB_CASE_REF_NAME, - id: subCaseId, - }, - ] - : []), ...(commentId ? [ { @@ -326,7 +305,6 @@ describe('CaseUserActionService', () => { "type": ".jira", }, }, - "sub_case_id": "", "type": "connector", }, "id": "100", @@ -388,18 +366,6 @@ describe('CaseUserActionService', () => { expect(transformed.saved_objects[0].attributes.comment_id).toBeNull(); }); - it('sets sub_case_id to an empty string when it cannot find the reference', () => { - const userAction = { - ...createUserActionSO({ action: Actions.create, subCaseId: '5' }), - references: [], - }; - const transformed = transformFindResponseToExternalModel( - createSOFindResponse([createUserActionFindSO(userAction)]) - ); - - expect(transformed.saved_objects[0].attributes.comment_id).toBeNull(); - }); - it('sets case_id correctly when it finds the reference', () => { const userAction = createConnectorUserAction(); @@ -423,21 +389,9 @@ describe('CaseUserActionService', () => { expect(transformed.saved_objects[0].attributes.comment_id).toEqual('5'); }); - it('sets sub_case_id correctly when it finds the reference', () => { - const userAction = { - ...createUserActionSO({ action: Actions.create, subCaseId: '5' }), - }; - - const transformed = transformFindResponseToExternalModel( - createSOFindResponse([createUserActionFindSO(userAction)]) - ); - - expect(transformed.saved_objects[0].attributes.sub_case_id).toEqual('5'); - }); - it('sets action_id correctly to the saved object id', () => { const userAction = { - ...createUserActionSO({ action: Actions.create, subCaseId: '5' }), + ...createUserActionSO({ action: Actions.create, commentId: '5' }), }; const transformed = transformFindResponseToExternalModel( diff --git a/x-pack/plugins/cases/server/services/user_actions/index.ts b/x-pack/plugins/cases/server/services/user_actions/index.ts index 130fe47645278..c80d2d6da4c98 100644 --- a/x-pack/plugins/cases/server/services/user_actions/index.ts +++ b/x-pack/plugins/cases/server/services/user_actions/index.ts @@ -33,14 +33,12 @@ import { CaseUserActionResponse, CommentRequest, NONE_CONNECTOR_ID, - SubCaseAttributes, User, } from '../../../common/api'; import { CASE_SAVED_OBJECT, CASE_USER_ACTION_SAVED_OBJECT, MAX_DOCS_PER_PAGE, - SUB_CASE_SAVED_OBJECT, CASE_COMMENT_SAVED_OBJECT, } from '../../../common/constants'; import { ClientArgs } from '..'; @@ -49,7 +47,6 @@ import { COMMENT_REF_NAME, CONNECTOR_ID_REFERENCE_NAME, PUSH_CONNECTOR_ID_REFERENCE_NAME, - SUB_CASE_REF_NAME, } from '../../common/constants'; import { findConnectorIdReference } from '../transform'; import { buildFilter, combineFilters, isTwoArraysDifference } from '../../client/utils'; @@ -59,7 +56,6 @@ import { defaultSortField } from '../../common/utils'; interface GetCaseUserActionArgs extends ClientArgs { caseId: string; - subCaseId?: string; } export interface UserActionItem { @@ -79,7 +75,7 @@ interface CreateUserActionES extends ClientArgs { type CommonUserActionArgs = ClientArgs & CommonArguments; interface BulkCreateCaseDeletionUserAction extends ClientArgs { - cases: Array<{ id: string; owner: string; subCaseId?: string; connectorId: string }>; + cases: Array<{ id: string; owner: string; connectorId: string }>; user: User; } @@ -90,8 +86,8 @@ interface GetUserActionItemByDifference extends CommonUserActionArgs { } interface BulkCreateBulkUpdateCaseUserActions extends ClientArgs { - originalCases: Array>; - updatedCases: Array>; + originalCases: Array>; + updatedCases: Array>; user: User; } @@ -114,7 +110,6 @@ export class CaseUserActionService { originalValue, newValue, caseId, - subCaseId, owner, user, }: GetUserActionItemByDifference): BuilderReturnValue[] { @@ -131,7 +126,6 @@ export class CaseUserActionService { const tagAddUserAction = tagsUserActionBuilder?.build({ action: Actions.add, caseId, - subCaseId, user, owner, payload: { tags: compareValues.addedItems }, @@ -146,7 +140,6 @@ export class CaseUserActionService { const tagsDeleteUserAction = tagsUserActionBuilder?.build({ action: Actions.delete, caseId, - subCaseId, user, owner, payload: { tags: compareValues.deletedItems }, @@ -164,7 +157,6 @@ export class CaseUserActionService { const userActionBuilder = this.builderFactory.getBuilder(ActionTypes[field]); const fieldUserAction = userActionBuilder?.build({ caseId, - subCaseId, owner, user, payload: { [field]: newValue }, @@ -252,7 +244,6 @@ export class CaseUserActionService { public async bulkCreateAttachmentDeletion({ unsecuredSavedObjectsClient, caseId, - subCaseId, attachments, user, }: BulkCreateAttachmentDeletionUserAction): Promise { @@ -263,7 +254,6 @@ export class CaseUserActionService { const deleteCommentUserAction = userActionBuilder?.build({ action: Actions.delete, caseId, - subCaseId, user, owner: attachment.owner, attachmentId: attachment.id, @@ -287,7 +277,6 @@ export class CaseUserActionService { action, type, caseId, - subCaseId, user, owner, payload, @@ -301,7 +290,6 @@ export class CaseUserActionService { const userAction = userActionBuilder?.build({ action, caseId, - subCaseId, user, owner, connectorId, @@ -322,11 +310,10 @@ export class CaseUserActionService { public async getAll({ unsecuredSavedObjectsClient, caseId, - subCaseId, }: GetCaseUserActionArgs): Promise> { try { - const id = subCaseId ?? caseId; - const type = subCaseId ? SUB_CASE_SAVED_OBJECT : CASE_SAVED_OBJECT; + const id = caseId; + const type = CASE_SAVED_OBJECT; const userActions = await unsecuredSavedObjectsClient.find({ @@ -534,7 +521,6 @@ function transformToExternalModel( const caseId = findReferenceId(CASE_REF_NAME, CASE_SAVED_OBJECT, references) ?? ''; const commentId = findReferenceId(COMMENT_REF_NAME, CASE_COMMENT_SAVED_OBJECT, references) ?? null; - const subCaseId = findReferenceId(SUB_CASE_REF_NAME, SUB_CASE_SAVED_OBJECT, references) ?? ''; const payload = addReferenceIdToPayload(userAction); return { @@ -544,7 +530,6 @@ function transformToExternalModel( action_id: userAction.id, case_id: caseId, comment_id: commentId, - sub_case_id: subCaseId, payload, } as CaseUserActionResponse, }; diff --git a/x-pack/plugins/cases/server/services/user_actions/mocks.ts b/x-pack/plugins/cases/server/services/user_actions/mocks.ts index 2d62d4747a8a4..c745c040ac2ce 100644 --- a/x-pack/plugins/cases/server/services/user_actions/mocks.ts +++ b/x-pack/plugins/cases/server/services/user_actions/mocks.ts @@ -9,6 +9,7 @@ import { CASE_SAVED_OBJECT } from '../../../common/constants'; import { SECURITY_SOLUTION_OWNER } from '../../../common'; import { CaseStatuses, CommentType, ConnectorTypes } from '../../../common/api'; import { createCaseSavedObjectResponse } from '../test_utils'; +import { transformSavedObjectToExternalModel } from '../cases/transform'; export const casePayload = { title: 'Case SIR', @@ -46,7 +47,7 @@ export const externalService = { export const originalCases = [ { ...createCaseSavedObjectResponse(), id: '1' }, { ...createCaseSavedObjectResponse(), id: '2' }, -]; +].map((so) => transformSavedObjectToExternalModel(so)); export const updatedCases = [ { diff --git a/x-pack/plugins/cases/server/services/user_actions/types.ts b/x-pack/plugins/cases/server/services/user_actions/types.ts index 50ce01bc54017..435e4169323a1 100644 --- a/x-pack/plugins/cases/server/services/user_actions/types.ts +++ b/x-pack/plugins/cases/server/services/user_actions/types.ts @@ -75,7 +75,6 @@ export interface CommonArguments { user: User; caseId: string; owner: string; - subCaseId?: string; attachmentId?: string; connectorId?: string; action?: UserAction; diff --git a/x-pack/plugins/cloud/.storybook/decorator.tsx b/x-pack/plugins/cloud/.storybook/decorator.tsx new file mode 100644 index 0000000000000..4489b58f75759 --- /dev/null +++ b/x-pack/plugins/cloud/.storybook/decorator.tsx @@ -0,0 +1,35 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { DecoratorFn } from '@storybook/react'; +import { ServicesProvider, CloudServices } from '../public/services'; + +// TODO: move to a storybook implementation of the service using parameters. +const services: CloudServices = { + chat: { + enabled: true, + chatURL: 'https://elasticcloud-production-chat-us-east-1.s3.amazonaws.com/drift-iframe.html', + user: { + id: 'user-id', + email: 'test-user@elastic.co', + // this doesn't affect chat appearance, + // but a user identity in Drift only + jwt: 'identity-jwt', + }, + }, +}; + +export const getCloudContextProvider: () => React.FC = + () => + ({ children }) => + {children}; + +export const getCloudContextDecorator: DecoratorFn = (storyFn) => { + const CloudContextProvider = getCloudContextProvider(); + return {storyFn()}; +}; diff --git a/x-pack/plugins/cases/server/scripts/sub_cases/generator.js b/x-pack/plugins/cloud/.storybook/index.ts similarity index 75% rename from x-pack/plugins/cases/server/scripts/sub_cases/generator.js rename to x-pack/plugins/cloud/.storybook/index.ts index 0c5b8bfc8550b..321df983cb20d 100644 --- a/x-pack/plugins/cases/server/scripts/sub_cases/generator.js +++ b/x-pack/plugins/cloud/.storybook/index.ts @@ -5,5 +5,4 @@ * 2.0. */ -require('../../../../../../src/setup_node_env'); -require('./index'); +export { getCloudContextDecorator, getCloudContextProvider } from './decorator'; diff --git a/x-pack/plugins/cases/server/connectors/case/translations.ts b/x-pack/plugins/cloud/.storybook/main.ts similarity index 64% rename from x-pack/plugins/cases/server/connectors/case/translations.ts rename to x-pack/plugins/cloud/.storybook/main.ts index aa14ee5aa7a6e..bf63e08d64c32 100644 --- a/x-pack/plugins/cases/server/connectors/case/translations.ts +++ b/x-pack/plugins/cloud/.storybook/main.ts @@ -5,8 +5,6 @@ * 2.0. */ -import { i18n } from '@kbn/i18n'; +import { defaultConfig } from '@kbn/storybook'; -export const NAME = i18n.translate('xpack.cases.connectors.cases.title', { - defaultMessage: 'Case', -}); +module.exports = defaultConfig; diff --git a/x-pack/plugins/cloud/.storybook/manager.ts b/x-pack/plugins/cloud/.storybook/manager.ts new file mode 100644 index 0000000000000..54c3d31c2002f --- /dev/null +++ b/x-pack/plugins/cloud/.storybook/manager.ts @@ -0,0 +1,20 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { addons } from '@storybook/addons'; +import { create } from '@storybook/theming'; +import { PANEL_ID } from '@storybook/addon-actions'; + +addons.setConfig({ + theme: create({ + base: 'light', + brandTitle: 'Cloud Storybook', + brandUrl: 'https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud', + }), + showPanel: true.valueOf, + selectedPanel: PANEL_ID, +}); diff --git a/x-pack/plugins/cloud/.storybook/preview.ts b/x-pack/plugins/cloud/.storybook/preview.ts new file mode 100644 index 0000000000000..83c512e516d5a --- /dev/null +++ b/x-pack/plugins/cloud/.storybook/preview.ts @@ -0,0 +1,11 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { addDecorator } from '@storybook/react'; +import { getCloudContextDecorator } from './decorator'; + +addDecorator(getCloudContextDecorator); diff --git a/x-pack/plugins/cloud/common/constants.ts b/x-pack/plugins/cloud/common/constants.ts index fc37906299d14..09333e3773fe9 100644 --- a/x-pack/plugins/cloud/common/constants.ts +++ b/x-pack/plugins/cloud/common/constants.ts @@ -6,6 +6,7 @@ */ export const ELASTIC_SUPPORT_LINK = 'https://cloud.elastic.co/support'; +export const GET_CHAT_USER_DATA_ROUTE_PATH = '/internal/cloud/chat_user'; /** * This is the page for managing your snapshots on Cloud. diff --git a/x-pack/plugins/cloud/common/types.ts b/x-pack/plugins/cloud/common/types.ts new file mode 100644 index 0000000000000..38ebeaf5f467c --- /dev/null +++ b/x-pack/plugins/cloud/common/types.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export interface GetChatUserDataResponseBody { + token: string; + email: string; + id: string; +} diff --git a/x-pack/plugins/cloud/public/components/chat/chat.stories.tsx b/x-pack/plugins/cloud/public/components/chat/chat.stories.tsx new file mode 100644 index 0000000000000..668017e134e75 --- /dev/null +++ b/x-pack/plugins/cloud/public/components/chat/chat.stories.tsx @@ -0,0 +1,20 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { Chat } from './chat'; + +export default { + title: 'Chat Widget', + description: '', + parameters: {}, +}; + +export const Component = () => { + return ; +}; diff --git a/x-pack/plugins/cloud/public/components/chat/chat.tsx b/x-pack/plugins/cloud/public/components/chat/chat.tsx new file mode 100644 index 0000000000000..99b53f553e75f --- /dev/null +++ b/x-pack/plugins/cloud/public/components/chat/chat.tsx @@ -0,0 +1,111 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect, useRef, useState, CSSProperties } from 'react'; +import { css } from '@emotion/react'; +import { useChat } from '../../services'; +import { getChatContext } from './get_chat_context'; + +type UseChatType = + | { enabled: false } + | { + enabled: true; + src: string; + ref: React.MutableRefObject; + style: CSSProperties; + isReady: boolean; + }; + +const MESSAGE_READY = 'driftIframeReady'; +const MESSAGE_RESIZE = 'driftIframeResize'; +const MESSAGE_SET_CONTEXT = 'driftSetContext'; + +const useChatConfig = (): UseChatType => { + const ref = useRef(null); + const chat = useChat(); + const [style, setStyle] = useState({}); + const [isReady, setIsReady] = useState(false); + + useEffect(() => { + const handleMessage = (event: MessageEvent): void => { + const { current: chatIframe } = ref; + + if ( + !chat.enabled || + !chatIframe?.contentWindow || + event.source !== chatIframe?.contentWindow + ) { + return; + } + + const context = getChatContext(); + const { data: message } = event; + const { user: userConfig } = chat; + const { id, email, jwt } = userConfig; + + switch (message.type) { + case MESSAGE_READY: { + const user = { + id, + attributes: { + email, + }, + jwt, + }; + + chatIframe.contentWindow.postMessage( + { + type: MESSAGE_SET_CONTEXT, + data: { context, user }, + }, + '*' + ); + + setIsReady(true); + + break; + } + + case MESSAGE_RESIZE: { + const styles = message.data.styles || ({} as CSSProperties); + setStyle({ ...style, ...styles }); + break; + } + + default: + break; + } + }; + + window.addEventListener('message', handleMessage); + + return () => window.removeEventListener('message', handleMessage); + }, [chat, style]); + + if (chat.enabled) { + return { enabled: true, src: chat.chatURL, ref, style, isReady }; + } + + return { enabled: false }; +}; + +export const Chat = () => { + const config = useChatConfig(); + + if (!config.enabled) { + return null; + } + + const iframeStyle = css` + position: fixed; + botton: 30px; + right: 30px; + visibility: ${config.isReady ? 'visible' : 'hidden'}; + `; + + return