diff --git a/.buildkite/pipelines/fleet/packages_daily.yml b/.buildkite/pipelines/fleet/packages_daily.yml index e64358661d7b9..cecd88a948ddc 100644 --- a/.buildkite/pipelines/fleet/packages_daily.yml +++ b/.buildkite/pipelines/fleet/packages_daily.yml @@ -7,21 +7,15 @@ steps: - wait - - command: .buildkite/scripts/steps/build_kibana.sh - label: Build Kibana Distribution and Plugins - agents: - queue: c2-16 - key: build - if: "build.env('KIBANA_BUILD_ID') == null || build.env('KIBANA_BUILD_ID') == ''" - timeout_in_minutes: 60 - - - wait - - command: .buildkite/scripts/steps/fleet/install_all_packages.sh label: Install All Packages agents: queue: n2-2 - key: linting + env: + # ensure that the FTR logs all output for these tests + DISABLE_CI_LOG_OUTPUT_CAPTURE: 'true' + # disable downloading a kibana build, this step does not use it + KIBANA_BUILD_ID: 'false' timeout_in_minutes: 90 - wait: ~ diff --git a/.buildkite/scripts/download_build_artifacts.sh b/.buildkite/scripts/download_build_artifacts.sh index 1e793346da33b..1b52e82c2d66b 100755 --- a/.buildkite/scripts/download_build_artifacts.sh +++ b/.buildkite/scripts/download_build_artifacts.sh @@ -4,25 +4,27 @@ set -euo pipefail source "$(dirname "$0")/common/util.sh" -if [[ ! -d "$KIBANA_BUILD_LOCATION/bin" ]]; then - echo '--- Downloading Distribution and Plugin artifacts' +if [[ "${KIBANA_BUILD_ID:-}" != "false" ]]; then + if [[ ! -d "$KIBANA_BUILD_LOCATION/bin" ]]; then + echo '--- Downloading Distribution and Plugin artifacts' - cd "$WORKSPACE" + cd "$WORKSPACE" - download_artifact kibana-default.tar.gz . --build "${KIBANA_BUILD_ID:-$BUILDKITE_BUILD_ID}" - download_artifact kibana-default-plugins.tar.gz . --build "${KIBANA_BUILD_ID:-$BUILDKITE_BUILD_ID}" + download_artifact kibana-default.tar.gz . --build "${KIBANA_BUILD_ID:-$BUILDKITE_BUILD_ID}" + download_artifact kibana-default-plugins.tar.gz . --build "${KIBANA_BUILD_ID:-$BUILDKITE_BUILD_ID}" - mkdir -p "$KIBANA_BUILD_LOCATION" - tar -xzf kibana-default.tar.gz -C "$KIBANA_BUILD_LOCATION" --strip=1 + mkdir -p "$KIBANA_BUILD_LOCATION" + tar -xzf kibana-default.tar.gz -C "$KIBANA_BUILD_LOCATION" --strip=1 - if is_pr_with_label "ci:build-example-plugins"; then - # Testing against an example plugin distribution is not supported, - # mostly due to snapshot failures when testing UI element lists - rm -rf "$KIBANA_BUILD_LOCATION/plugins" - mkdir "$KIBANA_BUILD_LOCATION/plugins" - fi + if is_pr_with_label "ci:build-example-plugins"; then + # Testing against an example plugin distribution is not supported, + # mostly due to snapshot failures when testing UI element lists + rm -rf "$KIBANA_BUILD_LOCATION/plugins" + mkdir "$KIBANA_BUILD_LOCATION/plugins" + fi - cd "$KIBANA_DIR" + cd "$KIBANA_DIR" - tar -xzf ../kibana-default-plugins.tar.gz + tar -xzf ../kibana-default-plugins.tar.gz + fi fi diff --git a/.buildkite/scripts/steps/fleet/install_all_packages.sh b/.buildkite/scripts/steps/fleet/install_all_packages.sh index b02c930160f12..eb001b4399b86 100755 --- a/.buildkite/scripts/steps/fleet/install_all_packages.sh +++ b/.buildkite/scripts/steps/fleet/install_all_packages.sh @@ -7,5 +7,6 @@ source .buildkite/scripts/steps/functional/common.sh echo '--- Installing all packages' node scripts/functional_tests \ - --debug --bail \ + --debug \ + --bail \ --config x-pack/test/fleet_packages/config.ts diff --git a/.buildkite/scripts/steps/scalability/benchmarking.sh b/.buildkite/scripts/steps/scalability/benchmarking.sh index 57f63445cb26a..9ad62d2dbddb8 100755 --- a/.buildkite/scripts/steps/scalability/benchmarking.sh +++ b/.buildkite/scripts/steps/scalability/benchmarking.sh @@ -68,15 +68,20 @@ upload_test_results() { buildkite-agent artifact upload "scalability_traces.tar.gz" } -echo "--- Download the latest artifacts from single user performance pipeline" -download_artifacts - echo "--- Clone kibana-load-testing repo and compile project" checkout_and_compile_load_runner -echo "--- Run Scalability Tests" cd "$KIBANA_DIR" -node scripts/run_scalability --kibana-install-dir "$KIBANA_BUILD_LOCATION" --journey-path "scalability_traces/server" +echo "--- Download the latest artifacts from single user performance pipeline" +download_artifacts + +if [ "$BUILDKITE_PIPELINE_SLUG" == "kibana-scalability-benchmarking-1" ]; then + echo "--- Run journey scalability tests" + node scripts/run_scalability --kibana-install-dir "$KIBANA_BUILD_LOCATION" --journey-path "scalability_traces/server" +else + echo "--- Run single apis capacity tests" + node scripts/run_scalability --kibana-install-dir "$KIBANA_BUILD_LOCATION" --journey-path "x-pack/test/scalability/apis" +fi echo "--- Upload test results" upload_test_results diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 02c94120cec22..78f3271d028a9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -13,6 +13,7 @@ /src/plugins/saved_search/ @elastic/kibana-data-discovery /x-pack/plugins/discover_enhanced/ @elastic/kibana-data-discovery /x-pack/test/functional/apps/discover/ @elastic/kibana-data-discovery +/x-pack/test/functional_with_es_ssl/apps/discover/ @elastic/kibana-data-discovery /test/functional/apps/discover/ @elastic/kibana-data-discovery /test/functional/apps/context/ @elastic/kibana-data-discovery /test/api_integration/apis/unified_field_list/ @elastic/kibana-data-discovery @@ -607,20 +608,19 @@ /x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions @elastic/security-solution-platform @elastic/security-detections-response-rules /x-pack/plugins/security_solution/server/routes @elastic/security-detections-response @elastic/security-threat-hunting - -## Security Solution sub teams - security-onboarding-and-lifecycle-mgt -/x-pack/plugins/security_solution/public/management/ @elastic/security-onboarding-and-lifecycle-mgt -/x-pack/plugins/security_solution/public/common/lib/endpoint*/ @elastic/security-onboarding-and-lifecycle-mgt -/x-pack/plugins/security_solution/public/common/components/endpoint/ @elastic/security-onboarding-and-lifecycle-mgt -/x-pack/plugins/security_solution/common/endpoint/ @elastic/security-onboarding-and-lifecycle-mgt -/x-pack/plugins/security_solution/server/endpoint/ @elastic/security-onboarding-and-lifecycle-mgt -/x-pack/plugins/security_solution/server/lists_integration/endpoint/ @elastic/security-onboarding-and-lifecycle-mgt -/x-pack/plugins/security_solution/server/lib/license/ @elastic/security-onboarding-and-lifecycle-mgt -/x-pack/plugins/security_solution/server/fleet_integration/ @elastic/security-onboarding-and-lifecycle-mgt -/x-pack/plugins/security_solution/scripts/endpoint/event_filters/ @elastic/security-onboarding-and-lifecycle-mgt -/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/ @elastic/security-onboarding-and-lifecycle-mgt -/x-pack/test/security_solution_endpoint/apps/endpoint/ @elastic/security-onboarding-and-lifecycle-mgt -/x-pack/test/security_solution_endpoint_api_int/ @elastic/security-onboarding-and-lifecycle-mgt +## Security Solution sub teams - security-defend-workflows +/x-pack/plugins/security_solution/public/management/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/public/common/lib/endpoint*/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/public/common/components/endpoint/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/common/endpoint/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/server/endpoint/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/server/lists_integration/endpoint/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/server/lib/license/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/server/fleet_integration/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/scripts/endpoint/event_filters/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/ @elastic/security-defend-workflows +/x-pack/test/security_solution_endpoint/apps/endpoint/ @elastic/security-defend-workflows +/x-pack/test/security_solution_endpoint_api_int/ @elastic/security-defend-workflows ## Security Solution sub teams - security-telemetry (Data Engineering) x-pack/plugins/security_solution/server/usage/ @elastic/security-data-analytics @@ -643,11 +643,11 @@ x-pack/plugins/threat_intelligence @elastic/protections-experience x-pack/plugins/security_solution/public/threat_intelligence @elastic/protections-experience x-pack/test/threat_intelligence_cypress @elastic/protections-experience -# Security Asset Management -/x-pack/plugins/osquery @elastic/security-asset-management -/x-pack/plugins/security_solution/common/detection_engine/rule_response_actions @elastic/security-asset-management -/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions @elastic/security-asset-management -/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions @elastic/security-asset-management +# Security Defend Workflows - OSQuery Ownership +/x-pack/plugins/osquery @elastic/security-defend-workflows +/x-pack/plugins/security_solution/common/detection_engine/rule_response_actions @elastic/security-defend-workflows +/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions @elastic/security-defend-workflows +/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions @elastic/security-defend-workflows # Cloud Security Posture /x-pack/plugins/cloud_security_posture/ @elastic/kibana-cloud-security-posture @@ -1072,7 +1072,9 @@ packages/shared-ux/storybook/mock @elastic/kibana-global-experience x-pack/packages/ml/agg_utils @elastic/ml-ui x-pack/packages/ml/aiops_components @elastic/ml-ui x-pack/packages/ml/aiops_utils @elastic/ml-ui +x-pack/packages/ml/is_defined @elastic/ml-ui x-pack/packages/ml/is_populated_object @elastic/ml-ui +x-pack/packages/ml/local_storage @elastic/ml-ui x-pack/packages/ml/nested_property @elastic/ml-ui x-pack/packages/ml/string_hash @elastic/ml-ui x-pack/packages/ml/url_state @elastic/ml-ui diff --git a/.gitignore b/.gitignore index 112d2775f01d6..d3abc8607b9c7 100644 --- a/.gitignore +++ b/.gitignore @@ -113,3 +113,4 @@ fleet-server.yml /packages/kbn-package-map/package-map.json /packages/kbn-synthetic-package-map/ **/.synthetics/ +**/.journeys/ diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 24b6403aeeab0..413b9153c5283 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index e04f503c998e0..5326a453f439a 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 95bd61adda0e4..f1c2bdd3907df 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.devdocs.json b/api_docs/alerting.devdocs.json index 4302ded1c3294..75f83e3ffe5c6 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -2224,6 +2224,264 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "alerting", + "id": "def-server.RuleExecutorServices.share", + "type": "Object", + "tags": [], + "label": "share", + "description": [], + "signature": [ + { + "pluginId": "share", + "scope": "server", + "docId": "kibSharePluginApi", + "section": "def-server.SharePluginStart", + "text": "SharePluginStart" + } + ], + "path": "x-pack/plugins/alerting/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "alerting", + "id": "def-server.RuleExecutorServices.dataViews", + "type": "Object", + "tags": [], + "label": "dataViews", + "description": [], + "signature": [ + "{ get: (id: string, displayErrors?: boolean, refreshFields?: boolean) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ">; delete: (indexPatternId: string) => Promise<{}>; create: (spec: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + }, + ", skipFetchFields?: boolean, displayErrors?: boolean) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ">; find: (search: string, size?: number) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + "[]>; getCanSave: () => Promise; getIds: (refresh?: boolean) => Promise; getTitles: (refresh?: boolean) => Promise; getIdsWithTitle: (refresh?: boolean) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewListItem", + "text": "DataViewListItem" + }, + "[]>; clearCache: () => void; clearInstanceCache: (id?: string | undefined) => void; getCache: () => Promise<", + { + "pluginId": "@kbn/core-saved-objects-common", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsCommonPluginApi", + "section": "def-common.SavedObject", + "text": "SavedObject" + }, + "<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSavedObjectAttrs", + "text": "DataViewSavedObjectAttrs" + }, + ">[] | null | undefined>; getDefault: (displayErrors?: boolean) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | null>; getDefaultId: () => Promise; setDefault: (id: string | null, force?: boolean) => Promise; hasUserDataView: () => Promise; getFieldsForWildcard: (options: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.GetFieldsOptions", + "text": "GetFieldsOptions" + }, + ") => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldSpec", + "text": "FieldSpec" + }, + "[]>; getFieldsForIndexPattern: (indexPattern: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + }, + ", options?: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.GetFieldsOptions", + "text": "GetFieldsOptions" + }, + " | undefined) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldSpec", + "text": "FieldSpec" + }, + "[]>; refreshFields: (dataView: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ", displayErrors?: boolean) => Promise; fieldArrayToMap: (fields: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldSpec", + "text": "FieldSpec" + }, + "[], fieldAttrs?: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldAttrs", + "text": "FieldAttrs" + }, + " | undefined) => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewFieldMap", + "text": "DataViewFieldMap" + }, + "; savedObjectToSpec: (savedObject: ", + { + "pluginId": "@kbn/core-saved-objects-common", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsCommonPluginApi", + "section": "def-common.SavedObject", + "text": "SavedObject" + }, + "<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewAttributes", + "text": "DataViewAttributes" + }, + ">) => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + }, + "; createAndSave: (spec: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + }, + ", override?: boolean, skipFetchFields?: boolean, displayErrors?: boolean) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ">; createSavedObject: (dataView: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ", override?: boolean, displayErrors?: boolean) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ">; updateSavedObject: (indexPattern: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ", saveAttempts?: number, ignoreErrors?: boolean, displayErrors?: boolean) => Promise; getDefaultDataView: (refreshFields?: boolean | undefined) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | null>; }" + ], + "path": "x-pack/plugins/alerting/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "alerting", "id": "def-server.RuleExecutorServices.ruleResultService", @@ -3113,7 +3371,7 @@ "section": "def-server.BulkOperationError", "text": "BulkOperationError" }, - "[]; rules: (", + "[]; total: number; rules: (", { "pluginId": "alerting", "scope": "common", @@ -3123,7 +3381,7 @@ }, " | ", "RuleWithLegacyId", - ")[]; total: number; taskIdsFailedToBeDeleted: string[]; }>; bulkEdit: )[]; taskIdsFailedToBeDeleted: string[]; }>; bulkEdit: | visTypeTimeseries, graph, dataViewManagement, dataViews | - | | | visTypeTimeseries, graph, dataViewManagement, dataViews | - | | | visTypeTimeseries, graph, dataViewManagement | - | -| | observability, dataVisualizer, fleet, cloudSecurityPosture, discoverEnhanced, osquery, synthetics | - | +| | observability, dataVisualizer, fleet, cloudSecurityPosture, discoverEnhanced, osquery, synthetics | - | | | dataViewManagement, dataViews | - | | | dataViews, dataViewManagement | - | | | dataViewManagement, dataViews | - | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 97cff5b465e0b..ef478e663324f 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -310,7 +310,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [overview_tab.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/overview_tab.tsx#:~:text=indexPatternId) | - | +| | [overview_tab.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/overview_tab.tsx#:~:text=indexPatternId) | - | @@ -433,7 +433,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=title), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=title), [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=title), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=title) | - | | | [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=title), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=title), [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=title), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=title) | - | | | [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=title), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=title) | - | -| | [results_links.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx#:~:text=indexPatternId), [actions_panel.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx#:~:text=indexPatternId) | - | +| | [results_links.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx#:~:text=indexPatternId), [actions_panel.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx#:~:text=indexPatternId) | - | @@ -460,7 +460,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [explore_data_context_menu_action.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_context_menu_action.ts#:~:text=indexPatternId), [explore_data_chart_action.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.ts#:~:text=indexPatternId) | - | +| | [explore_data_context_menu_action.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_context_menu_action.ts#:~:text=indexPatternId), [explore_data_chart_action.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.ts#:~:text=indexPatternId) | - | @@ -521,7 +521,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [filter_dataset.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx#:~:text=title), [filter_log_level.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx#:~:text=title), [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title), [filter_dataset.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx#:~:text=title), [filter_log_level.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx#:~:text=title), [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title) | - | | | [filter_dataset.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx#:~:text=title), [filter_log_level.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx#:~:text=title), [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title), [filter_dataset.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx#:~:text=title), [filter_log_level.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx#:~:text=title), [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title) | - | | | [filter_dataset.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx#:~:text=title), [filter_log_level.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx#:~:text=title), [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title) | - | -| | [use_get_logs_discover_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/hooks/use_get_logs_discover_link.tsx#:~:text=indexPatternId) | - | +| | [use_get_logs_discover_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/hooks/use_get_logs_discover_link.tsx#:~:text=indexPatternId) | - | | | [tutorial_directory_header_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/components/home_integration/tutorial_directory_header_link.tsx#:~:text=RedirectAppLinks), [tutorial_directory_header_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/components/home_integration/tutorial_directory_header_link.tsx#:~:text=RedirectAppLinks), [tutorial_directory_header_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/components/home_integration/tutorial_directory_header_link.tsx#:~:text=RedirectAppLinks), [custom_assets_accordion.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/components/custom_assets_accordion.tsx#:~:text=RedirectAppLinks), [custom_assets_accordion.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/components/custom_assets_accordion.tsx#:~:text=RedirectAppLinks), [custom_assets_accordion.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/components/custom_assets_accordion.tsx#:~:text=RedirectAppLinks), [agent_logs.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/agent_logs.tsx#:~:text=RedirectAppLinks), [agent_logs.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/agent_logs.tsx#:~:text=RedirectAppLinks), [agent_logs.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/agent_logs.tsx#:~:text=RedirectAppLinks), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/integrations/app.tsx#:~:text=RedirectAppLinks)+ 5 more | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/plugin.ts#:~:text=disabled) | 8.8.0 | | | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/plugin.ts#:~:text=disabled) | 8.8.0 | @@ -742,7 +742,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [observability_data_views.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts#:~:text=title), [report_definition_field.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx#:~:text=title), [use_filter_values.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts#:~:text=title), [filter_value_btn.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx#:~:text=title), [sample_attribute.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts#:~:text=title), [sample_attribute_kpi.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts#:~:text=title), [sample_attribute_with_reference_lines.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_with_reference_lines.ts#:~:text=title), [test_formula_metric_attribute.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/test_formula_metric_attribute.ts#:~:text=title), [single_metric_attributes.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.test.ts#:~:text=title), [single_metric_attributes.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.test.ts#:~:text=title)+ 14 more | - | | | [observability_data_views.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts#:~:text=title), [report_definition_field.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx#:~:text=title), [use_filter_values.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts#:~:text=title), [filter_value_btn.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx#:~:text=title), [sample_attribute.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts#:~:text=title), [sample_attribute_kpi.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts#:~:text=title), [sample_attribute_with_reference_lines.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_with_reference_lines.ts#:~:text=title), [test_formula_metric_attribute.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/test_formula_metric_attribute.ts#:~:text=title), [single_metric_attributes.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.test.ts#:~:text=title), [single_metric_attributes.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.test.ts#:~:text=title)+ 14 more | - | | | [observability_data_views.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts#:~:text=title), [report_definition_field.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx#:~:text=title), [use_filter_values.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts#:~:text=title), [filter_value_btn.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx#:~:text=title), [sample_attribute.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts#:~:text=title), [sample_attribute_kpi.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts#:~:text=title), [sample_attribute_with_reference_lines.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_with_reference_lines.ts#:~:text=title), [test_formula_metric_attribute.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/test_formula_metric_attribute.ts#:~:text=title), [single_metric_attributes.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.test.ts#:~:text=title), [single_metric_attributes.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.test.ts#:~:text=title)+ 2 more | - | -| | [use_discover_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_discover_link.tsx#:~:text=indexPatternId) | - | +| | [use_discover_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_discover_link.tsx#:~:text=indexPatternId) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/application/index.tsx#:~:text=RedirectAppLinks), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/application/index.tsx#:~:text=RedirectAppLinks), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/application/index.tsx#:~:text=RedirectAppLinks) | - | @@ -751,7 +751,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [pack_queries_status_table.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx#:~:text=indexPatternId), [view_results_in_discover.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/osquery/public/discover/view_results_in_discover.tsx#:~:text=indexPatternId), [use_discover_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/osquery/public/common/hooks/use_discover_link.tsx#:~:text=indexPatternId) | - | +| | [pack_queries_status_table.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx#:~:text=indexPatternId), [view_results_in_discover.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/osquery/public/discover/view_results_in_discover.tsx#:~:text=indexPatternId), [use_discover_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/osquery/public/common/hooks/use_discover_link.tsx#:~:text=indexPatternId) | - | | | [empty_state.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/osquery/public/components/empty_state.tsx#:~:text=KibanaPageTemplate), [empty_state.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/osquery/public/components/empty_state.tsx#:~:text=KibanaPageTemplate) | - | @@ -968,7 +968,7 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [filter_group.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx#:~:text=title), [filters_expression_select.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx#:~:text=title), [filter_group.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx#:~:text=title), [filters_expression_select.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx#:~:text=title) | - | | | [filter_group.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx#:~:text=title), [filters_expression_select.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx#:~:text=title), [filter_group.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx#:~:text=title), [filters_expression_select.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx#:~:text=title) | - | | | [filter_group.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx#:~:text=title), [filters_expression_select.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx#:~:text=title) | - | -| | [stderr_logs.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/synthetics/check_steps/stderr_logs.tsx#:~:text=indexPatternId) | - | +| | [stderr_logs.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/synthetics/check_steps/stderr_logs.tsx#:~:text=indexPatternId) | - | | | [alert_messages.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/lib/alert_types/alert_messages.tsx#:~:text=RedirectAppLinks), [alert_messages.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/lib/alert_types/alert_messages.tsx#:~:text=RedirectAppLinks), [alert_messages.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/lib/alert_types/alert_messages.tsx#:~:text=RedirectAppLinks), [uptime_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_app.tsx#:~:text=RedirectAppLinks), [uptime_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_app.tsx#:~:text=RedirectAppLinks), [uptime_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_app.tsx#:~:text=RedirectAppLinks), [synthetics_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx#:~:text=RedirectAppLinks), [synthetics_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx#:~:text=RedirectAppLinks), [synthetics_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx#:~:text=RedirectAppLinks) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 700f4f8045c66..1c38c7be918a7 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 13d80a858faec..c89652e7f5bce 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.devdocs.json b/api_docs/discover.devdocs.json index 12ff50d40da52..af684dd0a989d 100644 --- a/api_docs/discover.devdocs.json +++ b/api_docs/discover.devdocs.json @@ -242,465 +242,660 @@ "interfaces": [ { "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams", + "id": "def-public.DiscoverGridSettings", "type": "Interface", "tags": [], - "label": "DiscoverAppLocatorParams", + "label": "DiscoverGridSettings", "description": [], - "signature": [ - { - "pluginId": "discover", - "scope": "public", - "docId": "kibDiscoverPluginApi", - "section": "def-public.DiscoverAppLocatorParams", - "text": "DiscoverAppLocatorParams" - }, - " extends ", - { - "pluginId": "@kbn/utility-types", - "scope": "common", - "docId": "kibKbnUtilityTypesPluginApi", - "section": "def-common.SerializableRecord", - "text": "SerializableRecord" - } - ], - "path": "src/plugins/discover/public/locator.ts", + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.savedSearchId", - "type": "string", + "id": "def-public.DiscoverGridSettings.columns", + "type": "Object", "tags": [], - "label": "savedSearchId", - "description": [ - "\nOptionally set saved search ID." - ], + "label": "columns", + "description": [], "signature": [ - "string | undefined" + "Record | undefined" ], - "path": "src/plugins/discover/public/locator.ts", + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false - }, + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "discover", + "id": "def-public.DiscoverGridSettingsColumn", + "type": "Interface", + "tags": [], + "label": "DiscoverGridSettingsColumn", + "description": [], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ { "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.dataViewId", - "type": "string", + "id": "def-public.DiscoverGridSettingsColumn.width", + "type": "number", "tags": [], - "label": "dataViewId", - "description": [ - "\nOptionally set index pattern / data view ID." - ], + "label": "width", + "description": [], "signature": [ - "string | undefined" + "number | undefined" ], - "path": "src/plugins/discover/public/locator.ts", + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "discover", + "id": "def-public.ISearchEmbeddable", + "type": "Interface", + "tags": [], + "label": "ISearchEmbeddable", + "description": [], + "signature": [ + { + "pluginId": "discover", + "scope": "public", + "docId": "kibDiscoverPluginApi", + "section": "def-public.ISearchEmbeddable", + "text": "ISearchEmbeddable" + }, + " extends ", + { + "pluginId": "embeddable", + "scope": "public", + "docId": "kibEmbeddablePluginApi", + "section": "def-public.IEmbeddable", + "text": "IEmbeddable" + }, + "<", + { + "pluginId": "discover", + "scope": "public", + "docId": "kibDiscoverPluginApi", + "section": "def-public.SearchInput", + "text": "SearchInput" }, + ", ", + "SearchOutput", + ", any>" + ], + "path": "src/plugins/discover/public/embeddable/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ { "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.indexPatternId", - "type": "string", - "tags": [ - "deprecated" - ], - "label": "indexPatternId", - "description": [ - "\nDuplication of dataViewId" - ], + "id": "def-public.ISearchEmbeddable.getSavedSearch", + "type": "Function", + "tags": [], + "label": "getSavedSearch", + "description": [], "signature": [ - "string | undefined" + "() => ", + { + "pluginId": "savedSearch", + "scope": "public", + "docId": "kibSavedSearchPluginApi", + "section": "def-public.SavedSearch", + "text": "SavedSearch" + } ], - "path": "src/plugins/discover/public/locator.ts", - "deprecated": true, + "path": "src/plugins/discover/public/embeddable/types.ts", + "deprecated": false, "trackAdoption": false, - "references": [ + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SavedSearch", + "type": "Interface", + "tags": [], + "label": "SavedSearch", + "description": [], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "discover", + "id": "def-public.SavedSearch.searchSource", + "type": "Object", + "tags": [], + "label": "searchSource", + "description": [], + "signature": [ + "{ create: () => ", { - "plugin": "observability", - "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_discover_link.tsx" + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSource", + "text": "SearchSource" }, + "; history: ", + "SearchRequest", + "[]; setOverwriteDataViewType: (overwriteType: string | false | undefined) => void; setField: (field: K, value: ", { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx" + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSourceFields", + "text": "SearchSourceFields" }, + "[K]) => ", { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/hooks/use_get_logs_discover_link.tsx" + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSource", + "text": "SearchSource" }, + "; removeField: (field: K) => ", { - "plugin": "discoverEnhanced", - "path": "x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_context_menu_action.ts" + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSource", + "text": "SearchSource" }, + "; setFields: (newFields: ", { - "plugin": "discoverEnhanced", - "path": "x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.ts" + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSourceFields", + "text": "SearchSourceFields" }, + ") => ", { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx" + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSource", + "text": "SearchSource" }, + "; getId: () => string; getFields: () => ", { - "plugin": "osquery", - "path": "x-pack/plugins/osquery/public/discover/view_results_in_discover.tsx" + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSourceFields", + "text": "SearchSourceFields" }, + "; getField: (field: K, recurse?: boolean) => ", { - "plugin": "synthetics", - "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/synthetics/check_steps/stderr_logs.tsx" - } - ] - }, - { - "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.dataViewSpec", - "type": "Object", - "tags": [], - "label": "dataViewSpec", - "description": [], - "signature": [ + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSourceFields", + "text": "SearchSourceFields" + }, + "[K]; getActiveIndexFilter: () => string[]; getOwnField: (field: K) => ", { - "pluginId": "@kbn/es-query", + "pluginId": "data", "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.TimeRange", - "text": "TimeRange" + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSourceFields", + "text": "SearchSourceFields" }, - " | undefined" - ], - "path": "src/plugins/discover/public/locator.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.refreshInterval", - "type": "CompoundType", - "tags": [], - "label": "refreshInterval", - "description": [ - "\nOptionally set the refresh interval." - ], - "signature": [ - "(", + "[K]; createCopy: () => ", { "pluginId": "data", "scope": "common", - "docId": "kibDataQueryPluginApi", - "section": "def-common.RefreshInterval", - "text": "RefreshInterval" + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSource", + "text": "SearchSource" }, - " & ", + "; createChild: (options?: {}) => ", { - "pluginId": "@kbn/utility-types", + "pluginId": "data", "scope": "common", - "docId": "kibKbnUtilityTypesPluginApi", - "section": "def-common.SerializableRecord", - "text": "SerializableRecord" + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSource", + "text": "SearchSource" }, - ") | undefined" - ], - "path": "src/plugins/discover/public/locator.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.filters", - "type": "Array", - "tags": [], - "label": "filters", - "description": [ - "\nOptionally apply filters." - ], - "signature": [ + "; setParent: (parent?: ", { - "pluginId": "@kbn/es-query", + "pluginId": "data", "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.Filter", - "text": "Filter" + "docId": "kibDataSearchPluginApi", + "section": "def-common.ISearchSource", + "text": "ISearchSource" }, - "[] | undefined" - ], - "path": "src/plugins/discover/public/locator.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.query", - "type": "CompoundType", - "tags": [], - "label": "query", - "description": [ - "\nOptionally set a query." - ], - "signature": [ + " | undefined, options?: ", { - "pluginId": "@kbn/es-query", + "pluginId": "data", "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.Query", - "text": "Query" + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSourceOptions", + "text": "SearchSourceOptions" }, - " | ", + ") => ", { - "pluginId": "@kbn/es-query", + "pluginId": "data", "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.AggregateQuery", - "text": "AggregateQuery" + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSource", + "text": "SearchSource" }, - " | undefined" + "; getParent: () => ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSource", + "text": "SearchSource" + }, + " | undefined; fetch$: (options?: ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSourceSearchOptions", + "text": "SearchSourceSearchOptions" + }, + ") => ", + "Observable", + "<", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.IKibanaSearchResponse", + "text": "IKibanaSearchResponse" + }, + "<", + "SearchResponse", + ">>>; fetch: (options?: ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSourceSearchOptions", + "text": "SearchSourceSearchOptions" + }, + ") => Promise<", + "SearchResponse", + ">>; onRequestStart: (handler: (searchSource: ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSource", + "text": "SearchSource" + }, + ", options?: ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSourceSearchOptions", + "text": "SearchSourceSearchOptions" + }, + " | undefined) => Promise) => void; getSearchRequestBody: () => any; destroy: () => void; getSerializedFields: (recurse?: boolean, includeFields?: boolean) => ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SerializedSearchSourceFields", + "text": "SerializedSearchSourceFields" + }, + "; serialize: () => { searchSourceJSON: string; references: ", + { + "pluginId": "@kbn/core-saved-objects-common", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsCommonPluginApi", + "section": "def-common.SavedObjectReference", + "text": "SavedObjectReference" + }, + "[]; }; toExpressionAst: ({ asDatatable }?: ExpressionAstOptions) => ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.ExpressionAstExpression", + "text": "ExpressionAstExpression" + }, + "; parseActiveIndexPatternFromQueryString: (queryString: string) => string[]; }" ], - "path": "src/plugins/discover/public/locator.ts", + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.useHash", - "type": "CompoundType", + "id": "def-public.SavedSearch.id", + "type": "string", "tags": [], - "label": "useHash", - "description": [ - "\nIf not given, will use the uiSettings configuration for `storeInSessionStorage`. useHash determines\nwhether to hash the data in the url to avoid url length issues." - ], + "label": "id", + "description": [], "signature": [ - "boolean | undefined" + "string | undefined" ], - "path": "src/plugins/discover/public/locator.ts", + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.searchSessionId", + "id": "def-public.SavedSearch.title", "type": "string", "tags": [], - "label": "searchSessionId", - "description": [ - "\nBackground search session id" - ], + "label": "title", + "description": [], "signature": [ "string | undefined" ], - "path": "src/plugins/discover/public/locator.ts", + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.columns", + "id": "def-public.SavedSearch.sort", "type": "Array", "tags": [], - "label": "columns", - "description": [ - "\nColumns displayed in the table" - ], + "label": "sort", + "description": [], "signature": [ - "string[] | undefined" + "SortOrder", + "[] | undefined" ], - "path": "src/plugins/discover/public/locator.ts", + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.interval", - "type": "string", + "id": "def-public.SavedSearch.columns", + "type": "Array", "tags": [], - "label": "interval", - "description": [ - "\nUsed interval of the histogram" - ], + "label": "columns", + "description": [], "signature": [ - "string | undefined" + "string[] | undefined" ], - "path": "src/plugins/discover/public/locator.ts", + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.sort", - "type": "Array", - "tags": [], - "label": "sort", - "description": [ - "\nArray of the used sorting [[field,direction],...]" + "id": "def-public.SavedSearch.description", + "type": "string", + "tags": [], + "label": "description", + "description": [], + "signature": [ + "string | undefined" ], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SavedSearch.tags", + "type": "Array", + "tags": [], + "label": "tags", + "description": [], "signature": [ - "string[][] | undefined" + "string[] | undefined" ], - "path": "src/plugins/discover/public/locator.ts", + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.savedQuery", - "type": "string", + "id": "def-public.SavedSearch.grid", + "type": "Object", "tags": [], - "label": "savedQuery", - "description": [ - "\nid of the used saved query" + "label": "grid", + "description": [], + "signature": [ + "{ columns?: Record | undefined; } | undefined" ], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SavedSearch.hideChart", + "type": "CompoundType", + "tags": [], + "label": "hideChart", + "description": [], "signature": [ - "string | undefined" + "boolean | undefined" + ], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SavedSearch.sharingSavedObjectProps", + "type": "Object", + "tags": [], + "label": "sharingSavedObjectProps", + "description": [], + "signature": [ + "{ outcome?: \"conflict\" | \"exactMatch\" | \"aliasMatch\" | undefined; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; errorJSON?: string | undefined; } | undefined" ], - "path": "src/plugins/discover/public/locator.ts", + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.viewMode", + "id": "def-public.SavedSearch.viewMode", "type": "CompoundType", "tags": [], "label": "viewMode", - "description": [ - "\nTable view: Documents vs Field Statistics" - ], + "description": [], "signature": [ { - "pluginId": "discover", + "pluginId": "savedSearch", "scope": "public", - "docId": "kibDiscoverPluginApi", + "docId": "kibSavedSearchPluginApi", "section": "def-public.VIEW_MODE", "text": "VIEW_MODE" }, " | undefined" ], - "path": "src/plugins/discover/public/locator.ts", + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.hideAggregatedPreview", + "id": "def-public.SavedSearch.hideAggregatedPreview", "type": "CompoundType", "tags": [], "label": "hideAggregatedPreview", - "description": [ - "\nHide mini distribution/preview charts when in Field Statistics mode" + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SavedSearch.rowHeight", + "type": "number", + "tags": [], + "label": "rowHeight", + "description": [], + "signature": [ + "number | undefined" ], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SavedSearch.isTextBasedQuery", + "type": "CompoundType", + "tags": [], + "label": "isTextBasedQuery", + "description": [], "signature": [ "boolean | undefined" ], - "path": "src/plugins/discover/public/locator.ts", + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocatorParams.breakdownField", - "type": "string", + "id": "def-public.SavedSearch.usesAdHocDataView", + "type": "CompoundType", "tags": [], - "label": "breakdownField", - "description": [ - "\nBreakdown field" + "label": "usesAdHocDataView", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SavedSearch.timeRestore", + "type": "CompoundType", + "tags": [], + "label": "timeRestore", + "description": [], + "signature": [ + "boolean | undefined" ], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SavedSearch.timeRange", + "type": "Object", + "tags": [], + "label": "timeRange", + "description": [], "signature": [ - "string | undefined" + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataQueryPluginApi", + "section": "def-common.TimeRange", + "text": "TimeRange" + }, + " | undefined" ], - "path": "src/plugins/discover/public/locator.ts", + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "discover", - "id": "def-public.DiscoverGridSettings", - "type": "Interface", - "tags": [], - "label": "DiscoverGridSettings", - "description": [], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + }, { "parentPluginId": "discover", - "id": "def-public.DiscoverGridSettings.columns", + "id": "def-public.SavedSearch.refreshInterval", "type": "Object", "tags": [], - "label": "columns", + "label": "refreshInterval", "description": [], "signature": [ - "Record | undefined" + " | undefined" ], "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "discover", - "id": "def-public.DiscoverGridSettingsColumn", - "type": "Interface", - "tags": [], - "label": "DiscoverGridSettingsColumn", - "description": [], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + }, { "parentPluginId": "discover", - "id": "def-public.DiscoverGridSettingsColumn.width", + "id": "def-public.SavedSearch.rowsPerPage", "type": "number", "tags": [], - "label": "width", + "label": "rowsPerPage", "description": [], "signature": [ "number | undefined" @@ -708,44 +903,47 @@ "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SavedSearch.breakdownField", + "type": "string", + "tags": [], + "label": "breakdownField", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false }, { "parentPluginId": "discover", - "id": "def-public.ISearchEmbeddable", + "id": "def-public.SearchInput", "type": "Interface", "tags": [], - "label": "ISearchEmbeddable", + "label": "SearchInput", "description": [], "signature": [ { "pluginId": "discover", "scope": "public", "docId": "kibDiscoverPluginApi", - "section": "def-public.ISearchEmbeddable", - "text": "ISearchEmbeddable" + "section": "def-public.SearchInput", + "text": "SearchInput" }, " extends ", { "pluginId": "embeddable", - "scope": "public", + "scope": "common", "docId": "kibEmbeddablePluginApi", - "section": "def-public.IEmbeddable", - "text": "IEmbeddable" - }, - "<", - { - "pluginId": "discover", - "scope": "public", - "docId": "kibDiscoverPluginApi", - "section": "def-public.SearchInput", - "text": "SearchInput" - }, - ", ", - "SearchOutput", - ", any>" + "section": "def-common.EmbeddableInput", + "text": "EmbeddableInput" + } ], "path": "src/plugins/discover/public/embeddable/types.ts", "deprecated": false, @@ -753,748 +951,835 @@ "children": [ { "parentPluginId": "discover", - "id": "def-public.ISearchEmbeddable.getSavedSearch", - "type": "Function", + "id": "def-public.SearchInput.timeRange", + "type": "Object", "tags": [], - "label": "getSavedSearch", + "label": "timeRange", "description": [], "signature": [ - "() => ", - { - "pluginId": "savedSearch", - "scope": "public", - "docId": "kibSavedSearchPluginApi", - "section": "def-public.SavedSearch", - "text": "SavedSearch" - } + "{ from: string; to: string; mode?: \"absolute\" | \"relative\" | undefined; }" ], "path": "src/plugins/discover/public/embeddable/types.ts", "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "discover", - "id": "def-public.SavedSearch", - "type": "Interface", - "tags": [], - "label": "SavedSearch", - "description": [], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "trackAdoption": false + }, { "parentPluginId": "discover", - "id": "def-public.SavedSearch.searchSource", + "id": "def-public.SearchInput.timeslice", "type": "Object", "tags": [], - "label": "searchSource", + "label": "timeslice", + "description": [], + "signature": [ + "[number, number] | undefined" + ], + "path": "src/plugins/discover/public/embeddable/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SearchInput.query", + "type": "Object", + "tags": [], + "label": "query", "description": [], "signature": [ - "{ create: () => ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSource", - "text": "SearchSource" - }, - "; history: ", - "SearchRequest", - "[]; setOverwriteDataViewType: (overwriteType: string | false | undefined) => void; setField: (field: K, value: ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSourceFields", - "text": "SearchSourceFields" - }, - "[K]) => ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSource", - "text": "SearchSource" - }, - "; removeField: (field: K) => ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSource", - "text": "SearchSource" - }, - "; setFields: (newFields: ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSourceFields", - "text": "SearchSourceFields" - }, - ") => ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSource", - "text": "SearchSource" - }, - "; getId: () => string; getFields: () => ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSourceFields", - "text": "SearchSourceFields" - }, - "; getField: (field: K, recurse?: boolean) => ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSourceFields", - "text": "SearchSourceFields" - }, - "[K]; getActiveIndexFilter: () => string[]; getOwnField: (field: K) => ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSourceFields", - "text": "SearchSourceFields" - }, - "[K]; createCopy: () => ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSource", - "text": "SearchSource" - }, - "; createChild: (options?: {}) => ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSource", - "text": "SearchSource" - }, - "; setParent: (parent?: ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.ISearchSource", - "text": "ISearchSource" - }, - " | undefined, options?: ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSourceOptions", - "text": "SearchSourceOptions" - }, - ") => ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSource", - "text": "SearchSource" - }, - "; getParent: () => ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSource", - "text": "SearchSource" - }, - " | undefined; fetch$: (options?: ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSourceSearchOptions", - "text": "SearchSourceSearchOptions" - }, - ") => ", - "Observable", - "<", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.IKibanaSearchResponse", - "text": "IKibanaSearchResponse" - }, - "<", - "SearchResponse", - ">>>; fetch: (options?: ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSourceSearchOptions", - "text": "SearchSourceSearchOptions" - }, - ") => Promise<", - "SearchResponse", - ">>; onRequestStart: (handler: (searchSource: ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSource", - "text": "SearchSource" - }, - ", options?: ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSourceSearchOptions", - "text": "SearchSourceSearchOptions" - }, - " | undefined) => Promise) => void; getSearchRequestBody: () => any; destroy: () => void; getSerializedFields: (recurse?: boolean, includeFields?: boolean) => ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SerializedSearchSourceFields", - "text": "SerializedSearchSourceFields" - }, - "; serialize: () => { searchSourceJSON: string; references: ", { - "pluginId": "@kbn/core-saved-objects-common", + "pluginId": "@kbn/es-query", "scope": "common", - "docId": "kibKbnCoreSavedObjectsCommonPluginApi", - "section": "def-common.SavedObjectReference", - "text": "SavedObjectReference" + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.Query", + "text": "Query" }, - "[]; }; toExpressionAst: ({ asDatatable }?: ExpressionAstOptions) => ", + " | undefined" + ], + "path": "src/plugins/discover/public/embeddable/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SearchInput.filters", + "type": "Array", + "tags": [], + "label": "filters", + "description": [], + "signature": [ { - "pluginId": "expressions", + "pluginId": "@kbn/es-query", "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.ExpressionAstExpression", - "text": "ExpressionAstExpression" + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.Filter", + "text": "Filter" }, - "; parseActiveIndexPatternFromQueryString: (queryString: string) => string[]; }" + "[] | undefined" ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "path": "src/plugins/discover/public/embeddable/types.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SavedSearch.id", - "type": "string", + "id": "def-public.SearchInput.hidePanelTitles", + "type": "CompoundType", "tags": [], - "label": "id", + "label": "hidePanelTitles", "description": [], "signature": [ - "string | undefined" + "boolean | undefined" ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "path": "src/plugins/discover/public/embeddable/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SearchInput.columns", + "type": "Array", + "tags": [], + "label": "columns", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/plugins/discover/public/embeddable/types.ts", "deprecated": false, "trackAdoption": false }, { - "parentPluginId": "discover", - "id": "def-public.SavedSearch.title", - "type": "string", - "tags": [], - "label": "title", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", - "deprecated": false, - "trackAdoption": false + "parentPluginId": "discover", + "id": "def-public.SearchInput.sort", + "type": "Array", + "tags": [], + "label": "sort", + "description": [], + "signature": [ + "SortOrder", + "[] | undefined" + ], + "path": "src/plugins/discover/public/embeddable/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SearchInput.rowHeight", + "type": "number", + "tags": [], + "label": "rowHeight", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "src/plugins/discover/public/embeddable/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SearchInput.rowsPerPage", + "type": "number", + "tags": [], + "label": "rowsPerPage", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "src/plugins/discover/public/embeddable/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [ + { + "parentPluginId": "discover", + "id": "def-public.VIEW_MODE", + "type": "Enum", + "tags": [], + "label": "VIEW_MODE", + "description": [], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "misc": [ + { + "parentPluginId": "discover", + "id": "def-public.SEARCH_EMBEDDABLE_TYPE", + "type": "string", + "tags": [], + "label": "SEARCH_EMBEDDABLE_TYPE", + "description": [], + "signature": [ + "\"search\"" + ], + "path": "src/plugins/discover/common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [], + "setup": { + "parentPluginId": "discover", + "id": "def-public.DiscoverSetup", + "type": "Interface", + "tags": [], + "label": "DiscoverSetup", + "description": [], + "path": "src/plugins/discover/public/plugin.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "discover", + "id": "def-public.DiscoverSetup.docViews", + "type": "Object", + "tags": [], + "label": "docViews", + "description": [], + "signature": [ + "{ addDocView(docViewRaw: ", + "DocViewInput", + " | ", + "DocViewInputFn", + "): void; }" + ], + "path": "src/plugins/discover/public/plugin.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.DiscoverSetup.locator", + "type": "Object", + "tags": [], + "label": "locator", + "description": [ + "\n`share` plugin URL locator for Discover app. Use it to generate links into\nDiscover application, for example, navigate:\n\n```ts\nawait plugins.discover.locator.navigate({\n savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d',\n indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002',\n timeRange: {\n to: 'now',\n from: 'now-15m',\n mode: 'relative',\n },\n});\n```\n\nGenerate a location:\n\n```ts\nconst location = await plugins.discover.locator.getLocation({\n savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d',\n indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002',\n timeRange: {\n to: 'now',\n from: 'now-15m',\n mode: 'relative',\n },\n});\n```" + ], + "signature": [ + { + "pluginId": "discover", + "scope": "common", + "docId": "kibDiscoverPluginApi", + "section": "def-common.DiscoverAppLocator", + "text": "DiscoverAppLocator" + }, + " | undefined" + ], + "path": "src/plugins/discover/public/plugin.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "lifecycle": "setup", + "initialIsOpen": true + }, + "start": { + "parentPluginId": "discover", + "id": "def-public.DiscoverStart", + "type": "Interface", + "tags": [], + "label": "DiscoverStart", + "description": [], + "path": "src/plugins/discover/public/plugin.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "discover", + "id": "def-public.DiscoverStart.locator", + "type": "Object", + "tags": [], + "label": "locator", + "description": [ + "\n`share` plugin URL locator for Discover app. Use it to generate links into\nDiscover application, for example, navigate:\n\n```ts\nawait plugins.discover.locator.navigate({\n savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d',\n indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002',\n timeRange: {\n to: 'now',\n from: 'now-15m',\n mode: 'relative',\n },\n});\n```\n\nGenerate a location:\n\n```ts\nconst location = await plugins.discover.locator.getLocation({\n savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d',\n indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002',\n timeRange: {\n to: 'now',\n from: 'now-15m',\n mode: 'relative',\n },\n});\n```" + ], + "signature": [ + { + "pluginId": "discover", + "scope": "common", + "docId": "kibDiscoverPluginApi", + "section": "def-common.DiscoverAppLocator", + "text": "DiscoverAppLocator" + }, + " | undefined" + ], + "path": "src/plugins/discover/public/plugin.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "lifecycle": "start", + "initialIsOpen": true + } + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [ + { + "parentPluginId": "discover", + "id": "def-common.DiscoverAppLocatorDefinition", + "type": "Class", + "tags": [], + "label": "DiscoverAppLocatorDefinition", + "description": [], + "signature": [ + { + "pluginId": "discover", + "scope": "common", + "docId": "kibDiscoverPluginApi", + "section": "def-common.DiscoverAppLocatorDefinition", + "text": "DiscoverAppLocatorDefinition" }, + " implements ", { - "parentPluginId": "discover", - "id": "def-public.SavedSearch.sort", - "type": "Array", - "tags": [], - "label": "sort", - "description": [], - "signature": [ - "SortOrder", - "[] | undefined" - ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "share", + "scope": "common", + "docId": "kibSharePluginApi", + "section": "def-common.LocatorDefinition", + "text": "LocatorDefinition" }, + "<", { - "parentPluginId": "discover", - "id": "def-public.SavedSearch.columns", - "type": "Array", - "tags": [], - "label": "columns", - "description": [], - "signature": [ - "string[] | undefined" - ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "discover", + "scope": "common", + "docId": "kibDiscoverPluginApi", + "section": "def-common.DiscoverAppLocatorParams", + "text": "DiscoverAppLocatorParams" }, + ">" + ], + "path": "src/plugins/discover/common/locator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ { "parentPluginId": "discover", - "id": "def-public.SavedSearch.description", + "id": "def-common.DiscoverAppLocatorDefinition.id", "type": "string", "tags": [], - "label": "description", + "label": "id", "description": [], "signature": [ - "string | undefined" + "\"DISCOVER_APP_LOCATOR\"" ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SavedSearch.tags", - "type": "Array", + "id": "def-common.DiscoverAppLocatorDefinition.Unnamed", + "type": "Function", "tags": [], - "label": "tags", + "label": "Constructor", "description": [], "signature": [ - "string[] | undefined" + "any" ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "children": [ + { + "parentPluginId": "discover", + "id": "def-common.DiscoverAppLocatorDefinition.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "deps", + "description": [], + "signature": [ + "DiscoverAppLocatorDependencies" + ], + "path": "src/plugins/discover/common/locator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] }, { "parentPluginId": "discover", - "id": "def-public.SavedSearch.grid", - "type": "Object", + "id": "def-common.DiscoverAppLocatorDefinition.getLocation", + "type": "Function", "tags": [], - "label": "grid", + "label": "getLocation", "description": [], "signature": [ - "{ columns?: Record | undefined; } | undefined" + ") => Promise<{ app: string; path: string; state: ", + "MainHistoryLocationState", + "; }>" ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "children": [ + { + "parentPluginId": "discover", + "id": "def-common.DiscoverAppLocatorDefinition.getLocation.$1", + "type": "Object", + "tags": [], + "label": "params", + "description": [], + "signature": [ + { + "pluginId": "discover", + "scope": "common", + "docId": "kibDiscoverPluginApi", + "section": "def-common.DiscoverAppLocatorParams", + "text": "DiscoverAppLocatorParams" + } + ], + "path": "src/plugins/discover/common/locator.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [], + "interfaces": [ + { + "parentPluginId": "discover", + "id": "def-common.DiscoverAppLocatorParams", + "type": "Interface", + "tags": [], + "label": "DiscoverAppLocatorParams", + "description": [], + "signature": [ + { + "pluginId": "discover", + "scope": "common", + "docId": "kibDiscoverPluginApi", + "section": "def-common.DiscoverAppLocatorParams", + "text": "DiscoverAppLocatorParams" }, + " extends ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.SerializableRecord", + "text": "SerializableRecord" + } + ], + "path": "src/plugins/discover/common/locator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ { "parentPluginId": "discover", - "id": "def-public.SavedSearch.hideChart", - "type": "CompoundType", + "id": "def-common.DiscoverAppLocatorParams.savedSearchId", + "type": "string", "tags": [], - "label": "hideChart", - "description": [], + "label": "savedSearchId", + "description": [ + "\nOptionally set saved search ID." + ], "signature": [ - "boolean | undefined" + "string | undefined" ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SavedSearch.sharingSavedObjectProps", - "type": "Object", + "id": "def-common.DiscoverAppLocatorParams.dataViewId", + "type": "string", "tags": [], - "label": "sharingSavedObjectProps", - "description": [], + "label": "dataViewId", + "description": [ + "\nOptionally set index pattern / data view ID." + ], "signature": [ - "{ outcome?: \"conflict\" | \"exactMatch\" | \"aliasMatch\" | undefined; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; errorJSON?: string | undefined; } | undefined" + "string | undefined" ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SavedSearch.viewMode", - "type": "CompoundType", - "tags": [], - "label": "viewMode", - "description": [], + "id": "def-common.DiscoverAppLocatorParams.indexPatternId", + "type": "string", + "tags": [ + "deprecated" + ], + "label": "indexPatternId", + "description": [ + "\nDuplication of dataViewId" + ], "signature": [ + "string | undefined" + ], + "path": "src/plugins/discover/common/locator.ts", + "deprecated": true, + "trackAdoption": false, + "references": [ { - "pluginId": "savedSearch", - "scope": "public", - "docId": "kibSavedSearchPluginApi", - "section": "def-public.VIEW_MODE", - "text": "VIEW_MODE" + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_discover_link.tsx" }, - " | undefined" - ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", - "deprecated": false, - "trackAdoption": false + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx" + }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/hooks/use_get_logs_discover_link.tsx" + }, + { + "plugin": "cloudSecurityPosture", + "path": "x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/overview_tab.tsx" + }, + { + "plugin": "discoverEnhanced", + "path": "x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_context_menu_action.ts" + }, + { + "plugin": "discoverEnhanced", + "path": "x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.ts" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/public/discover/view_results_in_discover.tsx" + }, + { + "plugin": "osquery", + "path": "x-pack/plugins/osquery/public/common/hooks/use_discover_link.tsx" + }, + { + "plugin": "synthetics", + "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/synthetics/check_steps/stderr_logs.tsx" + } + ] }, { "parentPluginId": "discover", - "id": "def-public.SavedSearch.hideAggregatedPreview", - "type": "CompoundType", + "id": "def-common.DiscoverAppLocatorParams.dataViewSpec", + "type": "Object", "tags": [], - "label": "hideAggregatedPreview", + "label": "dataViewSpec", "description": [], "signature": [ - "boolean | undefined" + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + }, + " | undefined" ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SavedSearch.rowHeight", - "type": "number", + "id": "def-common.DiscoverAppLocatorParams.timeRange", + "type": "Object", "tags": [], - "label": "rowHeight", - "description": [], - "signature": [ - "number | undefined" + "label": "timeRange", + "description": [ + "\nOptionally set the time range in the time picker." ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "discover", - "id": "def-public.SavedSearch.isTextBasedQuery", - "type": "CompoundType", - "tags": [], - "label": "isTextBasedQuery", - "description": [], "signature": [ - "boolean | undefined" + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.TimeRange", + "text": "TimeRange" + }, + " | undefined" ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SavedSearch.usesAdHocDataView", + "id": "def-common.DiscoverAppLocatorParams.refreshInterval", "type": "CompoundType", "tags": [], - "label": "usesAdHocDataView", - "description": [], - "signature": [ - "boolean | undefined" + "label": "refreshInterval", + "description": [ + "\nOptionally set the refresh interval." ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "discover", - "id": "def-public.SavedSearch.timeRestore", - "type": "CompoundType", - "tags": [], - "label": "timeRestore", - "description": [], "signature": [ - "boolean | undefined" + "(", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataQueryPluginApi", + "section": "def-common.RefreshInterval", + "text": "RefreshInterval" + }, + " & ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.SerializableRecord", + "text": "SerializableRecord" + }, + ") | undefined" ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SavedSearch.timeRange", - "type": "Object", + "id": "def-common.DiscoverAppLocatorParams.filters", + "type": "Array", "tags": [], - "label": "timeRange", - "description": [], + "label": "filters", + "description": [ + "\nOptionally apply filters." + ], "signature": [ { - "pluginId": "data", + "pluginId": "@kbn/es-query", "scope": "common", - "docId": "kibDataQueryPluginApi", - "section": "def-common.TimeRange", - "text": "TimeRange" + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.Filter", + "text": "Filter" }, - " | undefined" + "[] | undefined" ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SavedSearch.refreshInterval", - "type": "Object", + "id": "def-common.DiscoverAppLocatorParams.query", + "type": "CompoundType", "tags": [], - "label": "refreshInterval", - "description": [], + "label": "query", + "description": [ + "\nOptionally set a query." + ], "signature": [ { - "pluginId": "data", + "pluginId": "@kbn/es-query", "scope": "common", - "docId": "kibDataQueryPluginApi", - "section": "def-common.RefreshInterval", - "text": "RefreshInterval" + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.Query", + "text": "Query" + }, + " | ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.AggregateQuery", + "text": "AggregateQuery" }, " | undefined" ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SavedSearch.rowsPerPage", - "type": "number", + "id": "def-common.DiscoverAppLocatorParams.useHash", + "type": "CompoundType", "tags": [], - "label": "rowsPerPage", - "description": [], + "label": "useHash", + "description": [ + "\nIf not given, will use the uiSettings configuration for `storeInSessionStorage`. useHash determines\nwhether to hash the data in the url to avoid url length issues." + ], "signature": [ - "number | undefined" + "boolean | undefined" ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SavedSearch.breakdownField", + "id": "def-common.DiscoverAppLocatorParams.searchSessionId", "type": "string", "tags": [], - "label": "breakdownField", - "description": [], + "label": "searchSessionId", + "description": [ + "\nBackground search session id" + ], "signature": [ "string | undefined" ], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "discover", - "id": "def-public.SearchInput", - "type": "Interface", - "tags": [], - "label": "SearchInput", - "description": [], - "signature": [ - { - "pluginId": "discover", - "scope": "public", - "docId": "kibDiscoverPluginApi", - "section": "def-public.SearchInput", - "text": "SearchInput" }, - " extends ", - { - "pluginId": "embeddable", - "scope": "common", - "docId": "kibEmbeddablePluginApi", - "section": "def-common.EmbeddableInput", - "text": "EmbeddableInput" - } - ], - "path": "src/plugins/discover/public/embeddable/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { "parentPluginId": "discover", - "id": "def-public.SearchInput.timeRange", - "type": "Object", + "id": "def-common.DiscoverAppLocatorParams.columns", + "type": "Array", "tags": [], - "label": "timeRange", - "description": [], - "signature": [ - "{ from: string; to: string; mode?: \"absolute\" | \"relative\" | undefined; }" + "label": "columns", + "description": [ + "\nColumns displayed in the table" ], - "path": "src/plugins/discover/public/embeddable/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "discover", - "id": "def-public.SearchInput.timeslice", - "type": "Object", - "tags": [], - "label": "timeslice", - "description": [], "signature": [ - "[number, number] | undefined" + "string[] | undefined" ], - "path": "src/plugins/discover/public/embeddable/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SearchInput.query", - "type": "Object", + "id": "def-common.DiscoverAppLocatorParams.interval", + "type": "string", "tags": [], - "label": "query", - "description": [], + "label": "interval", + "description": [ + "\nUsed interval of the histogram" + ], "signature": [ - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.Query", - "text": "Query" - }, - " | undefined" + "string | undefined" ], - "path": "src/plugins/discover/public/embeddable/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SearchInput.filters", + "id": "def-common.DiscoverAppLocatorParams.sort", "type": "Array", "tags": [], - "label": "filters", - "description": [], + "label": "sort", + "description": [ + "\nArray of the used sorting [[field,direction],...]" + ], "signature": [ - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.Filter", - "text": "Filter" - }, - "[] | undefined" + "string[][] | undefined" ], - "path": "src/plugins/discover/public/embeddable/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SearchInput.hidePanelTitles", - "type": "CompoundType", + "id": "def-common.DiscoverAppLocatorParams.savedQuery", + "type": "string", "tags": [], - "label": "hidePanelTitles", - "description": [], + "label": "savedQuery", + "description": [ + "\nid of the used saved query" + ], "signature": [ - "boolean | undefined" + "string | undefined" ], - "path": "src/plugins/discover/public/embeddable/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SearchInput.columns", - "type": "Array", + "id": "def-common.DiscoverAppLocatorParams.viewMode", + "type": "CompoundType", "tags": [], - "label": "columns", - "description": [], + "label": "viewMode", + "description": [ + "\nTable view: Documents vs Field Statistics" + ], "signature": [ - "string[] | undefined" + "VIEW_MODE", + " | undefined" ], - "path": "src/plugins/discover/public/embeddable/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SearchInput.sort", - "type": "Array", + "id": "def-common.DiscoverAppLocatorParams.hideAggregatedPreview", + "type": "CompoundType", "tags": [], - "label": "sort", - "description": [], + "label": "hideAggregatedPreview", + "description": [ + "\nHide mini distribution/preview charts when in Field Statistics mode" + ], "signature": [ - "SortOrder", - "[] | undefined" + "boolean | undefined" ], - "path": "src/plugins/discover/public/embeddable/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SearchInput.rowHeight", - "type": "number", + "id": "def-common.DiscoverAppLocatorParams.breakdownField", + "type": "string", "tags": [], - "label": "rowHeight", - "description": [], + "label": "breakdownField", + "description": [ + "\nBreakdown field" + ], "signature": [ - "number | undefined" + "string | undefined" ], - "path": "src/plugins/discover/public/embeddable/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.SearchInput.rowsPerPage", - "type": "number", + "id": "def-common.DiscoverAppLocatorParams.isAlertResults", + "type": "CompoundType", "tags": [], - "label": "rowsPerPage", - "description": [], + "label": "isAlertResults", + "description": [ + "\nUsed when navigating to particular alert results" + ], "signature": [ - "number | undefined" + "boolean | undefined" ], - "path": "src/plugins/discover/public/embeddable/types.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false } @@ -1502,201 +1787,47 @@ "initialIsOpen": false } ], - "enums": [ - { - "parentPluginId": "discover", - "id": "def-public.VIEW_MODE", - "type": "Enum", - "tags": [], - "label": "VIEW_MODE", - "description": [], - "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - } - ], + "enums": [], "misc": [ { "parentPluginId": "discover", - "id": "def-public.DISCOVER_APP_LOCATOR", + "id": "def-common.APP_ICON", "type": "string", "tags": [], - "label": "DISCOVER_APP_LOCATOR", - "description": [], - "signature": [ - "\"DISCOVER_APP_LOCATOR\"" - ], - "path": "src/plugins/discover/public/locator.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "discover", - "id": "def-public.DiscoverAppLocator", - "type": "Type", - "tags": [], - "label": "DiscoverAppLocator", + "label": "APP_ICON", "description": [], "signature": [ - { - "pluginId": "share", - "scope": "common", - "docId": "kibSharePluginApi", - "section": "def-common.LocatorPublic", - "text": "LocatorPublic" - }, - "<", - { - "pluginId": "discover", - "scope": "public", - "docId": "kibDiscoverPluginApi", - "section": "def-public.DiscoverAppLocatorParams", - "text": "DiscoverAppLocatorParams" - }, - ">" + "\"discoverApp\"" ], - "path": "src/plugins/discover/public/locator.ts", + "path": "src/plugins/discover/common/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "discover", - "id": "def-public.SEARCH_EMBEDDABLE_TYPE", + "id": "def-common.CONTEXT_DEFAULT_SIZE_SETTING", "type": "string", "tags": [], - "label": "SEARCH_EMBEDDABLE_TYPE", + "label": "CONTEXT_DEFAULT_SIZE_SETTING", "description": [], "signature": [ - "\"search\"" + "\"context:defaultSize\"" ], "path": "src/plugins/discover/common/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false - } - ], - "objects": [], - "setup": { - "parentPluginId": "discover", - "id": "def-public.DiscoverSetup", - "type": "Interface", - "tags": [], - "label": "DiscoverSetup", - "description": [], - "path": "src/plugins/discover/public/plugin.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "discover", - "id": "def-public.DiscoverSetup.docViews", - "type": "Object", - "tags": [], - "label": "docViews", - "description": [], - "signature": [ - "{ addDocView(docViewRaw: ", - "DocViewInput", - " | ", - "DocViewInputFn", - "): void; }" - ], - "path": "src/plugins/discover/public/plugin.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "discover", - "id": "def-public.DiscoverSetup.locator", - "type": "Object", - "tags": [], - "label": "locator", - "description": [ - "\n`share` plugin URL locator for Discover app. Use it to generate links into\nDiscover application, for example, navigate:\n\n```ts\nawait plugins.discover.locator.navigate({\n savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d',\n indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002',\n timeRange: {\n to: 'now',\n from: 'now-15m',\n mode: 'relative',\n },\n});\n```\n\nGenerate a location:\n\n```ts\nconst location = await plugins.discover.locator.getLocation({\n savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d',\n indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002',\n timeRange: {\n to: 'now',\n from: 'now-15m',\n mode: 'relative',\n },\n});\n```" - ], - "signature": [ - { - "pluginId": "discover", - "scope": "public", - "docId": "kibDiscoverPluginApi", - "section": "def-public.DiscoverAppLocator", - "text": "DiscoverAppLocator" - }, - " | undefined" - ], - "path": "src/plugins/discover/public/plugin.tsx", - "deprecated": false, - "trackAdoption": false - } - ], - "lifecycle": "setup", - "initialIsOpen": true - }, - "start": { - "parentPluginId": "discover", - "id": "def-public.DiscoverStart", - "type": "Interface", - "tags": [], - "label": "DiscoverStart", - "description": [], - "path": "src/plugins/discover/public/plugin.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "discover", - "id": "def-public.DiscoverStart.locator", - "type": "Object", - "tags": [], - "label": "locator", - "description": [ - "\n`share` plugin URL locator for Discover app. Use it to generate links into\nDiscover application, for example, navigate:\n\n```ts\nawait plugins.discover.locator.navigate({\n savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d',\n indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002',\n timeRange: {\n to: 'now',\n from: 'now-15m',\n mode: 'relative',\n },\n});\n```\n\nGenerate a location:\n\n```ts\nconst location = await plugins.discover.locator.getLocation({\n savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d',\n indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002',\n timeRange: {\n to: 'now',\n from: 'now-15m',\n mode: 'relative',\n },\n});\n```" - ], - "signature": [ - { - "pluginId": "discover", - "scope": "public", - "docId": "kibDiscoverPluginApi", - "section": "def-public.DiscoverAppLocator", - "text": "DiscoverAppLocator" - }, - " | undefined" - ], - "path": "src/plugins/discover/public/plugin.tsx", - "deprecated": false, - "trackAdoption": false - } - ], - "lifecycle": "start", - "initialIsOpen": true - } - }, - "server": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - }, - "common": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [ + }, { "parentPluginId": "discover", - "id": "def-common.APP_ICON", + "id": "def-common.CONTEXT_STEP_SETTING", "type": "string", "tags": [], - "label": "APP_ICON", + "label": "CONTEXT_STEP_SETTING", "description": [], "signature": [ - "\"discoverApp\"" + "\"context:step\"" ], "path": "src/plugins/discover/common/index.ts", "deprecated": false, @@ -1705,13 +1836,13 @@ }, { "parentPluginId": "discover", - "id": "def-common.CONTEXT_DEFAULT_SIZE_SETTING", + "id": "def-common.CONTEXT_TIE_BREAKER_FIELDS_SETTING", "type": "string", "tags": [], - "label": "CONTEXT_DEFAULT_SIZE_SETTING", + "label": "CONTEXT_TIE_BREAKER_FIELDS_SETTING", "description": [], "signature": [ - "\"context:defaultSize\"" + "\"context:tieBreakerFields\"" ], "path": "src/plugins/discover/common/index.ts", "deprecated": false, @@ -1720,13 +1851,13 @@ }, { "parentPluginId": "discover", - "id": "def-common.CONTEXT_STEP_SETTING", + "id": "def-common.DEFAULT_COLUMNS_SETTING", "type": "string", "tags": [], - "label": "CONTEXT_STEP_SETTING", + "label": "DEFAULT_COLUMNS_SETTING", "description": [], "signature": [ - "\"context:step\"" + "\"defaultColumns\"" ], "path": "src/plugins/discover/common/index.ts", "deprecated": false, @@ -1735,30 +1866,45 @@ }, { "parentPluginId": "discover", - "id": "def-common.CONTEXT_TIE_BREAKER_FIELDS_SETTING", + "id": "def-common.DISCOVER_APP_LOCATOR", "type": "string", "tags": [], - "label": "CONTEXT_TIE_BREAKER_FIELDS_SETTING", + "label": "DISCOVER_APP_LOCATOR", "description": [], "signature": [ - "\"context:tieBreakerFields\"" + "\"DISCOVER_APP_LOCATOR\"" ], - "path": "src/plugins/discover/common/index.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "discover", - "id": "def-common.DEFAULT_COLUMNS_SETTING", - "type": "string", + "id": "def-common.DiscoverAppLocator", + "type": "Type", "tags": [], - "label": "DEFAULT_COLUMNS_SETTING", + "label": "DiscoverAppLocator", "description": [], "signature": [ - "\"defaultColumns\"" + { + "pluginId": "share", + "scope": "common", + "docId": "kibSharePluginApi", + "section": "def-common.LocatorPublic", + "text": "LocatorPublic" + }, + "<", + { + "pluginId": "discover", + "scope": "common", + "docId": "kibDiscoverPluginApi", + "section": "def-common.DiscoverAppLocatorParams", + "text": "DiscoverAppLocatorParams" + }, + ">" ], - "path": "src/plugins/discover/common/index.ts", + "path": "src/plugins/discover/common/locator.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index a6249b28e0f46..e2e3331413690 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 100 | 0 | 82 | 4 | +| 107 | 0 | 88 | 7 | ## Client @@ -45,6 +45,12 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco ## Common +### Classes + + +### Interfaces + + ### Consts, variables and types diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index b161948747b78..aa71287214f45 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index d4a1e2121e316..7735c63a7a2a8 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 5f9143e325995..97b0e6aea7bbc 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 590ae392d53fb..f510d2d7d5107 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index 81e2a3ba99fbc..d83da79fbc0cd 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 49e3de1a4dd6e..1b43420445e00 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index d9818cbfcf965..43b2ca892920d 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index 829df1d6d19c7..b985f9e43fed2 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index d702fad53f995..73b827f2d2efa 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 485a61341fecc..015230f284154 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index bd65d05ed0539..4ddc27e049392 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index 45afff1e36195..23629c444261e 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index 181e5c71a9f37..189ace2228f64 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index a4d369bc4de6b..0c1c4e7f460ab 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index 85d53e6aae34c..fe54dd1821b4b 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index 0e4e382553be5..cbd71d00c97af 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index b4fd11bd28e4a..1a64c0975ed79 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index 84cf748aff889..14d4655fdfc35 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index 7ed6b044ab893..37ab16cb19254 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index f31bd56f19d65..d329df494a154 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index d964b82a4cafe..492194ece2a6a 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 591b701457142..79d75c9373b7b 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 6b2fa54e253f8..abd5cd8b228d7 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index 61414295133a5..bb6c943590bd9 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 923a9cc00587b..4a9ef9a8066dc 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index 661176109da1d..aa3d76398bb17 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index 364005bb13683..f2f56a329dcb1 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index 0bb15a818eb6e..520ca8150e7d8 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -4973,6 +4973,49 @@ ], "returnComment": [] }, + { + "parentPluginId": "fleet", + "id": "def-server.ArtifactsClientInterface.bulkCreateArtifacts", + "type": "Function", + "tags": [], + "label": "bulkCreateArtifacts", + "description": [], + "signature": [ + "(optionsList: ", + "ArtifactsClientCreateOptions", + "[]) => Promise<{ artifacts?: ", + { + "pluginId": "fleet", + "scope": "server", + "docId": "kibFleetPluginApi", + "section": "def-server.Artifact", + "text": "Artifact" + }, + "[] | undefined; errors?: Error[] | undefined; }>" + ], + "path": "x-pack/plugins/fleet/server/services/artifacts/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-server.ArtifactsClientInterface.bulkCreateArtifacts.$1", + "type": "Array", + "tags": [], + "label": "optionsList", + "description": [], + "signature": [ + "ArtifactsClientCreateOptions", + "[]" + ], + "path": "x-pack/plugins/fleet/server/services/artifacts/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "fleet", "id": "def-server.ArtifactsClientInterface.deleteArtifact", @@ -14988,6 +15031,37 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "fleet", + "id": "def-common.AssetsGroupedByServiceByType", + "type": "Type", + "tags": [], + "label": "AssetsGroupedByServiceByType", + "description": [], + "signature": [ + "Record<\"kibana\", ", + { + "pluginId": "fleet", + "scope": "common", + "docId": "kibFleetPluginApi", + "section": "def-common.KibanaAssetTypeToParts", + "text": "KibanaAssetTypeToParts" + }, + "> & Record<\"elasticsearch\", ", + { + "pluginId": "fleet", + "scope": "common", + "docId": "kibFleetPluginApi", + "section": "def-common.ElasticsearchAssetTypeToParts", + "text": "ElasticsearchAssetTypeToParts" + }, + ">" + ], + "path": "x-pack/plugins/fleet/common/types/models/epm.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "fleet", "id": "def-common.BulkGetAgentPoliciesResponse", @@ -17721,9 +17795,11 @@ "type": "Object", "tags": [], "label": "ENDPOINT_PRIVILEGES", - "description": [], + "description": [ + "\ndefines endpoint package privileges\nthe key is the name of the packagePrivilege (ie. 'readSecuritySolution')\nthe value object is for mapping kibana privileges and capabilities\nsee x-pack/plugins/fleet/server/services/security/security.ts for example of how object values are used" + ], "signature": [ - "readonly [\"writeEndpointList\", \"readEndpointList\", \"writeTrustedApplications\", \"readTrustedApplications\", \"writeHostIsolationExceptions\", \"readHostIsolationExceptions\", \"writeBlocklist\", \"readBlocklist\", \"writeEventFilters\", \"readEventFilters\", \"writePolicyManagement\", \"readPolicyManagement\", \"writeActionsLogManagement\", \"readActionsLogManagement\", \"writeHostIsolation\", \"writeProcessOperations\", \"writeFileOperations\"]" + "{ [x: string]: PrivilegeMapObject; }" ], "path": "x-pack/plugins/fleet/common/constants/authz.ts", "deprecated": false, diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 250176b5962a1..481a804c3b7d0 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Fleet](https://github.com/orgs/elastic/teams/fleet) for questions regar | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1029 | 3 | 924 | 20 | +| 1032 | 3 | 926 | 20 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index d10d721f94540..c37de49ada21d 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index 31cbd3b6c6c96..52e4db85947f4 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index 082fb44cf7445..88b7bbf497afc 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index 64a0f1da5ebce..029bd3a570f1c 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 52ee9eee291ca..8e8de976f54a4 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 753551629d771..93b8b0dca2ce6 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 58e6381a13ce6..cf51135346e4c 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 1cc222f2c16bd..eb1da51e31c26 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index a2e0a7062d739..45bf64f06fca0 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index ca43a965c930b..b946a46cce234 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index cf947135386c0..5a8f87033b6d2 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index dbae3199284eb..2eea67c84789a 100644 --- a/api_docs/kbn_alerts.mdx +++ b/api_docs/kbn_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts title: "@kbn/alerts" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index 69284ba571ff8..045f9e9e533e6 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index 0c57a56d2dd06..fa1efb18383b3 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index df7c2ef4644ec..fcc9a3b5cca82 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] --- import kbnAnalyticsShippersElasticV3BrowserObj from './kbn_analytics_shippers_elastic_v3_browser.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index 4b6ee76340bd2..9e3c5096eb8da 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] --- import kbnAnalyticsShippersElasticV3CommonObj from './kbn_analytics_shippers_elastic_v3_common.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index 875751061dd79..2e0aed7ae0a3c 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] --- import kbnAnalyticsShippersElasticV3ServerObj from './kbn_analytics_shippers_elastic_v3_server.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index c1daad155d097..0b445da7609b9 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_gainsight.mdx b/api_docs/kbn_analytics_shippers_gainsight.mdx index 11f9757f47adb..b82394c789501 100644 --- a/api_docs/kbn_analytics_shippers_gainsight.mdx +++ b/api_docs/kbn_analytics_shippers_gainsight.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-gainsight title: "@kbn/analytics-shippers-gainsight" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-gainsight plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-gainsight'] --- import kbnAnalyticsShippersGainsightObj from './kbn_analytics_shippers_gainsight.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 5bc90dae8c5b4..e31d17fae07d6 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.devdocs.json b/api_docs/kbn_apm_synthtrace.devdocs.json index e411c1cdd3e47..8ac8e3da77113 100644 --- a/api_docs/kbn_apm_synthtrace.devdocs.json +++ b/api_docs/kbn_apm_synthtrace.devdocs.json @@ -25,7 +25,7 @@ "tags": [], "label": "ApmSynthtraceEsClient", "description": [], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -39,70 +39,44 @@ "signature": [ "any" ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/apm-synthtrace", "id": "def-common.ApmSynthtraceEsClient.Unnamed.$1", - "type": "Object", - "tags": [], - "label": "client", - "description": [], - "signature": [ - "default" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.Unnamed.$2", - "type": "Object", - "tags": [], - "label": "logger", - "description": [], - "signature": [ - "{ perf: (name: string, cb: () => T) => T; debug: (...args: any[]) => void; info: (...args: any[]) => void; error: (...args: any[]) => void; }" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.Unnamed.$3", - "type": "Object", + "type": "CompoundType", "tags": [], "label": "options", "description": [], "signature": [ - "ApmSynthtraceEsClientOptions", - " | undefined" + "{ client: ", + "default", + "; logger: ", + "Logger", + "; } & ", + "ApmSynthtraceEsClientOptions" ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, - "isRequired": false + "isRequired": true } ], "returnComment": [] }, { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.runningVersion", + "id": "def-common.ApmSynthtraceEsClient.clean", "type": "Function", "tags": [], - "label": "runningVersion", + "label": "clean", "description": [], "signature": [ - "() => Promise" + "() => Promise" ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, "children": [], @@ -110,61 +84,87 @@ }, { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.clean", + "id": "def-common.ApmSynthtraceEsClient.updateComponentTemplate", "type": "Function", "tags": [], - "label": "clean", + "label": "updateComponentTemplate", "description": [], "signature": [ - "(dataStreams?: string[] | undefined) => Promise" + "(name: ", + "ComponentTemplateName", + ", modify: (template: ", + "ClusterComponentTemplateSummary", + ") => ", + "IndicesIndexState", + ") => Promise" ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.clean.$1", - "type": "Array", + "id": "def-common.ApmSynthtraceEsClient.updateComponentTemplate.$1", + "type": "Enum", "tags": [], - "label": "dataStreams", + "label": "name", + "description": [], + "signature": [ + "ComponentTemplateName" + ], + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/apm-synthtrace", + "id": "def-common.ApmSynthtraceEsClient.updateComponentTemplate.$2", + "type": "Function", + "tags": [], + "label": "modify", "description": [], "signature": [ - "string[] | undefined" + "(template: ", + "ClusterComponentTemplateSummary", + ") => ", + "IndicesIndexState" ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, - "isRequired": false + "isRequired": true } ], "returnComment": [] }, { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.updateComponentTemplates", + "id": "def-common.ApmSynthtraceEsClient.refresh", "type": "Function", "tags": [], - "label": "updateComponentTemplates", + "label": "refresh", "description": [], "signature": [ - "(numberOfPrimaryShards: number) => Promise" + "(dataStreams?: string[]) => Promise<", + "ShardsOperationResponseBase", + ">" ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.updateComponentTemplates.$1", - "type": "number", + "id": "def-common.ApmSynthtraceEsClient.refresh.$1", + "type": "Array", "tags": [], - "label": "numberOfPrimaryShards", + "label": "dataStreams", "description": [], "signature": [ - "number" + "string[]" ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -174,29 +174,31 @@ }, { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.registerGcpRepository", + "id": "def-common.ApmSynthtraceEsClient.getDefaultPipeline", "type": "Function", "tags": [], - "label": "registerGcpRepository", + "label": "getDefaultPipeline", "description": [], "signature": [ - "(connectionString: string) => Promise" + "(includeSerialization?: boolean) => (base: ", + "Readable", + ") => NodeJS.WritableStream" ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.registerGcpRepository.$1", - "type": "string", + "id": "def-common.ApmSynthtraceEsClient.getDefaultPipeline.$1", + "type": "boolean", "tags": [], - "label": "connectionString", + "label": "includeSerialization", "description": [], "signature": [ - "string" + "boolean" ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -206,213 +208,117 @@ }, { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.refresh", + "id": "def-common.ApmSynthtraceEsClient.pipeline", "type": "Function", "tags": [], - "label": "refresh", + "label": "pipeline", "description": [], "signature": [ - "(dataStreams?: string[] | undefined) => Promise<", - "ShardsOperationResponseBase", - ">" + "(cb: (base: ", + "Readable", + ") => NodeJS.WritableStream) => void" ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.refresh.$1", - "type": "Array", + "id": "def-common.ApmSynthtraceEsClient.pipeline.$1", + "type": "Function", "tags": [], - "label": "dataStreams", + "label": "cb", "description": [], "signature": [ - "string[] | undefined" + "(base: ", + "Readable", + ") => NodeJS.WritableStream" ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, - "isRequired": false + "isRequired": true } ], "returnComment": [] }, { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.index", + "id": "def-common.ApmSynthtraceEsClient.getVersion", "type": "Function", "tags": [], - "label": "index", + "label": "getVersion", "description": [], "signature": [ - "(events: ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.EntityIterable", - "text": "EntityIterable" - }, - " | ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.EntityIterable", - "text": "EntityIterable" - }, - "[], options?: ", - "StreamToBulkOptions", - "<", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmFields", - "text": "ApmFields" - }, - "> | undefined, streamProcessor?: ", - "StreamProcessor", - "<", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmFields", - "text": "ApmFields" - }, - "> | undefined) => Promise" + "() => string" ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.index.$1", - "type": "CompoundType", - "tags": [], - "label": "events", - "description": [], - "signature": [ - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.EntityIterable", - "text": "EntityIterable" - }, - " | ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.EntityIterable", - "text": "EntityIterable" - }, - "[]" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.index.$2", - "type": "Object", - "tags": [], - "label": "options", - "description": [], - "signature": [ - "StreamToBulkOptions", - "<", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmFields", - "text": "ApmFields" - }, - "> | undefined" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.index.$3", - "type": "Object", - "tags": [], - "label": "streamProcessor", - "description": [], - "signature": [ - "StreamProcessor", - "<", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmFields", - "text": "ApmFields" - }, - "> | undefined" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], + "children": [], "returnComment": [] }, { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.createDataStream", + "id": "def-common.ApmSynthtraceEsClient.index", "type": "Function", "tags": [], - "label": "createDataStream", + "label": "index", "description": [], "signature": [ - "(aggregator: ", - "StreamAggregator", + "(streamOrGenerator: MaybeArray<", + "Readable", + " | ", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.SynthtraceGenerator", + "text": "SynthtraceGenerator" + }, "<", { - "pluginId": "@kbn/apm-synthtrace", + "pluginId": "@kbn/apm-synthtrace-client", "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", + "docId": "kibKbnApmSynthtraceClientPluginApi", "section": "def-common.ApmFields", "text": "ApmFields" }, - ">) => Promise" + ">>) => Promise" ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmSynthtraceEsClient.createDataStream.$1", - "type": "Object", + "id": "def-common.ApmSynthtraceEsClient.index.$1", + "type": "CompoundType", "tags": [], - "label": "aggregator", + "label": "streamOrGenerator", "description": [], "signature": [ - "StreamAggregator", + "MaybeArray<", + "Readable", + " | ", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.SynthtraceGenerator", + "text": "SynthtraceGenerator" + }, "<", { - "pluginId": "@kbn/apm-synthtrace", + "pluginId": "@kbn/apm-synthtrace-client", "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", + "docId": "kibKbnApmSynthtraceClientPluginApi", "section": "def-common.ApmFields", "text": "ApmFields" }, - ">" + ">>" ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_es_client/index.ts", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -425,36 +331,18 @@ }, { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityArrayIterable", + "id": "def-common.ApmSynthtraceKibanaClient", "type": "Class", "tags": [], - "label": "EntityArrayIterable", + "label": "ApmSynthtraceKibanaClient", "description": [], - "signature": [ - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.EntityArrayIterable", - "text": "EntityArrayIterable" - }, - " implements ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.EntityIterable", - "text": "EntityIterable" - }, - "" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_kibana_client.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityArrayIterable.Unnamed", + "id": "def-common.ApmSynthtraceKibanaClient.Unnamed", "type": "Function", "tags": [], "label": "Constructor", @@ -462,87 +350,62 @@ "signature": [ "any" ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_kibana_client.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityArrayIterable.Unnamed.$1", - "type": "Array", + "id": "def-common.ApmSynthtraceKibanaClient.Unnamed.$1", + "type": "Object", "tags": [], - "label": "fields", + "label": "options", "description": [], - "signature": [ - "TFields[]" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_kibana_client.ts", "deprecated": false, "trackAdoption": false, - "isRequired": true + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace", + "id": "def-common.ApmSynthtraceKibanaClient.Unnamed.$1.logger", + "type": "Object", + "tags": [], + "label": "logger", + "description": [], + "signature": [ + "Logger" + ], + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_kibana_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace", + "id": "def-common.ApmSynthtraceKibanaClient.Unnamed.$1.target", + "type": "string", + "tags": [], + "label": "target", + "description": [], + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_kibana_client.ts", + "deprecated": false, + "trackAdoption": false + } + ] } ], "returnComment": [] }, { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityArrayIterable.order", - "type": "Function", - "tags": [], - "label": "order", - "description": [], - "signature": [ - "() => \"asc\" | \"desc\"" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityArrayIterable.estimatedRatePerMinute", - "type": "Function", - "tags": [], - "label": "estimatedRatePerMinute", - "description": [], - "signature": [ - "() => number" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityArrayIterable.Symbol.asyncIterator", - "type": "Function", - "tags": [], - "label": "[Symbol.asyncIterator]", - "description": [], - "signature": [ - "() => AsyncIterator" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityArrayIterable.Symbol.iterator", + "id": "def-common.ApmSynthtraceKibanaClient.fetchLatestApmPackageVersion", "type": "Function", "tags": [], - "label": "[Symbol.iterator]", + "label": "fetchLatestApmPackageVersion", "description": [], "signature": [ - "() => Iterator" + "() => Promise" ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_kibana_client.ts", "deprecated": false, "trackAdoption": false, "children": [], @@ -550,68 +413,35 @@ }, { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityArrayIterable.merge", + "id": "def-common.ApmSynthtraceKibanaClient.installApmPackage", "type": "Function", "tags": [], - "label": "merge", + "label": "installApmPackage", "description": [], "signature": [ - "(...iterables: ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.EntityIterable", - "text": "EntityIterable" - }, - "[]) => ", - "EntityStreams", - "" + "(packageVersion: string) => Promise" ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_kibana_client.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityArrayIterable.merge.$1", - "type": "Array", + "id": "def-common.ApmSynthtraceKibanaClient.installApmPackage.$1", + "type": "string", "tags": [], - "label": "iterables", + "label": "packageVersion", "description": [], "signature": [ - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.EntityIterable", - "text": "EntityIterable" - }, - "[]" + "string" ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_kibana_client.ts", "deprecated": false, "trackAdoption": false, "isRequired": true } ], "returnComment": [] - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityArrayIterable.toArray", - "type": "Function", - "tags": [], - "label": "toArray", - "description": [], - "signature": [ - "() => TFields[]" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] } ], "initialIsOpen": false @@ -620,107 +450,33 @@ "functions": [ { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.cleanWriteTargets", + "id": "def-common.createLogger", "type": "Function", "tags": [], - "label": "cleanWriteTargets", + "label": "createLogger", "description": [], "signature": [ - "({\n targets,\n client,\n logger,\n}: { targets: string[]; client: ", - "default", - "; logger: { perf: (name: string, cb: () => T) => T; debug: (...args: any[]) => void; info: (...args: any[]) => void; error: (...args: any[]) => void; }; }) => Promise" + "(logLevel: ", + { + "pluginId": "@kbn/apm-synthtrace", + "scope": "common", + "docId": "kibKbnApmSynthtracePluginApi", + "section": "def-common.LogLevel", + "text": "LogLevel" + }, + ") => ", + "Logger" ], - "path": "packages/kbn-apm-synthtrace/src/lib/utils/clean_write_targets.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/utils/create_logger.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.cleanWriteTargets.$1", - "type": "Object", + "id": "def-common.createLogger.$1", + "type": "Enum", "tags": [], - "label": "{\n targets,\n client,\n logger,\n}", - "description": [], - "path": "packages/kbn-apm-synthtrace/src/lib/utils/clean_write_targets.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.cleanWriteTargets.$1.targets", - "type": "Array", - "tags": [], - "label": "targets", - "description": [], - "signature": [ - "string[]" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/utils/clean_write_targets.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.cleanWriteTargets.$1.client", - "type": "Object", - "tags": [], - "label": "client", - "description": [], - "signature": [ - "default" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/utils/clean_write_targets.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.cleanWriteTargets.$1.logger", - "type": "Object", - "tags": [], - "label": "logger", - "description": [], - "signature": [ - "{ perf: (name: string, cb: () => T) => T; debug: (...args: any[]) => void; info: (...args: any[]) => void; error: (...args: any[]) => void; }" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/utils/clean_write_targets.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.createLogger", - "type": "Function", - "tags": [], - "label": "createLogger", - "description": [], - "signature": [ - "(logLevel: ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.LogLevel", - "text": "LogLevel" - }, - ") => { perf: (name: string, cb: () => T) => T; debug: (...args: any[]) => void; info: (...args: any[]) => void; error: (...args: any[]) => void; }" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/utils/create_logger.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.createLogger.$1", - "type": "Enum", - "tags": [], - "label": "logLevel", + "label": "logLevel", "description": [], "signature": [ { @@ -739,774 +495,24 @@ ], "returnComment": [], "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.dedot", - "type": "Function", - "tags": [], - "label": "dedot", - "description": [], - "signature": [ - "(source: Record, target: Record) => Record" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/utils/dedot.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.dedot.$1", - "type": "Object", - "tags": [], - "label": "source", - "description": [], - "signature": [ - "Record" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/utils/dedot.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.dedot.$2", - "type": "Object", - "tags": [], - "label": "target", - "description": [], - "signature": [ - "Record" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/utils/dedot.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.observer", - "type": "Function", - "tags": [], - "label": "observer", - "description": [], - "signature": [ - "() => ", - "Observer" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/agent_config/observer.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.timerange", - "type": "Function", - "tags": [], - "label": "timerange", - "description": [], - "signature": [ - "(from: number | Date, to: number | Date) => ", - "Timerange" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/timerange.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.timerange.$1", - "type": "CompoundType", - "tags": [], - "label": "from", - "description": [], - "signature": [ - "number | Date" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/timerange.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.timerange.$2", - "type": "CompoundType", - "tags": [], - "label": "to", - "description": [], - "signature": [ - "number | Date" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/timerange.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false } ], - "interfaces": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmException", - "type": "Interface", - "tags": [], - "label": "ApmException", - "description": [], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/apm_fields.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmException.message", - "type": "string", - "tags": [], - "label": "message", - "description": [], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/apm_fields.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, + "interfaces": [], + "enums": [ { "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityIterable", - "type": "Interface", + "id": "def-common.LogLevel", + "type": "Enum", "tags": [], - "label": "EntityIterable", + "label": "LogLevel", "description": [], - "signature": [ - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.EntityIterable", - "text": "EntityIterable" - }, - " extends Iterable,AsyncIterable" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityIterable.order", - "type": "Function", - "tags": [], - "label": "order", - "description": [], - "signature": [ - "() => \"asc\" | \"desc\"" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityIterable.estimatedRatePerMinute", - "type": "Function", - "tags": [], - "label": "estimatedRatePerMinute", - "description": [], - "signature": [ - "() => number" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityIterable.toArray", - "type": "Function", - "tags": [], - "label": "toArray", - "description": [], - "signature": [ - "() => ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmFields", - "text": "ApmFields" - }, - "[]" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityIterable.merge", - "type": "Function", - "tags": [], - "label": "merge", - "description": [], - "signature": [ - "(...iterables: ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.EntityIterable", - "text": "EntityIterable" - }, - "[]) => ", - "EntityStreams", - "" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.EntityIterable.merge.$1", - "type": "Array", - "tags": [], - "label": "iterables", - "description": [], - "signature": [ - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.EntityIterable", - "text": "EntityIterable" - }, - "[]" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity_iterable.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.Fields", - "type": "Interface", - "tags": [], - "label": "Fields", - "description": [], - "path": "packages/kbn-apm-synthtrace/src/lib/entity.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.Fields.timestamp", - "type": "number", - "tags": [], - "label": "'@timestamp'", - "description": [], - "signature": [ - "number | undefined" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/entity.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - } - ], - "enums": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.LogLevel", - "type": "Enum", - "tags": [], - "label": "LogLevel", - "description": [], - "path": "packages/kbn-apm-synthtrace/src/lib/utils/create_logger.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - } - ], - "misc": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.ApmFields", - "type": "Type", - "tags": [], - "label": "ApmFields", - "description": [], - "signature": [ - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.Fields", - "text": "Fields" - }, - " & Partial<{ 'timestamp.us'?: number | undefined; 'agent.name': string; 'agent.version': string; 'client.geo.city_name': string; 'client.geo.continent_name': string; 'client.geo.country_iso_code': string; 'client.geo.country_name': string; 'client.geo.region_iso_code': string; 'client.geo.region_name': string; 'client.geo.location': ", - "GeoLocation", - "; 'client.ip': string; 'cloud.provider': string; 'cloud.project.name': string; 'cloud.service.name': string; 'cloud.availability_zone': string; 'cloud.machine.type': string; 'cloud.region': string; 'container.id': string; 'destination.address': string; 'destination.port': number; 'device.id': string; 'device.model.identifier': string; 'device.model.name': string; 'device.manufacturer': string; 'ecs.version': string; 'event.outcome': string; 'event.name': string; 'event.ingested': number; 'error.id': string; 'error.exception': ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmException", - "text": "ApmException" - }, - "[]; 'error.grouping_name': string; 'error.grouping_key': string; 'faas.id': string; 'faas.name': string; 'faas.coldstart': boolean; 'faas.execution': string; 'faas.trigger.type': string; 'faas.trigger.request_id': string; 'host.name': string; 'host.architecture': string; 'host.hostname': string; 'host.os.full': string; 'host.os.name': string; 'host.os.platform': string; 'host.os.type': string; 'host.os.version': string; 'http.request.method': string; 'http.response.status_code': number; 'kubernetes.pod.uid': string; 'kubernetes.pod.name': string; 'metricset.name': string; observer: ", - "Observer", - "; 'network.connection.type': string; 'network.connection.subtype': string; 'network.carrier.name': string; 'network.carrier.mcc': string; 'network.carrier.mnc': string; 'network.carrier.icc': string; 'parent.id': string; 'processor.event': string; 'processor.name': string; 'session.id': string; 'trace.id': string; 'transaction.name': string; 'transaction.type': string; 'transaction.id': string; 'transaction.duration.us': number; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; 'transaction.sampled': true; 'service.name': string; 'service.version': string; 'service.environment': string; 'service.language.name': string; 'service.node.name': string; 'service.runtime.name': string; 'service.runtime.version': string; 'service.framework.name': string; 'service.framework.version': string; 'service.target.name': string; 'service.target.type': string; 'span.action': string; 'span.id': string; 'span.name': string; 'span.type': string; 'span.subtype': string; 'span.duration.us': number; 'span.destination.service.resource': string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; 'span.self_time.count': number; 'span.self_time.sum.us': number; 'span.links': { trace: { id: string; }; span: { id: string; }; }[]; 'url.original': string; }> & Partial<{ 'system.process.memory.size': number; 'system.memory.actual.free': number; 'system.memory.total': number; 'system.cpu.total.norm.pct': number; 'system.process.memory.rss.bytes': number; 'system.process.cpu.total.norm.pct': number; 'jvm.memory.heap.used': number; 'jvm.memory.non_heap.used': number; 'jvm.thread.count': number; 'faas.billed_duration': number; 'faas.timeout': number; 'faas.coldstart_duration': number; 'faas.duration': number; }>" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/apm_fields.ts", + "path": "packages/kbn-apm-synthtrace/src/lib/utils/create_logger.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false } ], - "objects": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm", - "type": "Object", - "tags": [], - "label": "apm", - "description": [], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.service", - "type": "Function", - "tags": [], - "label": "service", - "description": [], - "signature": [ - "{ (name: string, environment: string, agentName: string): ", - "Service", - "; (options: { name: string; environment: string; agentName: string; }): ", - "Service", - "; }" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/index.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.mobileApp", - "type": "Function", - "tags": [], - "label": "mobileApp", - "description": [], - "signature": [ - "{ (name: string, environment: string, agentName: MobileAgentName): ", - "MobileApp", - "; (options: { name: string; environment: string; agentName: MobileAgentName; }): ", - "MobileApp", - "; }" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/index.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.browser", - "type": "Function", - "tags": [], - "label": "browser", - "description": [], - "signature": [ - "({ serviceName, environment, userAgent, }: { serviceName: string; environment: string; userAgent: Partial<{ 'user_agent.original': string; 'user_agent.os.name': string; 'user_agent.name': string; 'user_agent.device.name': string; 'user_agent.version': number; }>; }) => ", - "Browser" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.browser.$1", - "type": "Object", - "tags": [], - "label": "__0", - "description": [], - "signature": [ - "{ serviceName: string; environment: string; userAgent: Partial<{ 'user_agent.original': string; 'user_agent.os.name': string; 'user_agent.name': string; 'user_agent.device.name': string; 'user_agent.version': number; }>; }" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/browser.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.getTransactionMetrics", - "type": "Function", - "tags": [], - "label": "getTransactionMetrics", - "description": [], - "signature": [ - "(events: ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmFields", - "text": "ApmFields" - }, - "[]) => { 'metricset.name': string; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; _doc_count: number; '@timestamp'?: number | undefined; 'timestamp.us'?: number | undefined; 'agent.name'?: string | undefined; 'agent.version'?: string | undefined; 'client.geo.city_name'?: string | undefined; 'client.geo.continent_name'?: string | undefined; 'client.geo.country_iso_code'?: string | undefined; 'client.geo.country_name'?: string | undefined; 'client.geo.region_iso_code'?: string | undefined; 'client.geo.region_name'?: string | undefined; 'client.geo.location'?: ", - "GeoLocation", - " | undefined; 'client.ip'?: string | 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; 'container.id'?: string | undefined; 'destination.address'?: string | undefined; 'destination.port'?: number | undefined; 'device.id'?: string | undefined; 'device.model.identifier'?: string | undefined; 'device.model.name'?: string | undefined; 'device.manufacturer'?: string | undefined; 'ecs.version'?: string | undefined; 'event.outcome'?: string | undefined; 'event.name'?: string | undefined; 'event.ingested'?: number | undefined; 'error.id'?: string | undefined; 'error.exception'?: ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmException", - "text": "ApmException" - }, - "[] | undefined; 'error.grouping_name'?: string | undefined; 'error.grouping_key'?: string | undefined; 'faas.id'?: string | undefined; 'faas.name'?: string | undefined; 'faas.coldstart'?: boolean | undefined; 'faas.execution'?: string | undefined; 'faas.trigger.type'?: string | undefined; 'faas.trigger.request_id'?: string | undefined; 'host.name'?: string | undefined; 'host.architecture'?: string | undefined; 'host.hostname'?: string | undefined; 'host.os.full'?: string | undefined; 'host.os.name'?: string | undefined; 'host.os.platform'?: string | undefined; 'host.os.type'?: string | undefined; 'host.os.version'?: string | undefined; 'http.request.method'?: string | undefined; 'http.response.status_code'?: number | undefined; 'kubernetes.pod.uid'?: string | undefined; 'kubernetes.pod.name'?: string | undefined; observer?: ", - "Observer", - " | undefined; 'network.connection.type'?: string | undefined; 'network.connection.subtype'?: string | undefined; 'network.carrier.name'?: string | undefined; 'network.carrier.mcc'?: string | undefined; 'network.carrier.mnc'?: string | undefined; 'network.carrier.icc'?: string | undefined; 'parent.id'?: string | undefined; 'processor.event'?: string | undefined; 'processor.name'?: string | undefined; 'session.id'?: 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.language.name'?: string | undefined; 'service.node.name'?: string | undefined; 'service.runtime.name'?: string | undefined; 'service.runtime.version'?: string | undefined; 'service.framework.name'?: string | undefined; 'service.framework.version'?: string | undefined; 'service.target.name'?: string | undefined; 'service.target.type'?: string | undefined; 'span.action'?: 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.resource'?: 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; 'span.links'?: { trace: { id: string; }; span: { id: string; }; }[] | undefined; 'url.original'?: 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; 'faas.billed_duration'?: number | undefined; 'faas.timeout'?: number | undefined; 'faas.coldstart_duration'?: number | undefined; 'faas.duration'?: number | undefined; }[]" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.getTransactionMetrics.$1", - "type": "Array", - "tags": [], - "label": "events", - "description": [], - "signature": [ - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmFields", - "text": "ApmFields" - }, - "[]" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/processors/get_transaction_metrics.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.getSpanDestinationMetrics", - "type": "Function", - "tags": [], - "label": "getSpanDestinationMetrics", - "description": [], - "signature": [ - "(events: ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmFields", - "text": "ApmFields" - }, - "[]) => { \"metricset.name\": string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; '@timestamp'?: number | undefined; 'timestamp.us'?: number | undefined; 'agent.name'?: string | undefined; 'agent.version'?: string | undefined; 'client.geo.city_name'?: string | undefined; 'client.geo.continent_name'?: string | undefined; 'client.geo.country_iso_code'?: string | undefined; 'client.geo.country_name'?: string | undefined; 'client.geo.region_iso_code'?: string | undefined; 'client.geo.region_name'?: string | undefined; 'client.geo.location'?: ", - "GeoLocation", - " | undefined; 'client.ip'?: string | 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; 'container.id'?: string | undefined; 'destination.address'?: string | undefined; 'destination.port'?: number | undefined; 'device.id'?: string | undefined; 'device.model.identifier'?: string | undefined; 'device.model.name'?: string | undefined; 'device.manufacturer'?: string | undefined; 'ecs.version'?: string | undefined; 'event.outcome'?: string | undefined; 'event.name'?: string | undefined; 'event.ingested'?: number | undefined; 'error.id'?: string | undefined; 'error.exception'?: ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmException", - "text": "ApmException" - }, - "[] | undefined; 'error.grouping_name'?: string | undefined; 'error.grouping_key'?: string | undefined; 'faas.id'?: string | undefined; 'faas.name'?: string | undefined; 'faas.coldstart'?: boolean | undefined; 'faas.execution'?: string | undefined; 'faas.trigger.type'?: string | undefined; 'faas.trigger.request_id'?: string | undefined; 'host.name'?: string | undefined; 'host.architecture'?: string | undefined; 'host.hostname'?: string | undefined; 'host.os.full'?: string | undefined; 'host.os.name'?: string | undefined; 'host.os.platform'?: string | undefined; 'host.os.type'?: string | undefined; 'host.os.version'?: string | undefined; 'http.request.method'?: string | undefined; 'http.response.status_code'?: number | undefined; 'kubernetes.pod.uid'?: string | undefined; 'kubernetes.pod.name'?: string | undefined; observer?: ", - "Observer", - " | undefined; 'network.connection.type'?: string | undefined; 'network.connection.subtype'?: string | undefined; 'network.carrier.name'?: string | undefined; 'network.carrier.mcc'?: string | undefined; 'network.carrier.mnc'?: string | undefined; 'network.carrier.icc'?: string | undefined; 'parent.id'?: string | undefined; 'processor.event'?: string | undefined; 'processor.name'?: string | undefined; 'session.id'?: 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.language.name'?: string | undefined; 'service.node.name'?: string | undefined; 'service.runtime.name'?: string | undefined; 'service.runtime.version'?: string | undefined; 'service.framework.name'?: string | undefined; 'service.framework.version'?: string | undefined; 'service.target.name'?: string | undefined; 'service.target.type'?: string | undefined; 'span.action'?: 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.resource'?: string | undefined; 'span.self_time.count'?: number | undefined; 'span.self_time.sum.us'?: number | undefined; 'span.links'?: { trace: { id: string; }; span: { id: string; }; }[] | undefined; 'url.original'?: 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; 'faas.billed_duration'?: number | undefined; 'faas.timeout'?: number | undefined; 'faas.coldstart_duration'?: number | undefined; 'faas.duration'?: number | undefined; }[]" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.getSpanDestinationMetrics.$1", - "type": "Array", - "tags": [], - "label": "events", - "description": [], - "signature": [ - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmFields", - "text": "ApmFields" - }, - "[]" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/processors/get_span_destination_metrics.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.getChromeUserAgentDefaults", - "type": "Function", - "tags": [], - "label": "getChromeUserAgentDefaults", - "description": [], - "signature": [ - "() => Partial<{ 'user_agent.original': string; 'user_agent.os.name': string; 'user_agent.name': string; 'user_agent.device.name': string; 'user_agent.version': number; }>" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [] - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.getBreakdownMetrics", - "type": "Function", - "tags": [], - "label": "getBreakdownMetrics", - "description": [], - "signature": [ - "(events: ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmFields", - "text": "ApmFields" - }, - "[]) => ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmFields", - "text": "ApmFields" - }, - "[]" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.getBreakdownMetrics.$1", - "type": "Array", - "tags": [], - "label": "events", - "description": [], - "signature": [ - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmFields", - "text": "ApmFields" - }, - "[]" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/processors/get_breakdown_metrics.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.getApmWriteTargets", - "type": "Function", - "tags": [], - "label": "getApmWriteTargets", - "description": [], - "signature": [ - "({ client, forceLegacyIndices, }: { client: ", - "default", - "; forceLegacyIndices?: boolean | undefined; }) => Promise<", - "ApmElasticsearchOutputWriteTargets", - ">" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.getApmWriteTargets.$1", - "type": "Object", - "tags": [], - "label": "__0", - "description": [], - "signature": [ - "{ client: ", - "default", - "; forceLegacyIndices?: boolean | undefined; }" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/utils/get_apm_write_targets.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.ApmSynthtraceEsClient", - "type": "Object", - "tags": [], - "label": "ApmSynthtraceEsClient", - "description": [], - "signature": [ - "typeof ", - { - "pluginId": "@kbn/apm-synthtrace", - "scope": "common", - "docId": "kibKbnApmSynthtracePluginApi", - "section": "def-common.ApmSynthtraceEsClient", - "text": "ApmSynthtraceEsClient" - } - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/index.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.ApmSynthtraceKibanaClient", - "type": "Object", - "tags": [], - "label": "ApmSynthtraceKibanaClient", - "description": [], - "signature": [ - "typeof ", - "ApmSynthtraceKibanaClient" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/index.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.serverlessFunction", - "type": "Function", - "tags": [], - "label": "serverlessFunction", - "description": [], - "signature": [ - "({ functionName, serviceName, environment, agentName, architecture, }: { functionName: string; environment: string; agentName: string; serviceName?: string | undefined; architecture?: string | undefined; }) => ", - "ServerlessFunction" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.apm.serverlessFunction.$1", - "type": "Object", - "tags": [], - "label": "__0", - "description": [], - "signature": [ - "{ functionName: string; environment: string; agentName: string; serviceName?: string | undefined; architecture?: string | undefined; }" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/apm/serverless_function.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.stackMonitoring", - "type": "Object", - "tags": [], - "label": "stackMonitoring", - "description": [], - "path": "packages/kbn-apm-synthtrace/src/lib/stack_monitoring/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.stackMonitoring.cluster", - "type": "Function", - "tags": [], - "label": "cluster", - "description": [], - "signature": [ - "(name: string) => ", - "Cluster" - ], - "path": "packages/kbn-apm-synthtrace/src/lib/stack_monitoring/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "@kbn/apm-synthtrace", - "id": "def-common.stackMonitoring.cluster.$1", - "type": "string", - "tags": [], - "label": "name", - "description": [], - "path": "packages/kbn-apm-synthtrace/src/lib/stack_monitoring/cluster.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "initialIsOpen": false - } - ] + "misc": [], + "objects": [] } } \ No newline at end of file diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 29ea17352697c..557008a3bc292 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; @@ -21,25 +21,16 @@ Contact [Owner missing] for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 77 | 0 | 77 | 15 | +| 27 | 0 | 27 | 3 | ## Common -### Objects - - ### Functions ### Classes -### Interfaces - - ### Enums -### Consts, variables and types - - diff --git a/api_docs/kbn_apm_synthtrace_client.devdocs.json b/api_docs/kbn_apm_synthtrace_client.devdocs.json new file mode 100644 index 0000000000000..3b9c8f26a7be3 --- /dev/null +++ b/api_docs/kbn_apm_synthtrace_client.devdocs.json @@ -0,0 +1,2542 @@ +{ + "id": "@kbn/apm-synthtrace-client", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace", + "type": "Class", + "tags": [], + "label": "DistributedTrace", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.timestamp", + "type": "number", + "tags": [], + "label": "timestamp", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.serviceInstance", + "type": "Object", + "tags": [], + "label": "serviceInstance", + "description": [], + "signature": [ + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.Instance", + "text": "Instance" + } + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.spanEndTimes", + "type": "Array", + "tags": [], + "label": "spanEndTimes", + "description": [], + "signature": [ + "number[]" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.childSpans", + "type": "Array", + "tags": [], + "label": "childSpans", + "description": [], + "signature": [ + "BaseSpan", + "[]" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.transaction", + "type": "Object", + "tags": [], + "label": "transaction", + "description": [], + "signature": [ + "Transaction" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "{\n serviceInstance,\n transactionName,\n timestamp,\n children,\n }", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.Unnamed.$1.serviceInstance", + "type": "Object", + "tags": [], + "label": "serviceInstance", + "description": [], + "signature": [ + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.Instance", + "text": "Instance" + } + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.Unnamed.$1.transactionName", + "type": "string", + "tags": [], + "label": "transactionName", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.Unnamed.$1.timestamp", + "type": "number", + "tags": [], + "label": "timestamp", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.Unnamed.$1.children", + "type": "Function", + "tags": [], + "label": "children", + "description": [], + "signature": [ + "((dt: ", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.DistributedTrace", + "text": "DistributedTrace" + }, + ") => void) | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.Unnamed.$1.children.$1", + "type": "Object", + "tags": [], + "label": "dt", + "description": [], + "signature": [ + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.DistributedTrace", + "text": "DistributedTrace" + } + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ] + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.getTransaction", + "type": "Function", + "tags": [], + "label": "getTransaction", + "description": [], + "signature": [ + "() => ", + "Transaction" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.service", + "type": "Function", + "tags": [], + "label": "service", + "description": [], + "signature": [ + "({ serviceInstance, transactionName, latency, repeat, timestamp, duration, children, }: { serviceInstance: ", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.Instance", + "text": "Instance" + }, + "; transactionName: string; repeat?: number | undefined; timestamp?: number | undefined; latency?: number | undefined; duration?: number | undefined; children?: ((dt: ", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.DistributedTrace", + "text": "DistributedTrace" + }, + ") => unknown) | undefined; }) => void" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.service.$1", + "type": "Object", + "tags": [], + "label": "{\n serviceInstance,\n transactionName,\n latency = 0,\n repeat = 1,\n timestamp = this.timestamp,\n duration,\n children,\n }", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.service.$1.serviceInstance", + "type": "Object", + "tags": [], + "label": "serviceInstance", + "description": [], + "signature": [ + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.Instance", + "text": "Instance" + } + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.service.$1.transactionName", + "type": "string", + "tags": [], + "label": "transactionName", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.service.$1.repeat", + "type": "number", + "tags": [], + "label": "repeat", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.service.$1.timestamp", + "type": "number", + "tags": [], + "label": "timestamp", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.service.$1.latency", + "type": "number", + "tags": [], + "label": "latency", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.service.$1.duration", + "type": "number", + "tags": [], + "label": "duration", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.service.$1.children", + "type": "Function", + "tags": [], + "label": "children", + "description": [], + "signature": [ + "((dt: ", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.DistributedTrace", + "text": "DistributedTrace" + }, + ") => unknown) | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.service.$1.children.$1", + "type": "Object", + "tags": [], + "label": "dt", + "description": [], + "signature": [ + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.DistributedTrace", + "text": "DistributedTrace" + } + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ] + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.external", + "type": "Function", + "tags": [], + "label": "external", + "description": [], + "signature": [ + "({ name, url, method, statusCode, duration, timestamp, }: { name: string; url: string; method?: ", + "HttpMethod", + " | undefined; statusCode?: number | undefined; duration: number; timestamp?: number | undefined; }) => void" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.external.$1", + "type": "Object", + "tags": [], + "label": "{\n name,\n url,\n method,\n statusCode,\n duration,\n timestamp = this.timestamp,\n }", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.external.$1.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.external.$1.url", + "type": "string", + "tags": [], + "label": "url", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.external.$1.method", + "type": "CompoundType", + "tags": [], + "label": "method", + "description": [], + "signature": [ + "HttpMethod", + " | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.external.$1.statusCode", + "type": "number", + "tags": [], + "label": "statusCode", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.external.$1.duration", + "type": "number", + "tags": [], + "label": "duration", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.external.$1.timestamp", + "type": "number", + "tags": [], + "label": "timestamp", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.db", + "type": "Function", + "tags": [], + "label": "db", + "description": [], + "signature": [ + "({ name, duration, type, statement, timestamp, }: { name: string; duration: number; type: \"elasticsearch\" | \"sqlite\" | \"redis\"; statement?: string | undefined; timestamp?: number | undefined; }) => void" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.db.$1", + "type": "Object", + "tags": [], + "label": "{\n name,\n duration,\n type,\n statement,\n timestamp = this.timestamp,\n }", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.db.$1.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.db.$1.duration", + "type": "number", + "tags": [], + "label": "duration", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.db.$1.type", + "type": "CompoundType", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"elasticsearch\" | \"sqlite\" | \"redis\"" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.db.$1.statement", + "type": "string", + "tags": [], + "label": "statement", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DistributedTrace.db.$1.timestamp", + "type": "number", + "tags": [], + "label": "timestamp", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/dsl/distributed_trace_client.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance", + "type": "Class", + "tags": [], + "label": "Instance", + "description": [], + "signature": [ + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.Instance", + "text": "Instance" + }, + " extends ", + "Entity", + "<", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.ApmFields", + "text": "ApmFields" + }, + ">" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.transaction", + "type": "Function", + "tags": [], + "label": "transaction", + "description": [], + "signature": [ + "(...options: [string] | [string, string] | [{ transactionName: string; transactionType?: string | undefined; }]) => ", + "Transaction" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.transaction.$1", + "type": "CompoundType", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "[string] | [string, string] | [{ transactionName: string; transactionType?: string | undefined; }]" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.span", + "type": "Function", + "tags": [], + "label": "span", + "description": [], + "signature": [ + "(...options: [string, string] | [string, string, string] | [", + "SpanParams", + "]) => ", + "Span" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.span.$1", + "type": "CompoundType", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "[string, string] | [string, string, string] | [", + "SpanParams", + "]" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.error", + "type": "Function", + "tags": [], + "label": "error", + "description": [], + "signature": [ + "({ message, type, groupingName, }: { message: string; type?: string | undefined; groupingName?: string | undefined; }) => ", + "ApmError" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.error.$1", + "type": "Object", + "tags": [], + "label": "{\n message,\n type,\n groupingName,\n }", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.error.$1.message", + "type": "string", + "tags": [], + "label": "message", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.error.$1.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.error.$1.groupingName", + "type": "string", + "tags": [], + "label": "groupingName", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.containerId", + "type": "Function", + "tags": [], + "label": "containerId", + "description": [], + "signature": [ + "(containerId: string) => this" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.containerId.$1", + "type": "string", + "tags": [], + "label": "containerId", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.podId", + "type": "Function", + "tags": [], + "label": "podId", + "description": [], + "signature": [ + "(podId: string) => this" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.podId.$1", + "type": "string", + "tags": [], + "label": "podId", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.appMetrics", + "type": "Function", + "tags": [], + "label": "appMetrics", + "description": [], + "signature": [ + "(metrics: Partial<{ 'system.process.memory.size': number; 'system.memory.actual.free': number; 'system.memory.total': number; 'system.cpu.total.norm.pct': number; 'system.process.memory.rss.bytes': number; 'system.process.cpu.total.norm.pct': number; 'jvm.memory.heap.used': number; 'jvm.memory.non_heap.used': number; 'jvm.thread.count': number; 'faas.billed_duration': number; 'faas.timeout': number; 'faas.coldstart_duration': number; 'faas.duration': number; }>) => ", + "Metricset", + "<", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.ApmFields", + "text": "ApmFields" + }, + ">" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Instance.appMetrics.$1", + "type": "Object", + "tags": [], + "label": "metrics", + "description": [], + "signature": [ + "Partial<{ 'system.process.memory.size': number; 'system.memory.actual.free': number; 'system.memory.total': number; 'system.cpu.total.norm.pct': number; 'system.process.memory.rss.bytes': number; 'system.process.cpu.total.norm.pct': number; 'jvm.memory.heap.used': number; 'jvm.memory.non_heap.used': number; 'jvm.thread.count': number; 'faas.billed_duration': number; 'faas.timeout': number; 'faas.coldstart_duration': number; 'faas.duration': number; }>" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/instance.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice", + "type": "Class", + "tags": [], + "label": "MobileDevice", + "description": [], + "signature": [ + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.MobileDevice", + "text": "MobileDevice" + }, + " extends ", + "Entity", + "<", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.ApmFields", + "text": "ApmFields" + }, + ">" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.networkConnection", + "type": "Object", + "tags": [], + "label": "networkConnection", + "description": [], + "signature": [ + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.NetworkConnectionInfo", + "text": "NetworkConnectionInfo" + } + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.Unnamed.$1", + "type": "CompoundType", + "tags": [], + "label": "fields", + "description": [], + "signature": [ + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.ApmFields", + "text": "ApmFields" + } + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.deviceInfo", + "type": "Function", + "tags": [], + "label": "deviceInfo", + "description": [], + "signature": [ + "(...options: [string, string] | [string, string, string] | [", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.DeviceInfo", + "text": "DeviceInfo" + }, + "]) => this" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.deviceInfo.$1", + "type": "CompoundType", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "[string, string] | [string, string, string] | [", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.DeviceInfo", + "text": "DeviceInfo" + }, + "]" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.osInfo", + "type": "Function", + "tags": [], + "label": "osInfo", + "description": [], + "signature": [ + "(...options: [string, string] | [string, string, string] | [string, string, string, string] | [", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.OSInfo", + "text": "OSInfo" + }, + "]) => this" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.osInfo.$1", + "type": "CompoundType", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "[string, string] | [string, string, string] | [string, string, string, string] | [", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.OSInfo", + "text": "OSInfo" + }, + "]" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.startNewSession", + "type": "Function", + "tags": [], + "label": "startNewSession", + "description": [], + "signature": [ + "() => this" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.setNetworkConnection", + "type": "Function", + "tags": [], + "label": "setNetworkConnection", + "description": [], + "signature": [ + "(networkInfo: ", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.NetworkConnectionInfo", + "text": "NetworkConnectionInfo" + }, + ") => this" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.setNetworkConnection.$1", + "type": "Object", + "tags": [], + "label": "networkInfo", + "description": [], + "signature": [ + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.NetworkConnectionInfo", + "text": "NetworkConnectionInfo" + } + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.setGeoInfo", + "type": "Function", + "tags": [], + "label": "setGeoInfo", + "description": [], + "signature": [ + "(geoInfo: ", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.GeoInfo", + "text": "GeoInfo" + }, + ") => this" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.setGeoInfo.$1", + "type": "Object", + "tags": [], + "label": "geoInfo", + "description": [], + "signature": [ + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.GeoInfo", + "text": "GeoInfo" + } + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.transaction", + "type": "Function", + "tags": [], + "label": "transaction", + "description": [], + "signature": [ + "(...options: [string] | [string, string] | [string, string, string] | [{ transactionName: string; frameworkName?: string | undefined; frameworkVersion?: string | undefined; }]) => ", + "Transaction" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.transaction.$1", + "type": "CompoundType", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "[string] | [string, string] | [string, string, string] | [{ transactionName: string; frameworkName?: string | undefined; frameworkVersion?: string | undefined; }]" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.span", + "type": "Function", + "tags": [], + "label": "span", + "description": [], + "signature": [ + "(...options: [string, string] | [string, string, string] | [", + "SpanParams", + "]) => ", + "Span" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.span.$1", + "type": "CompoundType", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "[string, string] | [string, string, string] | [", + "SpanParams", + "]" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.httpSpan", + "type": "Function", + "tags": [], + "label": "httpSpan", + "description": [], + "signature": [ + "(...options: [string, string, string] | [{ spanName: string; httpMethod: string; httpUrl: string; }]) => ", + "Span" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.MobileDevice.httpSpan.$1", + "type": "CompoundType", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "[string, string, string] | [{ spanName: string; httpMethod: string; httpUrl: string; }]" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Serializable", + "type": "Class", + "tags": [], + "label": "Serializable", + "description": [], + "signature": [ + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.Serializable", + "text": "Serializable" + }, + " extends ", + "Entity", + "" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/serializable.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Serializable.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/serializable.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Serializable.Unnamed.$1", + "type": "Uncategorized", + "tags": [], + "label": "fields", + "description": [], + "signature": [ + "TFields" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/serializable.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Serializable.timestamp", + "type": "Function", + "tags": [], + "label": "timestamp", + "description": [], + "signature": [ + "(time: number) => this" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/serializable.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Serializable.timestamp.$1", + "type": "number", + "tags": [], + "label": "time", + "description": [], + "signature": [ + "number" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/serializable.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Serializable.serialize", + "type": "Function", + "tags": [], + "label": "serialize", + "description": [], + "signature": [ + "() => TFields[]" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/serializable.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Timerange", + "type": "Class", + "tags": [], + "label": "Timerange", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/timerange.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Timerange.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/timerange.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Timerange.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "from", + "description": [], + "signature": [ + "Date" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/timerange.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Timerange.Unnamed.$2", + "type": "Object", + "tags": [], + "label": "to", + "description": [], + "signature": [ + "Date" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/timerange.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Timerange.interval", + "type": "Function", + "tags": [], + "label": "interval", + "description": [], + "signature": [ + "(interval: string) => ", + "Interval", + "<{ '@timestamp'?: number | undefined; }>" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/timerange.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Timerange.interval.$1", + "type": "string", + "tags": [], + "label": "interval", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/timerange.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Timerange.ratePerMinute", + "type": "Function", + "tags": [], + "label": "ratePerMinute", + "description": [], + "signature": [ + "(rate: number) => ", + "Interval", + "<{ '@timestamp'?: number | undefined; }>" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/timerange.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Timerange.ratePerMinute.$1", + "type": "number", + "tags": [], + "label": "rate", + "description": [], + "signature": [ + "number" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/timerange.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.appendHash", + "type": "Function", + "tags": [], + "label": "appendHash", + "description": [], + "signature": [ + "(hash: string, value: string) => string" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/utils/hash.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.appendHash.$1", + "type": "string", + "tags": [], + "label": "hash", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/utils/hash.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.appendHash.$2", + "type": "string", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/utils/hash.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.dedot", + "type": "Function", + "tags": [], + "label": "dedot", + "description": [], + "signature": [ + "(source: Record, target: Record) => Record" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/utils/dedot.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.dedot.$1", + "type": "Object", + "tags": [], + "label": "source", + "description": [], + "signature": [ + "Record" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/utils/dedot.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.dedot.$2", + "type": "Object", + "tags": [], + "label": "target", + "description": [], + "signature": [ + "Record" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/utils/dedot.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.generateLongId", + "type": "Function", + "tags": [], + "label": "generateLongId", + "description": [], + "signature": [ + "(seed: string | undefined) => string" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/utils/generate_id.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.generateLongId.$1", + "type": "string", + "tags": [], + "label": "seed", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/utils/generate_id.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.generateShortId", + "type": "Function", + "tags": [], + "label": "generateShortId", + "description": [], + "signature": [ + "(seed: string | undefined) => string" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/utils/generate_id.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.generateShortId.$1", + "type": "string", + "tags": [], + "label": "seed", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/utils/generate_id.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.hashKeysOf", + "type": "Function", + "tags": [], + "label": "hashKeysOf", + "description": [], + "signature": [ + "(source: T, keys: (keyof T)[]) => string" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/utils/hash.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.hashKeysOf.$1", + "type": "Uncategorized", + "tags": [], + "label": "source", + "description": [], + "signature": [ + "T" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/utils/hash.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.hashKeysOf.$2", + "type": "Array", + "tags": [], + "label": "keys", + "description": [], + "signature": [ + "(keyof T)[]" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/utils/hash.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.httpExitSpan", + "type": "Function", + "tags": [], + "label": "httpExitSpan", + "description": [], + "signature": [ + "({\n spanName,\n destinationUrl,\n method = 'GET',\n statusCode = 200,\n}: { spanName: string; destinationUrl: string; method?: ", + "HttpMethod", + " | undefined; statusCode?: number | undefined; }) => ", + "SpanParams" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/span.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.httpExitSpan.$1", + "type": "Object", + "tags": [], + "label": "{\n spanName,\n destinationUrl,\n method = 'GET',\n statusCode = 200,\n}", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/span.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.httpExitSpan.$1.spanName", + "type": "string", + "tags": [], + "label": "spanName", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/span.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.httpExitSpan.$1.destinationUrl", + "type": "string", + "tags": [], + "label": "destinationUrl", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/span.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.httpExitSpan.$1.method", + "type": "CompoundType", + "tags": [], + "label": "method", + "description": [], + "signature": [ + "HttpMethod", + " | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/span.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.httpExitSpan.$1.statusCode", + "type": "number", + "tags": [], + "label": "statusCode", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/span.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.observer", + "type": "Function", + "tags": [], + "label": "observer", + "description": [], + "signature": [ + "() => ", + "Observer" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/agent_config/observer.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.parseInterval", + "type": "Function", + "tags": [], + "label": "parseInterval", + "description": [], + "signature": [ + "(interval: string) => { intervalAmount: number; intervalUnit: moment.unitOfTime.DurationConstructor; }" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/interval.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.parseInterval.$1", + "type": "string", + "tags": [], + "label": "interval", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/interval.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.timerange", + "type": "Function", + "tags": [], + "label": "timerange", + "description": [], + "signature": [ + "(from: number | Date, to: number | Date) => ", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.Timerange", + "text": "Timerange" + } + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/timerange.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.timerange.$1", + "type": "CompoundType", + "tags": [], + "label": "from", + "description": [], + "signature": [ + "number | Date" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/timerange.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.timerange.$2", + "type": "CompoundType", + "tags": [], + "label": "to", + "description": [], + "signature": [ + "number | Date" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/timerange.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DeviceInfo", + "type": "Interface", + "tags": [], + "label": "DeviceInfo", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DeviceInfo.manufacturer", + "type": "string", + "tags": [], + "label": "manufacturer", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DeviceInfo.modelIdentifier", + "type": "string", + "tags": [], + "label": "modelIdentifier", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.DeviceInfo.modelName", + "type": "string", + "tags": [], + "label": "modelName", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.GeoInfo", + "type": "Interface", + "tags": [], + "label": "GeoInfo", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.GeoInfo.clientIp", + "type": "string", + "tags": [], + "label": "clientIp", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.GeoInfo.cityName", + "type": "string", + "tags": [], + "label": "cityName", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.GeoInfo.continentName", + "type": "string", + "tags": [], + "label": "continentName", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.GeoInfo.countryIsoCode", + "type": "string", + "tags": [], + "label": "countryIsoCode", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.GeoInfo.countryName", + "type": "string", + "tags": [], + "label": "countryName", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.GeoInfo.regionName", + "type": "string", + "tags": [], + "label": "regionName", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.GeoInfo.regionIsoCode", + "type": "string", + "tags": [], + "label": "regionIsoCode", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.GeoInfo.location", + "type": "Object", + "tags": [], + "label": "location", + "description": [], + "signature": [ + "GeoLocation", + " | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.NetworkConnectionInfo", + "type": "Interface", + "tags": [], + "label": "NetworkConnectionInfo", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.NetworkConnectionInfo.type", + "type": "CompoundType", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"unknown\" | \"cell\" | \"unavailable\" | \"wifi\" | \"wired\"" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.NetworkConnectionInfo.subType", + "type": "string", + "tags": [], + "label": "subType", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.NetworkConnectionInfo.carrierName", + "type": "string", + "tags": [], + "label": "carrierName", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.NetworkConnectionInfo.carrierMCC", + "type": "string", + "tags": [], + "label": "carrierMCC", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.NetworkConnectionInfo.carrierMNC", + "type": "string", + "tags": [], + "label": "carrierMNC", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.NetworkConnectionInfo.carrierICC", + "type": "string", + "tags": [], + "label": "carrierICC", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.OSInfo", + "type": "Interface", + "tags": [], + "label": "OSInfo", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.OSInfo.osType", + "type": "CompoundType", + "tags": [], + "label": "osType", + "description": [], + "signature": [ + "\"android\" | \"ios\"" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.OSInfo.osVersion", + "type": "string", + "tags": [], + "label": "osVersion", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.OSInfo.osFull", + "type": "string", + "tags": [], + "label": "osFull", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.OSInfo.runtimeVersion", + "type": "string", + "tags": [], + "label": "runtimeVersion", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/mobile_device.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.AgentConfigFields", + "type": "Type", + "tags": [], + "label": "AgentConfigFields", + "description": [], + "signature": [ + "Pick<", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.ApmFields", + "text": "ApmFields" + }, + ", \"@timestamp\" | \"metricset.name\" | \"ecs.version\" | \"event.ingested\" | \"observer.type\" | \"observer.version\" | \"observer.version_major\" | \"processor.event\" | \"processor.name\"> & Partial<{ 'labels.etag': string; agent_config_applied: number; 'event.agent_id_status': string; }>" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/agent_config/agent_config_fields.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.ApmFields", + "type": "Type", + "tags": [], + "label": "ApmFields", + "description": [], + "signature": [ + "{ '@timestamp'?: number | undefined; } & Partial<{ meta: { 'metricset.id': string; }; }> & Partial<{ 'timestamp.us'?: number | undefined; 'agent.name': string; 'agent.version': string; 'client.geo.city_name': string; 'client.geo.continent_name': string; 'client.geo.country_iso_code': string; 'client.geo.country_name': string; 'client.geo.location': ", + "GeoLocation", + "; 'client.geo.region_iso_code': string; 'client.geo.region_name': string; 'client.ip': string; 'cloud.account.id': string; 'cloud.account.name': string; 'cloud.availability_zone': string; 'cloud.machine.type': string; 'cloud.project.id': string; 'cloud.project.name': string; 'cloud.provider': string; 'cloud.region': string; 'cloud.service.name': string; 'container.id': string; 'destination.address': string; 'destination.port': number; 'device.id': string; 'device.manufacturer': string; 'device.model.identifier': string; 'device.model.name': string; 'ecs.version': string; 'error.exception': ", + "ApmException", + "[]; 'error.grouping_key': string; 'error.grouping_name': string; 'error.id': string; 'event.ingested': number; 'event.name': string; 'event.outcome': string; 'event.outcome_numeric': number | { sum: number; value_count: number; }; 'faas.coldstart': boolean; 'faas.execution': string; 'faas.id': string; 'faas.name': string; 'faas.trigger.type': string; 'faas.version': string; 'host.architecture': string; 'host.hostname': string; 'host.name': string; 'host.os.full': string; 'host.os.name': string; 'host.os.platform': string; 'host.os.type': string; 'host.os.version': string; 'http.request.method': string; 'http.response.status_code': number; 'kubernetes.pod.name': string; 'kubernetes.pod.uid': string; 'metricset.name': string; 'network.carrier.icc': string; 'network.carrier.mcc': string; 'network.carrier.mnc': string; 'network.carrier.name': string; 'network.connection.subtype': string; 'network.connection.type': string; 'observer.type': string; 'observer.version_major': number; 'observer.version': string; 'parent.id': string; 'processor.event': string; 'processor.name': string; 'session.id': string; 'trace.id': string; 'transaction.duration.us': number; 'transaction.id': string; 'transaction.name': string; 'transaction.type': string; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; 'service.environment': string; 'service.framework.name': string; 'service.framework.version': string; 'service.language.name': string; 'service.language.version': string; 'service.name': string; 'service.node.name': string; 'service.runtime.name': string; 'service.runtime.version': string; 'service.target.name': string; 'service.target.type': string; 'service.version': string; 'span.action': string; 'span.destination.service.resource': string; 'span.destination.service.response_time.count': number; 'span.destination.service.response_time.sum.us': number; 'span.duration.us': number; 'span.id': string; 'span.name': string; 'span.self_time.count': number; 'span.self_time.sum.us': number; 'span.subtype': string; 'span.type': string; 'transaction.result': string; 'transaction.sampled': true; 'span.links': { trace: { id: string; }; span: { id: string; }; }[]; 'url.original': string; }> & Partial<{ 'system.process.memory.size': number; 'system.memory.actual.free': number; 'system.memory.total': number; 'system.cpu.total.norm.pct': number; 'system.process.memory.rss.bytes': number; 'system.process.cpu.total.norm.pct': number; 'jvm.memory.heap.used': number; 'jvm.memory.non_heap.used': number; 'jvm.thread.count': number; 'faas.billed_duration': number; 'faas.timeout': number; 'faas.coldstart_duration': number; 'faas.duration': number; }> & Partial<{ 'metricset.interval': string; 'transaction.duration.summary': string; }>" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/apm_fields.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.ESDocumentWithOperation", + "type": "Type", + "tags": [], + "label": "ESDocumentWithOperation", + "description": [], + "signature": [ + "{ _index?: string | undefined; _action?: ", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.SynthtraceESAction", + "text": "SynthtraceESAction" + }, + " | undefined; } & TFields" + ], + "path": "packages/kbn-apm-synthtrace-client/src/types/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.Fields", + "type": "Type", + "tags": [], + "label": "Fields", + "description": [], + "signature": [ + "{ '@timestamp'?: number | undefined; } & (TMeta extends undefined ? {} : Partial<{ meta: TMeta; }>)" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/entity.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.SynthtraceESAction", + "type": "Type", + "tags": [], + "label": "SynthtraceESAction", + "description": [], + "signature": [ + "{ create: ", + "BulkCreateOperation", + "; } | { index: ", + "BulkIndexOperation", + "; }" + ], + "path": "packages/kbn-apm-synthtrace-client/src/types/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.SynthtraceGenerator", + "type": "Type", + "tags": [], + "label": "SynthtraceGenerator", + "description": [], + "signature": [ + "Generator<", + { + "pluginId": "@kbn/apm-synthtrace-client", + "scope": "common", + "docId": "kibKbnApmSynthtraceClientPluginApi", + "section": "def-common.Serializable", + "text": "Serializable" + }, + ", any, unknown>" + ], + "path": "packages/kbn-apm-synthtrace-client/src/types/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.apm", + "type": "Object", + "tags": [], + "label": "apm", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.apm.service", + "type": "Function", + "tags": [], + "label": "service", + "description": [], + "signature": [ + "{ (name: string, environment: string, agentName: string): ", + "Service", + "; (options: { name: string; environment: string; agentName: string; }): ", + "Service", + "; }" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.apm.mobileApp", + "type": "Function", + "tags": [], + "label": "mobileApp", + "description": [], + "signature": [ + "{ (name: string, environment: string, agentName: MobileAgentName): ", + "MobileApp", + "; (options: { name: string; environment: string; agentName: MobileAgentName; }): ", + "MobileApp", + "; }" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.apm.browser", + "type": "Function", + "tags": [], + "label": "browser", + "description": [], + "signature": [ + "({ serviceName, environment, userAgent, }: { serviceName: string; environment: string; userAgent: Partial<{ 'user_agent.original': string; 'user_agent.os.name': string; 'user_agent.name': string; 'user_agent.device.name': string; 'user_agent.version': number; }>; }) => ", + "Browser" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.apm.browser.$1", + "type": "Object", + "tags": [], + "label": "__0", + "description": [], + "signature": [ + "{ serviceName: string; environment: string; userAgent: Partial<{ 'user_agent.original': string; 'user_agent.os.name': string; 'user_agent.name': string; 'user_agent.device.name': string; 'user_agent.version': number; }>; }" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/browser.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.apm.getChromeUserAgentDefaults", + "type": "Function", + "tags": [], + "label": "getChromeUserAgentDefaults", + "description": [], + "signature": [ + "() => Partial<{ 'user_agent.original': string; 'user_agent.os.name': string; 'user_agent.name': string; 'user_agent.device.name': string; 'user_agent.version': number; }>" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.apm.serverlessFunction", + "type": "Function", + "tags": [], + "label": "serverlessFunction", + "description": [], + "signature": [ + "({ functionName, serviceName, environment, agentName, architecture, }: { functionName: string; environment: string; agentName: string; serviceName?: string | undefined; architecture?: string | undefined; }) => ", + "ServerlessFunction" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.apm.serverlessFunction.$1", + "type": "Object", + "tags": [], + "label": "__0", + "description": [], + "signature": [ + "{ functionName: string; environment: string; agentName: string; serviceName?: string | undefined; architecture?: string | undefined; }" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/apm/serverless_function.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "initialIsOpen": false + } + ] + } +} \ No newline at end of file diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx new file mode 100644 index 0000000000000..294123f44cf4e --- /dev/null +++ b/api_docs/kbn_apm_synthtrace_client.mdx @@ -0,0 +1,42 @@ +--- +#### +#### 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. +#### +id: kibKbnApmSynthtraceClientPluginApi +slug: /kibana-dev-docs/api/kbn-apm-synthtrace-client +title: "@kbn/apm-synthtrace-client" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/apm-synthtrace-client plugin +date: 2023-01-09 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace-client'] +--- +import kbnApmSynthtraceClientObj from './kbn_apm_synthtrace_client.devdocs.json'; + +Elastic APM trace data generator + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 152 | 0 | 152 | 16 | + +## Common + +### Objects + + +### Functions + + +### Classes + + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 069edd882052f..dfee7d81e7a4b 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index d14507a20a9dd..b94af0b0cd2a2 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index b1b67d3df5a18..0959716abc102 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index b12dcb04ef575..14b2c20683f87 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index d2de7f685f450..e7cdf7a9d2ae0 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index e214b81319794..d644913d7397e 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index 96a5f435e921d..b68a74f4541f5 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index 7ff5e107ca1fa..6412436fbd71f 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 775e2431130be..2d85899bd6932 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index c2eaff096f0a4..0649c3d10f983 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index a202335ccf32e..3be8481e20f34 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 660d70de32009..2476ff0ad31a9 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index d5e32b8c2cf34..51eada1261279 100644 --- a/api_docs/kbn_content_management_content_editor.mdx +++ b/api_docs/kbn_content_management_content_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-editor title: "@kbn/content-management-content-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-editor plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-editor'] --- import kbnContentManagementContentEditorObj from './kbn_content_management_content_editor.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list.mdx b/api_docs/kbn_content_management_table_list.mdx index 3982d6db2430f..ff76ee4ec4b0b 100644 --- a/api_docs/kbn_content_management_table_list.mdx +++ b/api_docs/kbn_content_management_table_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list title: "@kbn/content-management-table-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list'] --- import kbnContentManagementTableListObj from './kbn_content_management_table_list.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 395bcd721f56d..196ce19af1289 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index 338c495988ebe..6053092c118ac 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index fb0c3184969b3..afe663d47e550 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index a9f58451012b6..ff381508579ab 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index 401c78d7df4ff..b568a6e5c45d1 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index 00296d5ae3948..a1bf555c0b494 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 6260b7eef15d4..72b86e7ddda21 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index 4b282e54db22f..171671c34c8fd 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index 714739319696a..d5bca32ce3699 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index 14aba8aa5a189..f13953c207ba8 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_internal.mdx b/api_docs/kbn_core_apps_browser_internal.mdx index e39e656283881..980f255541d4a 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-internal'] --- import kbnCoreAppsBrowserInternalObj from './kbn_core_apps_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_mocks.mdx b/api_docs/kbn_core_apps_browser_mocks.mdx index 0baaf555d72e0..8e09ad45ebd40 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-mocks'] --- import kbnCoreAppsBrowserMocksObj from './kbn_core_apps_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index a36fb37dfe79b..d038fde8e9ff2 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 4bc0becba95d3..77f59211f3b5f 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index 0588d75d323d7..4ec5bd6584162 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index 64ad012bdd92b..4740495bcd1cc 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index 789f958e88c56..11f45f1805f90 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index 1825c03c51710..c6811c3437df4 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index c07c97dae064d..25b7884be85bb 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index 6a72bafb61c47..1b95f924077ee 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index 66659b4a37af7..3ea1b2387b554 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index 403973d3189ad..e7a0aaf59da41 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index b4dce1907f80b..6487bfff0d154 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index b645f4845cb82..818c42cdab654 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index 4eb086bb99788..1f25924c4e84d 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index cbb680ab7847b..9761482626b63 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index a246c14259322..705e8bec588f6 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index ea5155784208f..80b05500a11ab 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index e86a3704aaa08..10c609f98e5fe 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index 91260eecf6cc7..54a452b8487a4 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index e9dd33e35f495..5e0bb3568ba33 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index 3b825266da93e..312aa38986877 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index 8b61a3e7d4c18..64a364a50e6ce 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index 58f976c0783ac..38f8ee6a4f9a5 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index 47a3d9ef828d0..18a09e85cfb7d 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index 25a9e64fa7ebd..5f295b6c5abaf 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index 1148a02106e53..516c42677865f 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index cf6dc6d16ecb6..f07f531833905 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 54c6608c359d8..92c3a207e70d4 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index 55de80c6329a1..8ca089a7d0808 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index 87d1907e5ce6a..c7e003199805f 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index c4d997139c4f1..7db9c5119831f 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index 14d8408bcfbeb..87ed31a60b6a9 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index db1cd5ae412ac..edad7bf50e1b6 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index c09a448295ee3..0ba0ff24360cd 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index f22ff43941de2..ab904c27f058f 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index 62d0b3447a3ca..347f42295d72b 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index d37b355f64f2c..1e58325459678 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index f5b39e6d8886c..a817a8c416443 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index 2913423211a58..400c640a70e77 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index 0dd2733135afb..42fdd50209ea7 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index c27a6752b1d3d..2c7b3006e9e5d 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index e503cfda242cf..a0d0e4b9a2b76 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index c33fbd3a2ca07..2894db64af010 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index b39bb90694e05..aa2fe8e617d7a 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index e171bb1ad18da..854c9e1d64796 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_request_handler_context_server.mdx b/api_docs/kbn_core_http_request_handler_context_server.mdx index da5abca7ba525..e91d0d56adb04 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-request-handler-context-server'] --- import kbnCoreHttpRequestHandlerContextServerObj from './kbn_core_http_request_handler_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server.mdx b/api_docs/kbn_core_http_resources_server.mdx index 59608e1a05b66..fa4f5797d3864 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server'] --- import kbnCoreHttpResourcesServerObj from './kbn_core_http_resources_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_internal.mdx b/api_docs/kbn_core_http_resources_server_internal.mdx index 08ad8524f6385..a20fac2430dab 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-internal'] --- import kbnCoreHttpResourcesServerInternalObj from './kbn_core_http_resources_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_mocks.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index d19f6878aa935..a1a7fc6040a27 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-mocks'] --- import kbnCoreHttpResourcesServerMocksObj from './kbn_core_http_resources_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index ff753108b4d65..906ed5e220bf4 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index 2a2a5b9927a35..28db91382e9c8 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index 5893ae4f871cd..42c70112b4514 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index 82c379523e032..7638a730a54fc 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index 3470a2efcf369..40ba8afe3f97e 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index 391802fb27859..0b6b032a1fcf1 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index eaf72f487b34d..ce5eca51ba669 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index f4043eafb67c6..a8aeacd9ed55d 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index aca10cccaaa10..231dbfb4927ba 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index cbccdc84c6d46..c091c69cb6237 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 7acadaaf0eec4..c3a81829387c7 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index ae58be1aa6ae8..26fa7d5c3e273 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index d07bb18de417f..a8bbe917c73e1 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index 6ab1dc7f527e8..90acd88066d12 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser'] --- import kbnCoreLifecycleBrowserObj from './kbn_core_lifecycle_browser.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser_mocks.mdx b/api_docs/kbn_core_lifecycle_browser_mocks.mdx index 923aa3bf56abe..b9de178600597 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser-mocks'] --- import kbnCoreLifecycleBrowserMocksObj from './kbn_core_lifecycle_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server.mdx b/api_docs/kbn_core_lifecycle_server.mdx index 196f122dd09a8..5d71436b1643d 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server'] --- import kbnCoreLifecycleServerObj from './kbn_core_lifecycle_server.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server_mocks.mdx b/api_docs/kbn_core_lifecycle_server_mocks.mdx index f766ddb0a4ea8..d6bf4eb7a2651 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server-mocks'] --- import kbnCoreLifecycleServerMocksObj from './kbn_core_lifecycle_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_browser_mocks.mdx b/api_docs/kbn_core_logging_browser_mocks.mdx index 02a00e4dc4088..c28fb6375c809 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-browser-mocks'] --- import kbnCoreLoggingBrowserMocksObj from './kbn_core_logging_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_common_internal.mdx b/api_docs/kbn_core_logging_common_internal.mdx index 4a06ede86ccea..5c26ad0ba0fe1 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-common-internal'] --- import kbnCoreLoggingCommonInternalObj from './kbn_core_logging_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 2e6b26874d1c5..30e2bb6e47d7c 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index fb4e799c364f9..c5c6944d7138a 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index 88e5de39aa9c1..e7ff3f94e3656 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index 57248a0706a2f..7ef3749c22b52 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index 609dcebb15f68..c1afec3aabe33 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index ce4f808deaf53..758d46f5b3d1f 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index f61875ef8f8d5..46093aedc1447 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index d2c0aa0a899c1..be9d4ced2294e 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index a79ce67826626..16bcbb1e62355 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index 5f8d836d7f154..6f5c9feec6555 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 93209b14ea112..67e23e9d1bea2 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index a48fafc9b3478..3e3b6e4f48e70 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index aeca4844800e4..b1b5900072209 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index 2d0f3e6c39228..fa75f36472d17 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index 9bccbd44fbb7a..f523aa00af576 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index ad796e0a9e30f..92046f0acfcac 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index 80fd4bba10f98..ef132dc04ed0c 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index 889772c87fda6..4570aca17ff66 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser.mdx b/api_docs/kbn_core_plugins_browser.mdx index a49443ff504ee..cfeda2fd48f86 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser'] --- import kbnCorePluginsBrowserObj from './kbn_core_plugins_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index 2f51ac972ed18..980a71cb16a0a 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index b7bddffd86a3d..77721d5f611c8 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index 194594f9f2b44..bbcefb1774f32 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server-mocks'] --- import kbnCorePluginsServerMocksObj from './kbn_core_plugins_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index 76e9b8ffc0878..27dc75742b4d5 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index 65e11c1713771..ddf312d544bb6 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index eff8f640e3da8..3eee05562e6d9 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_internal.mdx b/api_docs/kbn_core_rendering_server_internal.mdx index 9348789dff285..cc6de53fa4c43 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-internal'] --- import kbnCoreRenderingServerInternalObj from './kbn_core_rendering_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_mocks.mdx b/api_docs/kbn_core_rendering_server_mocks.mdx index fafcf1864b10f..02af08d587553 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-mocks'] --- import kbnCoreRenderingServerMocksObj from './kbn_core_rendering_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_root_server_internal.mdx b/api_docs/kbn_core_root_server_internal.mdx index ca5bf3c06036e..e15071779819a 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index 69c1465ed65d3..45908a2a5cd52 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index 8b56326ecbb26..b9d79a0cc03d2 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_internal.mdx b/api_docs/kbn_core_saved_objects_api_server_internal.mdx index e93e15a243d70..799739bdaa5b3 100644 --- a/api_docs/kbn_core_saved_objects_api_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-internal title: "@kbn/core-saved-objects-api-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-internal'] --- import kbnCoreSavedObjectsApiServerInternalObj from './kbn_core_saved_objects_api_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index 7485655314908..5f946d51ea067 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index 1733508009863..fae8ef0a06b03 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index 02467a63a58ad..850804c8bd34f 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index 005c55a15284e..b34b4aab14fa0 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index b447ad774b642..44aeda68cc10f 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index 6630e5e6801b0..0f01956013c5c 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index 9e034416804b1..68434e5fe864c 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index 1246eec3a955d..16d9e296bd4c5 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index ba32b1206bb5b..4e86e961ad03c 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index e44edee58c08f..14462bb52fcfd 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index 2f42ebc19c767..41d09a0058e3f 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index 6fc1288733410..0777dd9ce30b2 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index 3035b90316d9f..75bc036df15e5 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index be5d0e5e89169..b5cb2371044ca 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index 102fb5a8eee8e..91c13ff169ffb 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index cacf71ed5e01c..2b614fff924fa 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] --- import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx index 92999ebe4a029..160917fc887f9 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] --- import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx index b5e1b634bc38f..66cba917f22f7 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server'] --- import kbnCoreStatusServerObj from './kbn_core_status_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx index d2a34fc88ff51..14374dcee2f37 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-internal'] --- import kbnCoreStatusServerInternalObj from './kbn_core_status_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_mocks.mdx b/api_docs/kbn_core_status_server_mocks.mdx index 28b2a00f7f47d..fac3db91bb75c 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-mocks'] --- import kbnCoreStatusServerMocksObj from './kbn_core_status_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index aa6f3b6fe580a..89ae7491137f1 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index 5e6cfb7e595c3..c0888a66f91e7 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index f160f6c5c9dad..6e22adab5c50d 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index f9cce6ce311f0..87b1c523e2847 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-so-type-serializer'] --- import kbnCoreTestHelpersSoTypeSerializerObj from './kbn_core_test_helpers_so_type_serializer.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_test_utils.mdx b/api_docs/kbn_core_test_helpers_test_utils.mdx index 28d4e669824c2..198a944b40e47 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-test-utils'] --- import kbnCoreTestHelpersTestUtilsObj from './kbn_core_test_helpers_test_utils.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index f0f93cd7096ef..212c813bc6f37 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index 9186945e41854..55125394b9738 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] --- import kbnCoreThemeBrowserInternalObj from './kbn_core_theme_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index 1e58c7d8a3050..de7aaf64b4a4f 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index f55485ef03f54..fcb053d746dd1 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index 127dcc2aa79a7..b56b9d84f1dde 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index 4526feeb0ba0a..e311693b3b373 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index 311bda6447458..7cdbbe2dd48b9 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server.mdx b/api_docs/kbn_core_ui_settings_server.mdx index 2c5601d67dd21..4b23796518392 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server'] --- import kbnCoreUiSettingsServerObj from './kbn_core_ui_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index 9a3ada7256eb6..bedbe16385dfa 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-internal'] --- import kbnCoreUiSettingsServerInternalObj from './kbn_core_ui_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_mocks.mdx b/api_docs/kbn_core_ui_settings_server_mocks.mdx index cc210fca79381..4a9638340ef11 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index af5dd8a8e0e6e..88ede01554301 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index 5384148197c51..a02883080ea07 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index 9c2dbc6636bad..de0435f938413 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 53a38c2ec3c31..8c572ac2421c6 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index cec9498d9efa5..c04a4ee9593b5 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index 409245bb85726..7fbe0a02078b9 100644 --- a/api_docs/kbn_cypress_config.mdx +++ b/api_docs/kbn_cypress_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cypress-config title: "@kbn/cypress-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cypress-config plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index ea4db8d10e017..9d5ee84b83b04 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index fe69f0b21fb74..118171f9247ea 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index 17c5076a81202..d993d360fe18d 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index 58dfcc17f27b2..0822ef9fb732a 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index f5a8407bf7395..76c826e4e8d36 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index d4b07c58e4a9b..8197168c8d022 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index a50b64ddba0ef..152b75eb742a1 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index 2d904ef288625..2bd4faff9ae79 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs.mdx b/api_docs/kbn_ecs.mdx index 1a61fe1155a86..f00eb0250b117 100644 --- a/api_docs/kbn_ecs.mdx +++ b/api_docs/kbn_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs title: "@kbn/ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs'] --- import kbnEcsObj from './kbn_ecs.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index 8bcf07fc5ae1c..236a2e21121aa 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 302588206616a..c93134b665869 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index 92fd053ffdeac..8770929d71aab 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index b9a6472f879e7..671f9f4548bb5 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index 1b6e9b1111b24..8dfbefeaf61a5 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-types'] --- import kbnEsTypesObj from './kbn_es_types.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 524f914bc234b..1c06fba39566f 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 790940d7204fb..cd0b2ab15b0ec 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index 1e9b1e9267b85..e64dfe676e9f7 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index a9c35a0d5e8aa..0ce79145b484d 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index bc971bf4adbd4..9e956b1e8c27f 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_get_repo_files.mdx b/api_docs/kbn_get_repo_files.mdx index 98892a7519efb..f0a79ec00c6de 100644 --- a/api_docs/kbn_get_repo_files.mdx +++ b/api_docs/kbn_get_repo_files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-get-repo-files title: "@kbn/get-repo-files" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/get-repo-files plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/get-repo-files'] --- import kbnGetRepoFilesObj from './kbn_get_repo_files.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index b915e44f0d176..b766b20be67ef 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index 594aea5915758..b48f074e30bf1 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index 09f6f5a54d27e..9e4eebb3b3182 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_health_gateway_server.mdx b/api_docs/kbn_health_gateway_server.mdx index 6371c9b60c53b..bd81015febc97 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/health-gateway-server'] --- import kbnHealthGatewayServerObj from './kbn_health_gateway_server.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index 999c978476a54..63ef68aae2f4b 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index 30e82cb2ed41e..3b46befb6aeb4 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index a8ef1b3622cc6..90934b8ccc0fc 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_i18n_react.mdx b/api_docs/kbn_i18n_react.mdx index 5a5da7b54f856..83284e1e5bf8c 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n-react'] --- import kbnI18nReactObj from './kbn_i18n_react.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index 8b209b7d6dc61..299c15f5e0860 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 2c23d5196ec76..c427848c0d916 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 3218c48df9f42..93fc8e4dfde80 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index c46be2a534aff..e4486c2cd0d40 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_journeys.mdx b/api_docs/kbn_journeys.mdx index de0951f267835..57fa48fd79086 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index a1fe16d664859..d79b1dff4d2bd 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_language_documentation_popover.mdx b/api_docs/kbn_language_documentation_popover.mdx index 74efda40f1c34..bf74f23cc2842 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 09034e374b6ed..035f853f2e23b 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index a6d2b35b5dd49..c13871a3a40f5 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 72ea4a2d4a4fb..624775f5ccb5e 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index a0b37686426b6..0b96577b6a352 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index ef16708460e8c..72bf2ec1eb362 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_is_defined.devdocs.json b/api_docs/kbn_ml_is_defined.devdocs.json new file mode 100644 index 0000000000000..29ddeefb700e4 --- /dev/null +++ b/api_docs/kbn_ml_is_defined.devdocs.json @@ -0,0 +1,65 @@ +{ + "id": "@kbn/ml-is-defined", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/ml-is-defined", + "id": "def-common.isDefined", + "type": "Function", + "tags": [], + "label": "isDefined", + "description": [ + "\nChecks whether the supplied argument is not `undefined` and not `null`.\n" + ], + "signature": [ + "(argument: T | null | undefined) => boolean" + ], + "path": "x-pack/packages/ml/is_defined/src/is_defined.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ml-is-defined", + "id": "def-common.isDefined.$1", + "type": "CompoundType", + "tags": [], + "label": "argument", + "description": [], + "signature": [ + "T | null | undefined" + ], + "path": "x-pack/packages/ml/is_defined/src/is_defined.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [ + "boolean" + ], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_ml_is_defined.mdx b/api_docs/kbn_ml_is_defined.mdx new file mode 100644 index 0000000000000..e339a4012610f --- /dev/null +++ b/api_docs/kbn_ml_is_defined.mdx @@ -0,0 +1,30 @@ +--- +#### +#### 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. +#### +id: kibKbnMlIsDefinedPluginApi +slug: /kibana-dev-docs/api/kbn-ml-is-defined +title: "@kbn/ml-is-defined" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/ml-is-defined plugin +date: 2023-01-09 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-defined'] +--- +import kbnMlIsDefinedObj from './kbn_ml_is_defined.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 2 | 0 | 1 | 0 | + +## Common + +### Functions + + diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index 7a931a2343f1a..afa6abb0587ff 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_local_storage.devdocs.json b/api_docs/kbn_ml_local_storage.devdocs.json new file mode 100644 index 0000000000000..6b0abed5166d2 --- /dev/null +++ b/api_docs/kbn_ml_local_storage.devdocs.json @@ -0,0 +1,113 @@ +{ + "id": "@kbn/ml-local-storage", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/ml-local-storage", + "id": "def-common.StorageContextProvider", + "type": "Function", + "tags": [], + "label": "StorageContextProvider", + "description": [ + "\nProvider to manage context for the `useStorage` hook." + ], + "signature": [ + "({\n children,\n storage,\n storageKeys,\n}: React.PropsWithChildren>) => JSX.Element" + ], + "path": "x-pack/packages/ml/local_storage/src/storage_context.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ml-local-storage", + "id": "def-common.StorageContextProvider.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n children,\n storage,\n storageKeys,\n}", + "description": [], + "signature": [ + "React.PropsWithChildren>" + ], + "path": "x-pack/packages/ml/local_storage/src/storage_context.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ml-local-storage", + "id": "def-common.useStorage", + "type": "Function", + "tags": [], + "label": "useStorage", + "description": [ + "\nHook for consuming a storage value" + ], + "signature": [ + "(key: K, initValue: T | undefined) => [T | undefined extends undefined ? T | undefined : Exclude, (value: T) => void]" + ], + "path": "x-pack/packages/ml/local_storage/src/storage_context.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ml-local-storage", + "id": "def-common.useStorage.$1", + "type": "Uncategorized", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "K" + ], + "path": "x-pack/packages/ml/local_storage/src/storage_context.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ml-local-storage", + "id": "def-common.useStorage.$2", + "type": "Uncategorized", + "tags": [], + "label": "initValue", + "description": [], + "signature": [ + "T | undefined" + ], + "path": "x-pack/packages/ml/local_storage/src/storage_context.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_ml_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx new file mode 100644 index 0000000000000..663370f26dcbe --- /dev/null +++ b/api_docs/kbn_ml_local_storage.mdx @@ -0,0 +1,30 @@ +--- +#### +#### 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. +#### +id: kibKbnMlLocalStoragePluginApi +slug: /kibana-dev-docs/api/kbn-ml-local-storage +title: "@kbn/ml-local-storage" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/ml-local-storage plugin +date: 2023-01-09 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-local-storage'] +--- +import kbnMlLocalStorageObj from './kbn_ml_local_storage.devdocs.json'; + +Utilities to combine url state management with local storage. + +Contact Machine Learning UI for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 5 | 0 | 3 | 0 | + +## Common + +### Functions + + diff --git a/api_docs/kbn_ml_nested_property.mdx b/api_docs/kbn_ml_nested_property.mdx index 5061cb253875e..b13b6c2522dbf 100644 --- a/api_docs/kbn_ml_nested_property.mdx +++ b/api_docs/kbn_ml_nested_property.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-nested-property title: "@kbn/ml-nested-property" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-nested-property plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-nested-property'] --- import kbnMlNestedPropertyObj from './kbn_ml_nested_property.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index 33d139d1e8211..b834aa8513279 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index adda612e26b71..f5b49b8e89e9a 100644 --- a/api_docs/kbn_ml_url_state.mdx +++ b/api_docs/kbn_ml_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-url-state title: "@kbn/ml-url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-url-state plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 18ef9b30d567b..292eae7955475 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 4449151d9fd32..3e3f446765d75 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index 4f75f1648c0da..1467c090460ec 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_osquery_io_ts_types.devdocs.json b/api_docs/kbn_osquery_io_ts_types.devdocs.json index 0ce61875f6d2f..65501b5031659 100644 --- a/api_docs/kbn_osquery_io_ts_types.devdocs.json +++ b/api_docs/kbn_osquery_io_ts_types.devdocs.json @@ -60,7 +60,7 @@ "label": "ArrayQueries", "description": [], "signature": [ - "{ id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; }[]" + "{ id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; removed: boolean | undefined; snapshot: boolean | undefined; }[]" ], "path": "packages/kbn-osquery-io-ts-types/src/live_query/index.ts", "deprecated": false, @@ -225,7 +225,7 @@ "label": "ObjectQueries", "description": [], "signature": [ - "{ [x: string]: { query: string; id: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; saved_query_id: string | undefined; }; }" + "{ [x: string]: { query: string; id: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; saved_query_id: string | undefined; removed: boolean | undefined; snapshot: boolean | undefined; }; }" ], "path": "packages/kbn-osquery-io-ts-types/src/live_query/index.ts", "deprecated": false, @@ -300,7 +300,7 @@ "label": "Queries", "description": [], "signature": [ - "{ id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; }[] | { [x: string]: { query: string; id: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; saved_query_id: string | undefined; }; }" + "{ id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; removed: boolean | undefined; snapshot: boolean | undefined; }[] | { [x: string]: { query: string; id: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; saved_query_id: string | undefined; removed: boolean | undefined; snapshot: boolean | undefined; }; }" ], "path": "packages/kbn-osquery-io-ts-types/src/live_query/index.ts", "deprecated": false, @@ -315,7 +315,7 @@ "label": "QueriesOrUndefined", "description": [], "signature": [ - "{ id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; }[] | { [x: string]: { query: string; id: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; saved_query_id: string | undefined; }; } | undefined" + "{ id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; removed: boolean | undefined; snapshot: boolean | undefined; }[] | undefined" ], "path": "packages/kbn-osquery-io-ts-types/src/live_query/index.ts", "deprecated": false, @@ -600,6 +600,18 @@ "StringC", ", ", "UndefinedC", + "]>; removed: ", + "UnionC", + "<[", + "BooleanC", + ", ", + "UndefinedC", + "]>; snapshot: ", + "UnionC", + "<[", + "BooleanC", + ", ", + "UndefinedC", "]>; }>>" ], "path": "packages/kbn-osquery-io-ts-types/src/live_query/index.ts", @@ -891,6 +903,18 @@ "StringC", ", ", "UndefinedC", + "]>; removed: ", + "UnionC", + "<[", + "BooleanC", + ", ", + "UndefinedC", + "]>; snapshot: ", + "UnionC", + "<[", + "BooleanC", + ", ", + "UndefinedC", "]>; }>>" ], "path": "packages/kbn-osquery-io-ts-types/src/live_query/index.ts", @@ -1017,6 +1041,18 @@ "StringC", ", ", "UndefinedC", + "]>; removed: ", + "UnionC", + "<[", + "BooleanC", + ", ", + "UndefinedC", + "]>; snapshot: ", + "UnionC", + "<[", + "BooleanC", + ", ", + "UndefinedC", "]>; }>>, ", "RecordC", "<", @@ -1065,6 +1101,18 @@ "StringC", ", ", "UndefinedC", + "]>; removed: ", + "UnionC", + "<[", + "BooleanC", + ", ", + "UndefinedC", + "]>; snapshot: ", + "UnionC", + "<[", + "BooleanC", + ", ", + "UndefinedC", "]>; }>>]>" ], "path": "packages/kbn-osquery-io-ts-types/src/live_query/index.ts", @@ -1080,8 +1128,6 @@ "label": "queriesOrUndefined", "description": [], "signature": [ - "UnionC", - "<[", "UnionC", "<[", "ArrayC", @@ -1123,55 +1169,19 @@ "StringC", ", ", "UndefinedC", - "]>; }>>, ", - "RecordC", - "<", - "StringC", - ", ", - "TypeC", - "<{ query: ", - "StringC", - "; id: ", - "StringC", - "; ecs_mapping: ", - "UnionC", - "<[", - "RecordC", - "<", - "StringC", - ", ", - "PartialC", - "<{ field: ", - "StringC", - "; value: ", - "UnionC", - "<[", - "StringC", - ", ", - "ArrayC", - "<", - "StringC", - ">]>; }>>, ", - "UndefinedC", - "]>; version: ", + "]>; removed: ", "UnionC", "<[", - "StringC", - ", ", - "UndefinedC", - "]>; platform: ", - "UnionC", - "<[", - "StringC", + "BooleanC", ", ", "UndefinedC", - "]>; saved_query_id: ", + "]>; snapshot: ", "UnionC", "<[", - "StringC", + "BooleanC", ", ", "UndefinedC", - "]>; }>>]>, ", + "]>; }>>, ", "UndefinedC", "]>" ], diff --git a/api_docs/kbn_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index 5b3e79226885c..d208989b34f5d 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 42d246ad9a4ca..58e797da9c556 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 943501e2e85b4..fbd5cdf0196a2 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index 16f88f5f88dba..9ded31429aa21 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index 4cc7ce92fa36f..7864f995abe38 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_path.mdx b/api_docs/kbn_repo_path.mdx index fecbed0ef0b60..c9498bce0302e 100644 --- a/api_docs/kbn_repo_path.mdx +++ b/api_docs/kbn_repo_path.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-path title: "@kbn/repo-path" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-path plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-path'] --- import kbnRepoPathObj from './kbn_repo_path.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index 7244557e8470c..d2a7b8ec1c3b0 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_rison.devdocs.json b/api_docs/kbn_rison.devdocs.json index f6c4c481670fd..6d27f7e58ad0e 100644 --- a/api_docs/kbn_rison.devdocs.json +++ b/api_docs/kbn_rison.devdocs.json @@ -206,6 +206,48 @@ ], "returnComment": [], "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/rison", + "id": "def-common.safeDecode", + "type": "Function", + "tags": [], + "label": "safeDecode", + "description": [ + "\nsafely parse a rison string into a javascript structure, never throws" + ], + "signature": [ + "(rison: string) => ", + { + "pluginId": "@kbn/rison", + "scope": "common", + "docId": "kibKbnRisonPluginApi", + "section": "def-common.RisonValue", + "text": "RisonValue" + } + ], + "path": "packages/kbn-rison/kbn_rison.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/rison", + "id": "def-common.safeDecode.$1", + "type": "string", + "tags": [], + "label": "rison", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-rison/kbn_rison.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false } ], "interfaces": [], diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index 67b306598da61..03bc18f3a3c66 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Owner missing] for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 11 | 2 | 7 | 0 | +| 13 | 2 | 8 | 0 | ## Common diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 86db64e5f6adb..b8ac712c42e1c 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 78c457fe10925..0b729b1f6fddb 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 67b44636f160f..f95919f50a252 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index cc5dd2f38fbca..8311092787864 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-exception-list-components'] --- import kbnSecuritysolutionExceptionListComponentsObj from './kbn_securitysolution_exception_list_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 7a02f64f1b212..ac7de620f2dba 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index fe085680d5ff2..2ef8dd92a6034 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,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 description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 56599820cca0f..77badb89b3721 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,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 description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index ddd0bb78c8452..176ba0cf1c4fe 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index e135cb260ea8d..6bfd56e20badc 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index d70c2aaf47ea0..8748c2146b681 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 3e3f1cb3937b4..b3cdcea9c65fc 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index 5c95c689d6d5e..ac62dd52d18ab 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index 4bff9014fc9f2..7ad64039976b9 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index 9131f3b346d70..793fe2f6c6a3e 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index 55af30ab23a6c..f9d0c539867af 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index fdf7f7bbab4aa..3904573e2058b 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index e0288c33b77ab..96784a9dd35c9 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index ad1a708d546ca..6ffd814a801e8 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index 1fa6690d342d7..2ca9e3a24346a 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_solution.mdx b/api_docs/kbn_shared_ux_avatar_solution.mdx index 2834f7d8b4980..a068857319cb3 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx index 080dd384242a2..b819e612b164e 100644 --- a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx +++ b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-user-profile-components title: "@kbn/shared-ux-avatar-user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-user-profile-components plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-user-profile-components'] --- import kbnSharedUxAvatarUserProfileComponentsObj from './kbn_shared_ux_avatar_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index 993c114ace882..63ab62a2cad15 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx index 24212b49c97a0..673dd28a872ff 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen-mocks title: "@kbn/shared-ux-button-exit-full-screen-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen-mocks'] --- import kbnSharedUxButtonExitFullScreenMocksObj from './kbn_shared_ux_button_exit_full_screen_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 814acac876932..8d4cfa8ec3904 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 7f4152a72a83a..e46e123cb9b61 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index f6d24ff81d069..9a1ce76f350d1 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index 78516c74b4a6c..bed8fa55ea820 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-context'] --- import kbnSharedUxFileContextObj from './kbn_shared_ux_file_context.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index a4e3069519107..0c9a2bbd9333a 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image'] --- import kbnSharedUxFileImageObj from './kbn_shared_ux_file_image.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image_mocks.mdx b/api_docs/kbn_shared_ux_file_image_mocks.mdx index 39a510747f3e4..b9fd59ba697d5 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image-mocks'] --- import kbnSharedUxFileImageMocksObj from './kbn_shared_ux_file_image_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx index 26c8811eddcd4..a9cfd399e8f32 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-mocks'] --- import kbnSharedUxFileMocksObj from './kbn_shared_ux_file_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_picker.mdx b/api_docs/kbn_shared_ux_file_picker.mdx index 5b486f5ab8893..f0d494b0a3112 100644 --- a/api_docs/kbn_shared_ux_file_picker.mdx +++ b/api_docs/kbn_shared_ux_file_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-picker title: "@kbn/shared-ux-file-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-picker plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-picker'] --- import kbnSharedUxFilePickerObj from './kbn_shared_ux_file_picker.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index 3a8c5e6f01493..3915f35e74147 100644 --- a/api_docs/kbn_shared_ux_file_upload.mdx +++ b/api_docs/kbn_shared_ux_file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-upload title: "@kbn/shared-ux-file-upload" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-upload plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-upload'] --- import kbnSharedUxFileUploadObj from './kbn_shared_ux_file_upload.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index 5a18a62168566..d8d658f687890 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-util'] --- import kbnSharedUxFileUtilObj from './kbn_shared_ux_file_util.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app.mdx b/api_docs/kbn_shared_ux_link_redirect_app.mdx index e94bbb4554227..5713155fbae13 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app'] --- import kbnSharedUxLinkRedirectAppObj from './kbn_shared_ux_link_redirect_app.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index 058995b1b27a1..99eb870cd46db 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown.mdx b/api_docs/kbn_shared_ux_markdown.mdx index 5e323f805efb0..be9ca0ecbf780 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown'] --- import kbnSharedUxMarkdownObj from './kbn_shared_ux_markdown.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown_mocks.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index c3ed1a40f6093..222a8ab641754 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown-mocks'] --- import kbnSharedUxMarkdownMocksObj from './kbn_shared_ux_markdown_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index af1b05374b0f3..7e11590cc99d9 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index cf7a2cae82251..dd7197f6299b4 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index 179f0c3cd0bc8..4f6e7532977fe 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index 3fc339955ec20..ca8ab5916b5de 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index 85155fdf266c6..19b40a7902df6 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index 20c89fe979d66..4fb019e469c4c 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index 4d34decfaacba..a2cae7542345c 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index 5035f9405291d..644374168c44a 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index 00d935d807c97..61e86737d7d70 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index bb04fbc45f687..f8bb2f633137d 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index d5f579d9b321e..136b1c121e58c 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index 4bc2698060427..2652798598f01 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index 5c0139a802fbc..2c169936ea675 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_not_found.mdx b/api_docs/kbn_shared_ux_prompt_not_found.mdx index 9c5e6b6bd4194..6a53fda3129d5 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-not-found'] --- import kbnSharedUxPromptNotFoundObj from './kbn_shared_ux_prompt_not_found.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index a3c6bcaaa9b69..bd475c9817650 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router'] --- import kbnSharedUxRouterObj from './kbn_shared_ux_router.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router_mocks.mdx b/api_docs/kbn_shared_ux_router_mocks.mdx index 002c61397fb4f..b8d17a36429c0 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router-mocks'] --- import kbnSharedUxRouterMocksObj from './kbn_shared_ux_router_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index bf463a404c85f..c3904063dab85 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index 40413e0b6ec78..d28a25ce9b93b 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 779b345e74955..909e16e398133 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_slo_schema.devdocs.json b/api_docs/kbn_slo_schema.devdocs.json index f301cd52ad346..dc6a3660a4d79 100644 --- a/api_docs/kbn_slo_schema.devdocs.json +++ b/api_docs/kbn_slo_schema.devdocs.json @@ -82,6 +82,59 @@ ], "returnComment": [] }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.Duration.add", + "type": "Function", + "tags": [], + "label": "add", + "description": [], + "signature": [ + "(other: ", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + }, + ") => ", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + } + ], + "path": "packages/kbn-slo-schema/src/models/duration.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.Duration.add.$1", + "type": "Object", + "tags": [], + "label": "other", + "description": [], + "signature": [ + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + } + ], + "path": "packages/kbn-slo-schema/src/models/duration.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "@kbn/slo-schema", "id": "def-common.Duration.isShorterThan", diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index 4665cd41141d1..a5986452b0568 100644 --- a/api_docs/kbn_slo_schema.mdx +++ b/api_docs/kbn_slo_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-slo-schema title: "@kbn/slo-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/slo-schema plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Owner missing] for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 63 | 0 | 63 | 0 | +| 65 | 0 | 65 | 0 | ## Common diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 6d7d4aaa75740..9490633dfc481 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_package_json.mdx b/api_docs/kbn_sort_package_json.mdx index d5031b98be78c..ad618e638afbc 100644 --- a/api_docs/kbn_sort_package_json.mdx +++ b/api_docs/kbn_sort_package_json.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-package-json title: "@kbn/sort-package-json" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-package-json plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-package-json'] --- import kbnSortPackageJsonObj from './kbn_sort_package_json.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index efe25cb5c111b..a144f96f96fe5 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index 60e2b903b4add..6946804913886 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index 7e5a59e5673d9..327a5d05a565d 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 2ada823d80c8f..96d1f02ce6395 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index b9112c665fa49..d303a57b482ae 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index cd9715e484fec..66bdf19cf3e33 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_subj_selector.mdx b/api_docs/kbn_test_subj_selector.mdx index 07bb626be10f8..ca94ecf200122 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index e897460e5ab71..dba7783132c1c 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_ts_project_linter.mdx b/api_docs/kbn_ts_project_linter.mdx index 6ffc78604b9df..3df6d029b18d8 100644 --- a/api_docs/kbn_ts_project_linter.mdx +++ b/api_docs/kbn_ts_project_linter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-project-linter title: "@kbn/ts-project-linter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-project-linter plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ts-project-linter'] --- import kbnTsProjectLinterObj from './kbn_ts_project_linter.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index ae3b6e29a09b3..8da1219800b34 100644 --- a/api_docs/kbn_ts_projects.mdx +++ b/api_docs/kbn_ts_projects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-projects title: "@kbn/ts-projects" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-projects plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ts-projects'] --- import kbnTsProjectsObj from './kbn_ts_projects.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index b7f710c69a02e..3390e960d7ee9 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index 29f9ff3d5632c..c50c0e47d65e6 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-shared-deps-src'] --- import kbnUiSharedDepsSrcObj from './kbn_ui_shared_deps_src.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index 5dfafb2f60919..6ecc82f0cc75d 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 2b02ca1d5dacb..5b263bacfed52 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index 566b9a40548d7..6de6961a25f45 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index 62d60744d49ce..1b7d28310ac4e 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index badc0905fb8cb..80adf4bbc18dc 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 8b23f28d9a670..138653d6f1eea 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index 61abf9c225c45..44f182b9ed2df 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index d28184f9e5a81..6185ebc07d145 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.devdocs.json b/api_docs/kibana_utils.devdocs.json index 307b8bc437e19..6f0caeb2b3c77 100644 --- a/api_docs/kibana_utils.devdocs.json +++ b/api_docs/kibana_utils.devdocs.json @@ -2730,54 +2730,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "kibanaUtils", - "id": "def-public.createStateHash", - "type": "Function", - "tags": [], - "label": "createStateHash", - "description": [], - "signature": [ - "(json: string, existingJsonProvider: ((hash: string) => string | null) | undefined) => string" - ], - "path": "src/plugins/kibana_utils/public/state_management/state_hash/state_hash.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "kibanaUtils", - "id": "def-public.createStateHash.$1", - "type": "string", - "tags": [], - "label": "json", - "description": [], - "signature": [ - "string" - ], - "path": "src/plugins/kibana_utils/public/state_management/state_hash/state_hash.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "kibanaUtils", - "id": "def-public.createStateHash.$2", - "type": "Function", - "tags": [], - "label": "existingJsonProvider", - "description": [], - "signature": [ - "((hash: string) => string | null) | undefined" - ], - "path": "src/plugins/kibana_utils/public/state_management/state_hash/state_hash.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "kibanaUtils", "id": "def-public.createUrlTracker", @@ -3279,39 +3231,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "kibanaUtils", - "id": "def-public.isStateHash", - "type": "Function", - "tags": [], - "label": "isStateHash", - "description": [], - "signature": [ - "(str: string) => boolean" - ], - "path": "src/plugins/kibana_utils/public/state_management/state_hash/state_hash.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "kibanaUtils", - "id": "def-public.isStateHash.$1", - "type": "string", - "tags": [], - "label": "str", - "description": [], - "signature": [ - "string" - ], - "path": "src/plugins/kibana_utils/public/state_management/state_hash/state_hash.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "kibanaUtils", "id": "def-public.of", @@ -3729,118 +3648,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "kibanaUtils", - "id": "def-public.replaceUrlHashQuery", - "type": "Function", - "tags": [], - "label": "replaceUrlHashQuery", - "description": [], - "signature": [ - "(rawUrl: string, queryReplacer: (query: ", - "ParsedQuery", - ") => ", - "ParsedQuery", - ") => string" - ], - "path": "src/plugins/kibana_utils/public/state_management/url/format.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "kibanaUtils", - "id": "def-public.replaceUrlHashQuery.$1", - "type": "string", - "tags": [], - "label": "rawUrl", - "description": [], - "signature": [ - "string" - ], - "path": "src/plugins/kibana_utils/public/state_management/url/format.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "kibanaUtils", - "id": "def-public.replaceUrlHashQuery.$2", - "type": "Function", - "tags": [], - "label": "queryReplacer", - "description": [], - "signature": [ - "(query: ", - "ParsedQuery", - ") => ", - "ParsedQuery", - "" - ], - "path": "src/plugins/kibana_utils/public/state_management/url/format.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "kibanaUtils", - "id": "def-public.replaceUrlQuery", - "type": "Function", - "tags": [], - "label": "replaceUrlQuery", - "description": [], - "signature": [ - "(rawUrl: string, queryReplacer: (query: ", - "ParsedQuery", - ") => ", - "ParsedQuery", - ") => string" - ], - "path": "src/plugins/kibana_utils/public/state_management/url/format.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "kibanaUtils", - "id": "def-public.replaceUrlQuery.$1", - "type": "string", - "tags": [], - "label": "rawUrl", - "description": [], - "signature": [ - "string" - ], - "path": "src/plugins/kibana_utils/public/state_management/url/format.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "kibanaUtils", - "id": "def-public.replaceUrlQuery.$2", - "type": "Function", - "tags": [], - "label": "queryReplacer", - "description": [], - "signature": [ - "(query: ", - "ParsedQuery", - ") => ", - "ParsedQuery", - "" - ], - "path": "src/plugins/kibana_utils/public/state_management/url/format.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "kibanaUtils", "id": "def-public.retrieveState", @@ -3881,10 +3688,12 @@ "tags": [], "label": "setStateToKbnUrl", "description": [ - "\nSets state to the url by key and returns a new url string.\nDoesn't actually updates history\n\ne.g.:\ngiven a url: http://localhost:5601/oxf/app/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')\nkey: '_a'\nand state: {tab: 'other'}\n\nwill return url:\nhttp://localhost:5601/oxf/app/kibana#/yourApp?_a=(tab:other)&_b=(f:test,i:'',l:'')\n\nBy default due to Kibana legacy reasons assumed that state is stored in a query inside a hash part of the URL:\nhttp://localhost:5601/oxf/app/kibana#/yourApp?_a={STATE}\n\n{ storeInHashQuery: false } option should be used in you want to store you state in a main query (not in a hash):\nhttp://localhost:5601/oxf/app/kibana?_a={STATE}#/yourApp" + "\nSets state to the url by key and returns a new url string.\nDoesn't actually updates history\n\ne.g.:\ngiven a url: http://localhost:5601/oxf/app/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')\nkey: '_a'\nand state: {tab: 'other'}\n\nwill return url:\nhttp://localhost:5601/oxf/app/kibana#/yourApp?_a=(tab:other)&_b=(f:test,i:'',l:'')\n\nBy default due to Kibana legacy reasons assumed that state is stored in a query inside a hash part of the URL:\nhttp://localhost:5601/oxf/app/kibana#/yourApp?_a={STATE}\n\n{ storeInHashQuery: false } option should be used in you want to store your state in a main query (not in a hash):\nhttp://localhost:5601/oxf/app/kibana?_a={STATE}#/yourApp" ], "signature": [ - "(key: string, state: State, { useHash = false, storeInHashQuery = true }: { useHash: boolean; storeInHashQuery?: boolean | undefined; }, rawUrl: string) => string" + "(key: string, state: State, { useHash = false, storeInHashQuery = true }: ", + "SetStateToKbnUrlHashOptions", + ", rawUrl: string) => string" ], "path": "src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts", "deprecated": false, @@ -3927,36 +3736,13 @@ "tags": [], "label": "{ useHash = false, storeInHashQuery = true }", "description": [], + "signature": [ + "SetStateToKbnUrlHashOptions" + ], "path": "src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts", "deprecated": false, "trackAdoption": false, - "children": [ - { - "parentPluginId": "kibanaUtils", - "id": "def-public.setStateToKbnUrl.$3.useHash", - "type": "boolean", - "tags": [], - "label": "useHash", - "description": [], - "path": "src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "kibanaUtils", - "id": "def-public.setStateToKbnUrl.$3.storeInHashQuery", - "type": "CompoundType", - "tags": [], - "label": "storeInHashQuery", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts", - "deprecated": false, - "trackAdoption": false - } - ] + "isRequired": true }, { "parentPluginId": "kibanaUtils", @@ -9675,6 +9461,144 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "kibanaUtils", + "id": "def-common.replaceUrlHashQuery", + "type": "Function", + "tags": [], + "label": "replaceUrlHashQuery", + "description": [], + "signature": [ + "(rawUrl: string, queryReplacer: (query: ", + "ParsedQuery", + ") => ", + "ParsedQuery", + ") => string" + ], + "path": "src/plugins/kibana_utils/common/state_management/format.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "kibanaUtils", + "id": "def-common.replaceUrlHashQuery.$1", + "type": "string", + "tags": [], + "label": "rawUrl", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/kibana_utils/common/state_management/format.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "kibanaUtils", + "id": "def-common.replaceUrlHashQuery.$2", + "type": "Function", + "tags": [], + "label": "queryReplacer", + "description": [], + "signature": [ + "(query: ", + "ParsedQuery", + ") => ", + "ParsedQuery", + "" + ], + "path": "src/plugins/kibana_utils/common/state_management/format.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "kibanaUtils", + "id": "def-common.setStateToKbnUrl", + "type": "Function", + "tags": [], + "label": "setStateToKbnUrl", + "description": [ + "\nCommon version of setStateToKbnUrl which doesn't use session storage.\n\nSets state to the url by key and returns a new url string.\n\ne.g.:\ngiven a url: http://localhost:5601/oxf/app/kibana#/yourApp?_a=(tab:indexedFields)&_b=(f:test,i:'',l:'')\nkey: '_a'\nand state: {tab: 'other'}\n\nwill return url:\nhttp://localhost:5601/oxf/app/kibana#/yourApp?_a=(tab:other)&_b=(f:test,i:'',l:'')\n\nBy default due to Kibana legacy reasons assumed that state is stored in a query inside a hash part of the URL:\nhttp://localhost:5601/oxf/app/kibana#/yourApp?_a={STATE}\n\n{ storeInHashQuery: true } option should be used in you want to store you state in a main query (not in a hash):\nhttp://localhost:5601/oxf/app/kibana?_a={STATE}#/yourApp" + ], + "signature": [ + "(key: string, state: State, hashOptions: ", + "SetStateToKbnUrlHashOptions", + ", rawUrl: string) => string" + ], + "path": "src/plugins/kibana_utils/common/state_management/set_state_to_kbn_url.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "kibanaUtils", + "id": "def-common.setStateToKbnUrl.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/kibana_utils/common/state_management/set_state_to_kbn_url.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "kibanaUtils", + "id": "def-common.setStateToKbnUrl.$2", + "type": "Uncategorized", + "tags": [], + "label": "state", + "description": [], + "signature": [ + "State" + ], + "path": "src/plugins/kibana_utils/common/state_management/set_state_to_kbn_url.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "kibanaUtils", + "id": "def-common.setStateToKbnUrl.$3", + "type": "Object", + "tags": [], + "label": "hashOptions", + "description": [], + "signature": [ + "SetStateToKbnUrlHashOptions" + ], + "path": "src/plugins/kibana_utils/common/state_management/set_state_to_kbn_url.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "kibanaUtils", + "id": "def-common.setStateToKbnUrl.$4", + "type": "string", + "tags": [], + "label": "rawUrl", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/kibana_utils/common/state_management/set_state_to_kbn_url.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "kibanaUtils", "id": "def-common.useContainerSelector", diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index e73d2abf29a90..e9b46e2deb2fd 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; @@ -21,7 +21,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 624 | 3 | 424 | 8 | +| 619 | 3 | 418 | 9 | ## Client diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index a0465ef158baf..0b02243fb4120 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 62bb45d75dfc0..aece2377a7e0a 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index c151aa4240fb6..8c1dcfe2ae8f6 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index a20948523a0e1..26bbf896c2636 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 2d81dbbab4bb8..8832fead82b68 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index da5719363b687..5206ee34cd476 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index 38a5359462315..73b11afa98558 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 2e510bc176047..1322c192f1e3a 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index eaf2097d6941d..6b2f10d29a123 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index e2aa3598e7767..6e858f7ee3336 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 1aa25df608cc4..e9b2f79cc147c 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index dd2569b69e782..6032c8c8df2f8 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index e9991f9a44448..6b88671558f1f 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index ca99e5769e6d2..54ae76a2e6ec8 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index b571a2c8d938f..d27e8e7836f44 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 95abe4f6ba646..148df74b3e762 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/osquery.devdocs.json b/api_docs/osquery.devdocs.json index 9ec19fc8e2d46..afb316f5ab7a5 100644 --- a/api_docs/osquery.devdocs.json +++ b/api_docs/osquery.devdocs.json @@ -43,7 +43,7 @@ "((props: ", "OsqueryActionProps", " & { ecsData?: ", - "AlertEcsData", + "Ecs", " | undefined; }) => JSX.Element) | undefined" ], "path": "x-pack/plugins/osquery/public/types.ts", @@ -190,6 +190,46 @@ "trackAdoption": false } ] + }, + { + "parentPluginId": "osquery", + "id": "def-public.OsqueryPluginStart.fetchAllLiveQueries", + "type": "Function", + "tags": [], + "label": "fetchAllLiveQueries", + "description": [], + "signature": [ + "(config: ", + "UseAllLiveQueriesConfig", + ") => ", + "UseQueryResult", + "<{ data: Omit<", + "ActionsStrategyResponse", + ", \"edges\"> & { items: ", + "SearchHit", + "[]; }; }, Error>" + ], + "path": "x-pack/plugins/osquery/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "osquery", + "id": "def-public.OsqueryPluginStart.fetchAllLiveQueries.$1", + "type": "Object", + "tags": [], + "label": "config", + "description": [], + "signature": [ + "UseAllLiveQueriesConfig" + ], + "path": "x-pack/plugins/osquery/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "lifecycle": "start", @@ -222,7 +262,15 @@ "label": "osqueryCreateAction", "description": [], "signature": [ - "(payload: { agent_ids?: string[] | undefined; agent_all?: boolean | undefined; agent_platforms?: string[] | undefined; agent_policy_ids?: string[] | undefined; query?: string | undefined; queries?: { id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; }[] | { [x: string]: { query: string; id: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; saved_query_id: string | undefined; }; } | undefined; saved_query_id?: string | undefined; ecs_mapping?: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; pack_id?: string | undefined; alert_ids?: string[] | undefined; case_ids?: string[] | undefined; event_ids?: string[] | undefined; metadata?: object | undefined; }) => void" + "(payload: { agent_ids?: string[] | undefined; agent_all?: boolean | undefined; agent_platforms?: string[] | undefined; agent_policy_ids?: string[] | undefined; query?: string | undefined; queries?: { id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; removed: boolean | undefined; snapshot: boolean | undefined; }[] | undefined; saved_query_id?: string | undefined; ecs_mapping?: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; pack_id?: string | undefined; alert_ids?: string[] | undefined; case_ids?: string[] | undefined; event_ids?: string[] | undefined; metadata?: object | undefined; }, ecsData?: ", + { + "pluginId": "@kbn/ecs", + "scope": "common", + "docId": "kibKbnEcsPluginApi", + "section": "def-common.Ecs", + "text": "Ecs" + }, + " | undefined) => void" ], "path": "x-pack/plugins/osquery/server/types.ts", "deprecated": false, @@ -236,12 +284,34 @@ "label": "payload", "description": [], "signature": [ - "{ agent_ids?: string[] | undefined; agent_all?: boolean | undefined; agent_platforms?: string[] | undefined; agent_policy_ids?: string[] | undefined; query?: string | undefined; queries?: { id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; }[] | { [x: string]: { query: string; id: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; saved_query_id: string | undefined; }; } | undefined; saved_query_id?: string | undefined; ecs_mapping?: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; pack_id?: string | undefined; alert_ids?: string[] | undefined; case_ids?: string[] | undefined; event_ids?: string[] | undefined; metadata?: object | undefined; }" + "{ agent_ids?: string[] | undefined; agent_all?: boolean | undefined; agent_platforms?: string[] | undefined; agent_policy_ids?: string[] | undefined; query?: string | undefined; queries?: { id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; removed: boolean | undefined; snapshot: boolean | undefined; }[] | undefined; saved_query_id?: string | undefined; ecs_mapping?: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; pack_id?: string | undefined; alert_ids?: string[] | undefined; case_ids?: string[] | undefined; event_ids?: string[] | undefined; metadata?: object | undefined; }" ], "path": "x-pack/plugins/osquery/server/types.ts", "deprecated": false, "trackAdoption": false, "isRequired": true + }, + { + "parentPluginId": "osquery", + "id": "def-server.OsqueryPluginSetup.osqueryCreateAction.$2", + "type": "CompoundType", + "tags": [], + "label": "ecsData", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ecs", + "scope": "common", + "docId": "kibKbnEcsPluginApi", + "section": "def-common.Ecs", + "text": "Ecs" + }, + " | undefined" + ], + "path": "x-pack/plugins/osquery/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false } ], "returnComment": [] diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 2e4807c07f70e..107defad71e0a 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Security asset management](https://github.com/orgs/elastic/teams/securi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 21 | 0 | 21 | 5 | +| 24 | 0 | 24 | 7 | ## Client diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 8f07bfcaffcfb..a697f82929b5a 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,13 +15,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 541 | 447 | 42 | +| 544 | 450 | 42 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 33995 | 521 | 23728 | 1167 | +| 34131 | 521 | 23848 | 1178 | ## Plugin Directory @@ -30,7 +30,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 220 | 8 | 215 | 24 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 36 | 1 | 32 | 2 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | AIOps plugin maintained by ML team. | 12 | 0 | 1 | 2 | -| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 427 | 0 | 418 | 37 | +| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 429 | 0 | 420 | 37 | | | [APM UI](https://github.com/orgs/elastic/teams/apm-ui) | The user interface for Elastic APM | 42 | 0 | 42 | 58 | | | [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. | 89 | 1 | 74 | 2 | @@ -56,12 +56,12 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 52 | 0 | 51 | 0 | | | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | 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. | 3300 | 119 | 2578 | 27 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | This plugin provides the ability to create data views via a modal flyout inside Kibana apps | 16 | 0 | 7 | 0 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Reusable data view field editor across Kibana | 60 | 0 | 30 | 0 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Reusable data view field editor across Kibana | 72 | 0 | 33 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data view management app | 2 | 0 | 2 | 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. | 1032 | 0 | 231 | 2 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The Data Visualizer tools help you understand your data, by analyzing the metrics and fields in a log file or an existing Elasticsearch index. | 29 | 3 | 25 | 1 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 10 | 0 | 8 | 2 | -| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 100 | 0 | 82 | 4 | +| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 107 | 0 | 88 | 7 | | | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 37 | 0 | 35 | 2 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds embeddables service to Kibana | 524 | 8 | 423 | 4 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Extends embeddable plugin with more functionality | 14 | 0 | 14 | 0 | @@ -89,7 +89,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 62 | 0 | 62 | 2 | | | [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/team:AppServicesUx) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 252 | 1 | 45 | 5 | | | [@elastic/kibana-global-experience](https://github.com/orgs/elastic/teams/@elastic/kibana-global-experience) | Simple UI for managing files in Kibana | 2 | 1 | 2 | 0 | -| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1029 | 3 | 924 | 20 | +| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1032 | 3 | 926 | 20 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | globalSearchProviders | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | @@ -108,7 +108,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 6 | 0 | 6 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 184 | 1 | 151 | 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) | - | 624 | 3 | 424 | 8 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 619 | 3 | 418 | 9 | | | [Security Team](https://github.com/orgs/elastic/teams/security-team) | - | 3 | 0 | 3 | 1 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-visualizations) | 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. | 695 | 0 | 599 | 50 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 8 | 0 | 8 | 0 | @@ -126,7 +126,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 17 | 0 | 17 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 2 | 0 | 2 | 1 | | | [Observability UI](https://github.com/orgs/elastic/teams/observability-ui) | - | 571 | 38 | 567 | 31 | -| | [Security asset management](https://github.com/orgs/elastic/teams/security-asset-management) | - | 21 | 0 | 21 | 5 | +| | [Security asset management](https://github.com/orgs/elastic/teams/security-asset-management) | - | 24 | 0 | 24 | 7 | | 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). | 231 | 7 | 175 | 11 | | | [profiling](https://github.com/orgs/elastic/teams/profiling-ui) | - | 15 | 2 | 15 | 0 | @@ -165,9 +165,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 579 | 11 | 550 | 53 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds UI Actions service to Kibana | 140 | 2 | 97 | 12 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Extends UI Actions plugin with more functionality | 206 | 0 | 142 | 9 | -| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Contains functionality for the field list which can be integrated into apps | 269 | 0 | 244 | 7 | +| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Contains functionality for the field list which can be integrated into apps | 270 | 0 | 245 | 7 | | | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | The `unifiedHistogram` plugin provides UI components to create a layout including a resizable histogram and a main display. | 52 | 0 | 15 | 0 | -| | [Visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Contains all the key functionality of Kibana's unified search experience.Contains all the key functionality of Kibana's unified search experience. | 134 | 2 | 99 | 19 | +| | [Visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Contains all the key functionality of Kibana's unified search experience.Contains all the key functionality of Kibana's unified search experience. | 134 | 2 | 99 | 20 | | upgradeAssistant | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | urlDrilldown | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds drilldown implementations to Kibana | 0 | 0 | 0 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 12 | 0 | 12 | 0 | @@ -205,7 +205,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | Kibana Core | - | 21 | 0 | 0 | 0 | | | Kibana Core | - | 18 | 0 | 2 | 0 | | | [Owner missing] | - | 17 | 0 | 17 | 0 | -| | [Owner missing] | Elastic APM trace data generator | 77 | 0 | 77 | 15 | +| | [Owner missing] | Elastic APM trace data generator | 27 | 0 | 27 | 3 | +| | [Owner missing] | Elastic APM trace data generator | 152 | 0 | 152 | 16 | | | [Owner missing] | - | 11 | 0 | 11 | 0 | | | [Owner missing] | - | 10 | 0 | 10 | 0 | | | [Owner missing] | - | 4 | 0 | 3 | 0 | @@ -411,7 +412,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Owner missing] | - | 6 | 0 | 1 | 1 | | | [Owner missing] | - | 534 | 1 | 1 | 0 | | | Machine Learning UI | This package includes utility functions related to creating elasticsearch aggregation queries, data manipulation and verification. | 82 | 2 | 58 | 0 | +| | [Owner missing] | - | 2 | 0 | 1 | 0 | | | Machine Learning UI | A type guard to check record like object structures. | 3 | 0 | 2 | 0 | +| | Machine Learning UI | Utilities to combine url state management with local storage. | 5 | 0 | 3 | 0 | | | Machine Learning UI | TypeScript-aware utility functions to get/set attributes from objects. | 8 | 2 | 8 | 0 | | | Machine Learning UI | Creates a deterministic number based hash out of a string. | 2 | 0 | 1 | 0 | | | Machine Learning UI | Url state management utilities. | 31 | 1 | 24 | 1 | @@ -425,7 +428,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Owner missing] | - | 21 | 0 | 10 | 0 | | | [Owner missing] | - | 11 | 0 | 8 | 0 | | | [Owner missing] | - | 6 | 0 | 6 | 1 | -| | [Owner missing] | - | 11 | 2 | 7 | 0 | +| | [Owner missing] | - | 13 | 2 | 8 | 0 | | | [Owner missing] | - | 97 | 0 | 94 | 0 | | | [Owner missing] | Security Solution auto complete | 56 | 1 | 41 | 1 | | | [Owner missing] | security solution elastic search utilities to use across plugins such lists, security_solution, cases, etc... | 67 | 0 | 61 | 1 | @@ -482,7 +485,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Owner missing] | - | 2 | 0 | 0 | 0 | | | [Owner missing] | - | 15 | 0 | 4 | 0 | | | [Owner missing] | - | 9 | 0 | 3 | 0 | -| | [Owner missing] | SLO io-ts schema definition and common models shared between public and server. | 63 | 0 | 63 | 0 | +| | [Owner missing] | SLO io-ts schema definition and common models shared between public and server. | 65 | 0 | 65 | 0 | | | [Owner missing] | - | 20 | 0 | 12 | 0 | | | [Owner missing] | - | 2 | 0 | 2 | 0 | | | Kibana Core | - | 97 | 1 | 64 | 1 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 125c4bfe5bc1b..ba76ab22302ee 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index 8c1aea06b0162..5ad31e51db80b 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 1c9b50b719128..78e3ef59625e5 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index c99e9c3834f28..0ba680ce495e3 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index 579ffcf5fca08..3d0b9a0fa58e2 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 061d2915ce5b2..6b993f220bda6 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index 0e36073b5710a..38a129be1d77a 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index be290e20679f0..0d16830dcc99c 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index c9b96614b2a34..9000fc7b91ea0 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index 1bf87c339d0e9..e3c723291457d 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index 5e9c2e4e31f48..7d3ecae3665ed 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 586e4aa8490bd..43febb7894ba6 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index 168f53bd501c3..3a668bf2061ef 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index cdb67fc0305ad..cd7f0dc88773f 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index a0a1e0fe74690..64ffa67bafcd4 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 53f129c5b862d..dd977aafaab27 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 69e77842b9e33..8e75bb1d52d7d 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 209c672e1e1bd..d582cf2d75a65 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index 53180d67261be..f1a2b3c1b7fd0 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index e6d67d3147fc5..b06a27b9e49ce 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index ee4e29aa13080..c0315f4fd599b 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index 9082cc379c1f7..3460f2aa4cb2f 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/stack_connectors.mdx b/api_docs/stack_connectors.mdx index 8267ffe362fbb..8d0c6770518e4 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 2ac3a10c58b42..0cd86f3bcc273 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index f5c0a1fd70413..27584775ffd9b 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 4ce7b2bb14b7c..f1195314db4bc 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 846a836deb78e..bf9b9ca42aaaa 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index c950dc5cc5bf8..6e2f61a625b8f 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index ba7d534452672..39748981da0d1 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index e13fffa01b6aa..add1032a306fc 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index bdef21038a511..4be6a50ed7261 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index 44098cf130fe4..0b26c32a445ec 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index b6666167770a3..77ef9bfaee8c9 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index 9b0d2ce308a8a..f81e623fa3f73 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_field_list.devdocs.json b/api_docs/unified_field_list.devdocs.json index 19bf10e13212d..4b58ce1785a44 100644 --- a/api_docs/unified_field_list.devdocs.json +++ b/api_docs/unified_field_list.devdocs.json @@ -2680,6 +2680,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldListGroupedProps.localStorageKeyPrefix", + "type": "string", + "tags": [], + "label": "localStorageKeyPrefix", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_list_grouped/field_list_grouped.tsx", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "unifiedFieldList", "id": "def-public.FieldListGroupedProps.datatestsubj", diff --git a/api_docs/unified_field_list.mdx b/api_docs/unified_field_list.mdx index 30c61d67c55b4..afbd1e1598768 100644 --- a/api_docs/unified_field_list.mdx +++ b/api_docs/unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedFieldList title: "unifiedFieldList" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedFieldList plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 269 | 0 | 244 | 7 | +| 270 | 0 | 245 | 7 | ## Client diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index 9b07ff8b2785a..d276f90bb9ac7 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.devdocs.json b/api_docs/unified_search.devdocs.json index bd59a466a5169..a18eb699a0f2a 100644 --- a/api_docs/unified_search.devdocs.json +++ b/api_docs/unified_search.devdocs.json @@ -157,9 +157,11 @@ "\nRenders a single filter pill" ], "signature": [ - "(props: ", + "(props: Omit<", "FilterItemProps", - ") => JSX.Element" + ", keyof ", + "WithCloseFilterEditorConfirmModalProps", + ">) => JSX.Element" ], "path": "src/plugins/unified_search/public/filter_bar/index.tsx", "deprecated": false, @@ -173,7 +175,11 @@ "label": "props", "description": [], "signature": [ - "FilterItemProps" + "Omit<", + "FilterItemProps", + ", keyof ", + "WithCloseFilterEditorConfirmModalProps", + ">" ], "path": "src/plugins/unified_search/public/filter_bar/index.tsx", "deprecated": false, diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 6c31fe0e88adc..91f88d1bc3c08 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Visualizations](https://github.com/orgs/elastic/teams/kibana-visualizat | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 134 | 2 | 99 | 19 | +| 134 | 2 | 99 | 20 | ## Client diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index 040c02814b669..94ebb1bf531a3 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Visualizations](https://github.com/orgs/elastic/teams/kibana-visualizat | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 134 | 2 | 99 | 19 | +| 134 | 2 | 99 | 20 | ## Client diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index 2050243ee5c98..3b98d214a2e62 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 40eb092071d15..8465f448402f9 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index 03664ce4d35b6..e5ac4adf0bbcc 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index c696b9f4a7726..1b43811ead118 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index 96bfd4cd91f0c..753209d1409ef 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index abcd85cb9d53e..2005588d77a94 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index f52cbf84d3e63..2cf6d1f050956 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index 85aeea05d5afb..19cddded0cb1f 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 4bc2596d433c9..4cfae7b2b112e 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index d7e4d794ce0c5..adc05ae437aa6 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index b8dd706506a66..b366f5fd42147 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index d6a74dd1c905d..470be3eab03b9 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 844f11a4df15b..146642c3e898d 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 3ee2fd69a9c53..910f7ff56c769 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2023-01-04 +date: 2023-01-09 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; diff --git a/docs/management/cases/manage-cases.asciidoc b/docs/management/cases/manage-cases.asciidoc index 08a57240799d0..71b1694e046a8 100644 --- a/docs/management/cases/manage-cases.asciidoc +++ b/docs/management/cases/manage-cases.asciidoc @@ -54,11 +54,49 @@ go back to your case. After a visualization has been added to a case, you can modify or interact with it by clicking the *Open Visualization* option in the comment menu. +[[add-case-notifications]] +=== Add email notifications + +// tag::case-notifications[] +You can configure email notifications that occur when users are assigned to +cases. + +For hosted {kib} on {ess}: + +. Add the email addresses to the monitoring email allowlist. Follow the steps in +{cloud}/ec-watcher.html#ec-watcher-allowlist[Send alerts by email]. ++ +-- +You do not need to take any more steps to configure an email connector or update +{kib} user settings, since the preconfigured Elastic-Cloud-SMTP connector is +used by default. +-- + +For self-managed {kib}: + +. Create a preconfigured email connector. ++ +-- +NOTE: At this time, email notifications support only preconfigured connectors, +which are defined in the `kibana.yml` file. For examples, refer to +{kibana-ref}/email-action-type.html#preconfigured-email-configuration[Preconfigured email connector] +and {kibana-ref}/email-action-type.html#configuring-email[Configuring email connectors for well-known services]. +-- +. Set the `notifications.connectors.default.email` {kib} setting to the name of +your email connector. +. If you want the email notifications to contain links back to the case, you +must configure the {kibana-ref}/settings.html#server-publicBaseUrl[server.publicBaseUrl] setting. + +When you subsequently add assignees to cases, they receive an email. +// end::case-notifications[] + [[manage-case]] === Manage cases In *Management > {stack-manage-app} > Cases*, you can search cases and filter -them by severity, status, tags, and assignees. +them by attributes such as assignees, severity, status, and tags. You can also +select multiple cases and use bulk actions to delete cases or change their +attributes. To view a case, click on its name. You can then: diff --git a/docs/management/connectors/action-types/tines.asciidoc b/docs/management/connectors/action-types/tines.asciidoc index b9060943adf57..ff98cd6c50ecb 100644 --- a/docs/management/connectors/action-types/tines.asciidoc +++ b/docs/management/connectors/action-types/tines.asciidoc @@ -84,7 +84,7 @@ image::management/connectors/images/tines-webhook-url-fallback.png[Tines Webhook [float] [[tines-story-library]] -=== Tines Story Libary +=== Tines story library In order to simplify the integration with Elastic, Tines offers a set of pre-defined Elastic stories in the Story library. They can be found by searching for "Elastic" in the Tines Story library: diff --git a/docs/settings/fleet-settings.asciidoc b/docs/settings/fleet-settings.asciidoc index 6d907ba23a807..41319a85612ee 100644 --- a/docs/settings/fleet-settings.asciidoc +++ b/docs/settings/fleet-settings.asciidoc @@ -197,3 +197,6 @@ xpack.fleet.agentPolicies: - type: winlog enabled: false ---- + +`xpack.fleet.enableExperimental`:: +List of experimental feature flag to enable in Fleet. \ No newline at end of file diff --git a/docs/setup/install/targz.asciidoc b/docs/setup/install/targz.asciidoc index 1d8c61a6e9a07..2dd6058106a56 100644 --- a/docs/setup/install/targz.asciidoc +++ b/docs/setup/install/targz.asciidoc @@ -50,7 +50,7 @@ endif::[] .macOS Gatekeeper warnings ==== Apple's rollout of stricter notarization requirements affected the notarization -of the {version} {kib} artifacts. If macOS Catalina displays a dialog when you +of the {version} {kib} artifacts. If macOS displays a dialog when you first run {kib} that interrupts it, you will need to take an action to allow it to run. diff --git a/docs/user/security/audit-logging.asciidoc b/docs/user/security/audit-logging.asciidoc index b832b21a3eeb7..91d39da28be4e 100644 --- a/docs/user/security/audit-logging.asciidoc +++ b/docs/user/security/audit-logging.asciidoc @@ -90,6 +90,24 @@ Refer to the corresponding {es} logs for potential write errors. | `unknown` | User is creating a space. | `failure` | User is not authorized to create a space. +.2+| `case_create` +| `unknown` | User is creating a case. +| `failure` | User is not authorized to create a case. + +.2+| `case_configuration_create` +| `unknown` | User is creating a case configuration. +| `failure` | User is not authorized to create a case configuration. + +.2+| `case_comment_create` +| `unknown` | User is creating a case comment. +| `failure` | User is not authorized to create a case comment. + +.1+| `case_user_action_create_comment` +| `success` | User has created a case comment. + +.1+| `case_user_action_create_case` +| `success` | User has created a case. + 3+a| ====== Type: change @@ -165,6 +183,48 @@ Refer to the corresponding {es} logs for potential write errors. | `unknown` | User is unsnoozing a rule. | `failure` | User is not authorized to unsnooze a rule. +.2+| `case_update` +| `unknown` | User is updating a case. +| `failure` | User is not authorized to update a case. + +.2+| `case_push` +| `unknown` | User is pushing a case to an external service. +| `failure` | User is not authorized to push a case to an external service. + +.2+| `case_configuration_update` +| `unknown` | User is updating a case configuration. +| `failure` | User is not authorized to update a case configuration. + +.2+| `case_comment_update` +| `unknown` | User is updating a case comment. +| `failure` | User is not authorized to update a case comment. + +.1+| `case_user_action_add_case_assignees` +| `success` | User has added a case assignee. + +.1+| `case_user_action_update_case_connector` +| `success` | User has updated a case connector. + +.1+| `case_user_action_update_case_description` +| `success` | User has updated a case description. + +.1+| `case_user_action_update_case_settings` +| `success` | User has updated the case settings. + +.1+| `case_user_action_update_case_severity` +| `success` | User has updated the case severity. + +.1+| `case_user_action_update_case_status` +| `success` | User has updated the case status. + +.1+| `case_user_action_pushed_case` +| `success` | User has pushed a case to an external service. + +.1+| `case_user_action_add_case_tags` +| `success` | User has added tags to a case. + +.1+| `case_user_action_update_case_title` +| `success` | User has updated the case title. 3+a| ====== Type: deletion @@ -193,6 +253,30 @@ Refer to the corresponding {es} logs for potential write errors. | `unknown` | User is deleting a space. | `failure` | User is not authorized to delete a space. +.2+| `case_delete` +| `unknown` | User is deleting a case. +| `failure` | User is not authorized to delete a case. + +.2+| `case_comment_delete_all` +| `unknown` | User is deleting all comments associated with a case. +| `failure` | User is not authorized to delete all comments associated with a case. + +.2+| `case_comment_delete` +| `unknown` | User is deleting a case comment. +| `failure` | User is not authorized to delete a case comment. + +.1+| `case_user_action_delete_case_assignees` +| `success` | User has removed a case assignee. + +.1+| `case_user_action_delete_comment` +| `success` | User has deleted a case comment. + +.1+| `case_user_action_delete_case` +| `success` | User has deleted a case. + +.1+| `case_user_action_delete_case_tags` +| `success` | User has removed tags from a case. + 3+a| ====== Type: access @@ -248,6 +332,74 @@ Refer to the corresponding {es} logs for potential write errors. | `success` | User has accessed an alert as part of a search operation. | `failure` | User is not authorized to access alerts. +.2+| `case_get` +| `success` | User has accessed a case. +| `failure` | User is not authorized to access a case. + +.2+| `case_resolve` +| `success` | User has accessed a case. +| `failure` | User is not authorized to access a case. + +.2+| `case_find` +| `success` | User has accessed a case as part of a search operation. +| `failure` | User is not authorized to search for cases. + +.2+| `case_ids_by_alert_id_get` +| `success` | User has accessed cases. +| `failure` | User is not authorized to access cases. + +.2+| `case_get_metrics` +| `success` | User has accessed metrics for a case. +| `failure` | User is not authorized to access metrics for a case. + +.2+| `cases_get_metrics` +| `success` | User has accessed metrics for cases. +| `failure` | User is not authorized to access metrics for cases. + +.2+| `case_configuration_find` +| `success` | User has accessed a case configuration as part of a search operation. +| `failure` | User is not authorized to search for case configurations. + +.2+| `case_comment_get_metrics` +| `success` | User has accessed metrics for case comments. +| `failure` | User is not authorized to access metrics for case comments. + +.2+| `case_comment_alerts_attach_to_case` +| `success` | User has accessed case alerts. +| `failure` | User is not authorized to access case alerts. + +.2+| `case_comment_get` +| `success` | User has accessed a case comment. +| `failure` | User is not authorized to access a case comment. + +.2+| `case_comment_get_all` +| `success` | User has accessed case comments. +| `failure` | User is not authorized to access case comments. + +.2+| `case_comment_find` +| `success` | User has accessed a case comment as part of a search operation. +| `failure` | User is not authorized to search for case comments. + +.2+| `case_tags_get` +| `success` | User has accessed a case. +| `failure` | User is not authorized to access a case. + +.2+| `case_reporters_get` +| `success` | User has accessed a case. +| `failure` | User is not authorized to access a case. + +.2+| `case_find_statuses` +| `success` | User has accessed a case as part of a search operation. +| `failure` | User is not authorized to search for cases. + +.2+| `case_user_actions_get` +| `success` | User has accessed the user activity of a case. +| `failure` | User is not authorized to access the user activity of a case. + +.2+| `case_user_action_get_metrics` +| `success` | User has accessed metrics for the user activity of a case. +| `failure` | User is not authorized to access metrics for the user activity of a case. + 3+a| ===== Category: web diff --git a/package.json b/package.json index d5e1dbeadb1bf..9bd39109e62c9 100644 --- a/package.json +++ b/package.json @@ -350,7 +350,9 @@ "@kbn/logging-mocks": "link:packages/kbn-logging-mocks", "@kbn/mapbox-gl": "link:packages/kbn-mapbox-gl", "@kbn/ml-agg-utils": "link:x-pack/packages/ml/agg_utils", + "@kbn/ml-is-defined": "link:x-pack/packages/ml/is_defined", "@kbn/ml-is-populated-object": "link:x-pack/packages/ml/is_populated_object", + "@kbn/ml-local-storage": "link:x-pack/packages/ml/local_storage", "@kbn/ml-nested-property": "link:x-pack/packages/ml/nested_property", "@kbn/ml-string-hash": "link:x-pack/packages/ml/string_hash", "@kbn/ml-url-state": "link:x-pack/packages/ml/url_state", @@ -494,7 +496,7 @@ "compare-versions": "3.5.1", "constate": "^3.3.2", "copy-to-clipboard": "^3.0.8", - "core-js": "^3.27.0", + "core-js": "^3.27.1", "cronstrue": "^1.51.0", "cuid": "^2.1.8", "cytoscape": "^3.10.0", @@ -565,7 +567,7 @@ "load-json-file": "^6.2.0", "lodash": "^4.17.21", "lru-cache": "^4.1.5", - "luxon": "^2.3.2", + "luxon": "^2.5.2", "lz-string": "^1.4.4", "mapbox-gl-draw-rectangle-mode": "1.0.4", "maplibre-gl": "2.1.9", @@ -619,7 +621,7 @@ "react-fast-compare": "^2.0.4", "react-focus-on": "^3.7.0", "react-grid-layout": "^1.3.4", - "react-hook-form": "^7.41.1", + "react-hook-form": "^7.41.3", "react-intl": "^2.8.0", "react-is": "^17.0.2", "react-markdown": "^6.0.3", @@ -896,7 +898,7 @@ "@types/jsdom": "^16.2.14", "@types/json-schema": "^7", "@types/json-stable-stringify": "^1.0.32", - "@types/json5": "^0.0.30", + "@types/json5": "^2.2.0", "@types/jsonwebtoken": "^8.5.6", "@types/license-checker": "15.0.0", "@types/listr": "^0.14.0", @@ -953,7 +955,7 @@ "@types/redux-logger": "^3.0.8", "@types/resolve": "^1.20.1", "@types/seedrandom": ">=2.0.0 <4.0.0", - "@types/selenium-webdriver": "^4.1.9", + "@types/selenium-webdriver": "^4.1.10", "@types/semver": "^7", "@types/set-value": "^2.0.0", "@types/sharp": "^0.30.4", @@ -1017,14 +1019,14 @@ "cssnano": "^5.1.12", "cssnano-preset-default": "^5.2.12", "csstype": "^3.0.2", - "cypress": "^11.2.0", - "cypress-axe": "^1.0.0", + "cypress": "^12.3.0", + "cypress-axe": "^1.2.0", "cypress-file-upload": "^5.0.8", - "cypress-multi-reporters": "^1.6.1", + "cypress-multi-reporters": "^1.6.2", "cypress-pipe": "^2.0.0", "cypress-react-selector": "^3.0.0", - "cypress-real-events": "^1.7.4", - "cypress-recurse": "^1.24.0", + "cypress-real-events": "^1.7.6", + "cypress-recurse": "^1.26.0", "debug": "^2.6.9", "delete-empty": "^2.0.0", "dependency-check": "^4.1.0", @@ -1087,7 +1089,7 @@ "jest-styled-components": "7.0.3", "jsdom": "^16.4.0", "json-schema-typed": "^8.0.1", - "json5": "^1.0.1", + "json5": "^2.2.3", "jsondiffpatch": "0.4.1", "license-checker": "^25.0.1", "listr": "^0.14.1", diff --git a/packages/kbn-babel-transform/options.js b/packages/kbn-babel-transform/options.js index c8c089f873da7..4b98a790414e7 100644 --- a/packages/kbn-babel-transform/options.js +++ b/packages/kbn-babel-transform/options.js @@ -31,7 +31,7 @@ function getBabelOptions(path, config = {}) { ], cwd, babelrc: false, - sourceMaps: !config.disableSourceMaps, + sourceMaps: config.disableSourceMaps ? false : 'both', ast: false, }; } diff --git a/packages/kbn-es/README.mdx b/packages/kbn-es/README.mdx index a5392504490fe..d65171641613e 100644 --- a/packages/kbn-es/README.mdx +++ b/packages/kbn-es/README.mdx @@ -70,6 +70,16 @@ Type: `String` Location where snapshots are cached +## Snapshot Updates + +Snapshots are built and tested daily. If tests pass, the snapshot is promoted and will automatically be used when started from the CLI. + +CI pipelines supporting this can be found at: + +- https://buildkite.com/elastic/kibana-elasticsearch-snapshot-build +- https://buildkite.com/elastic/kibana-elasticsearch-snapshot-verify +- https://buildkite.com/elastic/kibana-elasticsearch-snapshot-promote + ## Snapshot Pinning Sometimes we need to pin snapshots for a specific version. We'd really like to get this automated, but until that is completed here are the steps to take to build, upload, and switch to pinned snapshots for a branch. diff --git a/packages/kbn-journeys/index.ts b/packages/kbn-journeys/index.ts index cc4c10c685d1c..def8e5f3b0d59 100644 --- a/packages/kbn-journeys/index.ts +++ b/packages/kbn-journeys/index.ts @@ -7,7 +7,11 @@ */ export { JourneyConfig } from './journey/journey_config'; -export type { ScalabilityAction, ScalabilitySetup } from './journey/journey_config'; +export type { + ScalabilityAction, + ScalabilitySetup, + ResponseTimeMetric, +} from './journey/journey_config'; export { Journey } from './journey/journey'; export type { Step } from './journey/journey'; diff --git a/packages/kbn-journeys/journey/journey_config.ts b/packages/kbn-journeys/journey/journey_config.ts index 5323d7989bdf5..53b321aa0c05d 100644 --- a/packages/kbn-journeys/journey/journey_config.ts +++ b/packages/kbn-journeys/journey/journey_config.ts @@ -39,6 +39,18 @@ export interface ConstantConcurrentUsersAction { export type ScalabilityAction = RampConcurrentUsersAction | ConstantConcurrentUsersAction; +export type ResponseTimeMetric = + | 'min' + | '25%' + | '50%' + | '75%' + | '80%' + | '85%' + | '90%' + | '95%' + | '99%' + | 'max'; + export interface ScalabilitySetup { /** * Duration strings must be formatted as string that starts with an integer and @@ -47,6 +59,12 @@ export interface ScalabilitySetup { * eg: "1m" or "30s" */ maxDuration: string; + responseTimeMetric?: ResponseTimeMetric; + responseTimeThreshold?: { + threshold1: number; + threshold2: number; + threshold3: number; + }; warmup: ScalabilityAction[]; test: ScalabilityAction[]; } diff --git a/packages/kbn-osquery-io-ts-types/src/live_query/index.ts b/packages/kbn-osquery-io-ts-types/src/live_query/index.ts index 08352be1e78ca..378bb446cafab 100644 --- a/packages/kbn-osquery-io-ts-types/src/live_query/index.ts +++ b/packages/kbn-osquery-io-ts-types/src/live_query/index.ts @@ -99,6 +99,8 @@ export const arrayQueries = t.array( ecs_mapping: ecsMappingOrUndefined, version: versionOrUndefined, platform: platformOrUndefined, + removed: removedOrUndefined, + snapshot: snapshotOrUndefined, }) ); export type ArrayQueries = t.TypeOf; @@ -111,10 +113,12 @@ export const objectQueries = t.record( version: versionOrUndefined, platform: platformOrUndefined, saved_query_id: savedQueryIdOrUndefined, + removed: removedOrUndefined, + snapshot: snapshotOrUndefined, }) ); export type ObjectQueries = t.TypeOf; export const queries = t.union([arrayQueries, objectQueries]); export type Queries = t.TypeOf; -export const queriesOrUndefined = t.union([queries, t.undefined]); +export const queriesOrUndefined = t.union([arrayQueries, t.undefined]); // in the future we might need to support `objectQueries` so use `queries` instead of `arrayQueries` - now removing this because of strange type issue where query is a number export type QueriesOrUndefined = t.TypeOf; diff --git a/packages/kbn-rison/kbn_rison.test.ts b/packages/kbn-rison/kbn_rison.test.ts index 0a3e49cacf485..a085ef299f92c 100644 --- a/packages/kbn-rison/kbn_rison.test.ts +++ b/packages/kbn-rison/kbn_rison.test.ts @@ -21,7 +21,7 @@ describe('encoding', () => { }); it('throws if it received undefined', () => { expect(() => Rison.encode(undefined)).toThrowErrorMatchingInlineSnapshot( - `"unable to encode value into rison, expected a primative value array or object"` + `"unable to encode value into rison, expected a primitive value array or object"` ); }); it('encodes a complex object', () => { diff --git a/packages/kbn-rison/kbn_rison.ts b/packages/kbn-rison/kbn_rison.ts index 4b2fe7958704c..be789a9a54560 100644 --- a/packages/kbn-rison/kbn_rison.ts +++ b/packages/kbn-rison/kbn_rison.ts @@ -29,7 +29,7 @@ export function encode(obj: any) { const rison = encodeUnknown(obj); if (rison === undefined) { throw new Error( - 'unable to encode value into rison, expected a primative value array or object' + 'unable to encode value into rison, expected a primitive value array or object' ); } return rison; @@ -42,6 +42,17 @@ export function decode(rison: string): RisonValue { return Rison.decode(rison); } +/** + * safely parse a rison string into a javascript structure, never throws + */ +export function safeDecode(rison: string): RisonValue { + try { + return decode(rison); + } catch { + return null; + } +} + /** * rison-encode a javascript array without surrounding parens */ diff --git a/packages/kbn-slo-schema/src/models/duration.test.ts b/packages/kbn-slo-schema/src/models/duration.test.ts index 2b61063f0d5b8..f3cd23278b41a 100644 --- a/packages/kbn-slo-schema/src/models/duration.test.ts +++ b/packages/kbn-slo-schema/src/models/duration.test.ts @@ -78,4 +78,25 @@ describe('Duration', () => { expect(short.isLongerOrEqualThan(new Duration(1, DurationUnit.Year))).toBe(false); }); }); + + describe('add', () => { + it('returns the duration result in minute', () => { + const someDuration = new Duration(1, DurationUnit.Minute); + expect(someDuration.add(new Duration(1, DurationUnit.Minute))).toEqual( + new Duration(2, DurationUnit.Minute) + ); + expect(someDuration.add(new Duration(1, DurationUnit.Hour))).toEqual( + new Duration(61, DurationUnit.Minute) + ); + expect(someDuration.add(new Duration(1, DurationUnit.Day))).toEqual( + new Duration(1441, DurationUnit.Minute) + ); + expect(someDuration.add(new Duration(1, DurationUnit.Week))).toEqual( + new Duration(10081, DurationUnit.Minute) + ); + expect(someDuration.add(new Duration(1, DurationUnit.Month))).toEqual( + new Duration(43201, DurationUnit.Minute) + ); + }); + }); }); diff --git a/packages/kbn-slo-schema/src/models/duration.ts b/packages/kbn-slo-schema/src/models/duration.ts index 3788882b7b9c4..ecffb97f30e57 100644 --- a/packages/kbn-slo-schema/src/models/duration.ts +++ b/packages/kbn-slo-schema/src/models/duration.ts @@ -29,6 +29,16 @@ class Duration { } } + add(other: Duration): Duration { + const currentDurationMoment = moment.duration(this.value, toMomentUnitOfTime(this.unit)); + const otherDurationMoment = moment.duration(other.value, toMomentUnitOfTime(other.unit)); + + return new Duration( + currentDurationMoment.add(otherDurationMoment).asMinutes(), + DurationUnit.Minute + ); + } + isShorterThan(other: Duration): boolean { const otherDurationMoment = moment.duration(other.value, toMomentUnitOfTime(other.unit)); const currentDurationMoment = moment.duration(this.value, toMomentUnitOfTime(this.unit)); diff --git a/src/core/server/integration_tests/saved_objects/migrations/multiple_kibana_nodes.test.ts b/src/core/server/integration_tests/saved_objects/migrations/multiple_kibana_nodes.test.ts index 34df1d484b92b..a947854e9249b 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/multiple_kibana_nodes.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/multiple_kibana_nodes.test.ts @@ -106,8 +106,7 @@ async function createRoot({ logFileName }: CreateRootConfig) { // suite is very long, the 10mins default can cause timeouts jest.setTimeout(15 * 60 * 1000); -// FLAKY: https://github.com/elastic/kibana/issues/148263 -describe.skip('migration v2', () => { +describe('migration v2', () => { let esServer: TestElasticsearchUtils; let rootA: Root; let rootB: Root; diff --git a/src/plugins/dashboard/public/dashboard_app/listing/dashboard_listing.tsx b/src/plugins/dashboard/public/dashboard_app/listing/dashboard_listing.tsx index fb0281db9c8ba..d857e640c04da 100644 --- a/src/plugins/dashboard/public/dashboard_app/listing/dashboard_listing.tsx +++ b/src/plugins/dashboard/public/dashboard_app/listing/dashboard_listing.tsx @@ -25,7 +25,7 @@ import type { SavedObjectsFindOptionsReference, SimpleSavedObject } from '@kbn/c import { TableListView, type UserContentCommonSchema } from '@kbn/content-management-table-list'; import { reportPerformanceMetricEvent } from '@kbn/ebt-tools'; -import { SAVED_OBJECT_LOADED_TIME } from '../../dashboard_constants'; +import { SAVED_OBJECT_DELETE_TIME, SAVED_OBJECT_LOADED_TIME } from '../../dashboard_constants'; import { getDashboardBreadcrumb, @@ -292,7 +292,7 @@ export const DashboardListing = ({ eventName: SAVED_OBJECT_LOADED_TIME, duration: searchDuration, meta: { - saved_object_type: 'dashboard', + saved_object_type: DASHBOARD_SAVED_OBJECT_TYPE, }, }); return { @@ -306,16 +306,31 @@ export const DashboardListing = ({ const deleteItems = useCallback( async (dashboardsToDelete: Array<{ id: string }>) => { - await Promise.all( - dashboardsToDelete.map(({ id }) => { - dashboardSessionStorage.clearState(id); - return savedObjectsClient.delete(DASHBOARD_SAVED_OBJECT_TYPE, id); - }) - ).catch((error) => { + try { + const deleteStartTime = window.performance.now(); + + await Promise.all( + dashboardsToDelete.map(({ id }) => { + dashboardSessionStorage.clearState(id); + return savedObjectsClient.delete(DASHBOARD_SAVED_OBJECT_TYPE, id); + }) + ); + + const deleteDuration = window.performance.now() - deleteStartTime; + reportPerformanceMetricEvent(pluginServices.getServices().analytics, { + eventName: SAVED_OBJECT_DELETE_TIME, + duration: deleteDuration, + meta: { + saved_object_type: DASHBOARD_SAVED_OBJECT_TYPE, + total: dashboardsToDelete.length, + }, + }); + } catch (error) { toasts.addError(error, { title: dashboardListingErrorStrings.getErrorDeletingDashboardToast(), }); - }); + } + setUnsavedDashboardIds(dashboardSessionStorage.getDashboardIdsWithUnsavedChanges()); }, [savedObjectsClient, dashboardSessionStorage, toasts] diff --git a/src/plugins/dashboard/public/dashboard_constants.ts b/src/plugins/dashboard/public/dashboard_constants.ts index 0bad3dda9786a..9f8c45ad82d69 100644 --- a/src/plugins/dashboard/public/dashboard_constants.ts +++ b/src/plugins/dashboard/public/dashboard_constants.ts @@ -43,6 +43,7 @@ export function createDashboardListingFilterUrl(filter: string | undefined) { // ------------------------------------------------------------------ export const DASHBOARD_LOADED_EVENT = 'dashboard_loaded'; export const SAVED_OBJECT_LOADED_TIME = 'saved_object_loaded_time'; +export const SAVED_OBJECT_DELETE_TIME = 'saved_object_delete_time'; export const DASHBOARD_UI_METRIC_ID = 'dashboard'; // ------------------------------------------------------------------ diff --git a/src/plugins/data_view_field_editor/public/open_editor.tsx b/src/plugins/data_view_field_editor/public/open_editor.tsx index 6d3dbc6c3f4cd..a90d68cc5fb89 100644 --- a/src/plugins/data_view_field_editor/public/open_editor.tsx +++ b/src/plugins/data_view_field_editor/public/open_editor.tsx @@ -162,6 +162,7 @@ export const getFieldEditorOpener = // Runtime field field = { name: fieldNameToEdit!, + format: dataView.getFormatterForFieldNoDefault(fieldNameToEdit!)?.toJSON(), ...dataView.getRuntimeField(fieldNameToEdit!)!, }; } else { 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 51cdaadd1cda2..705299c1566d2 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 @@ -377,6 +377,7 @@ export function DiscoverSidebarComponent({ {...fieldListGroupedProps} renderFieldItem={renderFieldItem} screenReaderDescriptionId={fieldSearchDescriptionId} + localStorageKeyPrefix="discover" /> )} diff --git a/src/plugins/discover/public/components/field_name/__snapshots__/field_name.test.tsx.snap b/src/plugins/discover/public/components/field_name/__snapshots__/field_name.test.tsx.snap index b26160d9d33bc..21777f772c9a5 100644 --- a/src/plugins/discover/public/components/field_name/__snapshots__/field_name.test.tsx.snap +++ b/src/plugins/discover/public/components/field_name/__snapshots__/field_name.test.tsx.snap @@ -135,3 +135,76 @@ Array [ , ] `; + +exports[`FieldName renders when mapping is provided 1`] = ` +Array [ +
+ + + Number field + + +
, +
+
+ + + bytes + + +
+
, +] +`; + +exports[`FieldName renders with a search highlight 1`] = ` +Array [ +
+ + + Number field + + +
, +
+
+ + + + te + + st.test.test + + +
+
, +] +`; diff --git a/src/plugins/discover/public/components/field_name/field_name.test.tsx b/src/plugins/discover/public/components/field_name/field_name.test.tsx index d2f961392c43c..929ec2add2acc 100644 --- a/src/plugins/discover/public/components/field_name/field_name.test.tsx +++ b/src/plugins/discover/public/components/field_name/field_name.test.tsx @@ -8,26 +8,45 @@ import React from 'react'; import { render } from 'enzyme'; +import { stubLogstashDataView as dataView } from '@kbn/data-plugin/common/stubs'; import { FieldName } from './field_name'; -// Note that it currently provides just 2 basic tests, there should be more, but -// the components involved will soon change -test('FieldName renders a string field by providing fieldType and fieldName', () => { - const component = render(); - expect(component).toMatchSnapshot(); -}); +describe('FieldName', function () { + test('renders a string field by providing fieldType and fieldName', () => { + const component = render(); + expect(component).toMatchSnapshot(); + }); -test('FieldName renders a number field by providing a field record', () => { - const component = render(); - expect(component).toMatchSnapshot(); -}); + test('renders a number field by providing a field record', () => { + const component = render(); + expect(component).toMatchSnapshot(); + }); -test('FieldName renders a geo field', () => { - const component = render(); - expect(component).toMatchSnapshot(); -}); + test('renders a geo field', () => { + const component = render(); + expect(component).toMatchSnapshot(); + }); + + test('renders unknown field', () => { + const component = render(); + expect(component).toMatchSnapshot(); + }); + + test('renders with a search highlight', () => { + const component = render( + + ); + expect(component).toMatchSnapshot(); + }); -test('FieldName renders unknown field', () => { - const component = render(); - expect(component).toMatchSnapshot(); + test('renders when mapping is provided', () => { + const component = render( + + ); + expect(component).toMatchSnapshot(); + }); }); diff --git a/src/plugins/discover/public/components/field_name/field_name.tsx b/src/plugins/discover/public/components/field_name/field_name.tsx index 3de9bd129fa35..ca386d344e42f 100644 --- a/src/plugins/discover/public/components/field_name/field_name.tsx +++ b/src/plugins/discover/public/components/field_name/field_name.tsx @@ -8,7 +8,7 @@ import React, { Fragment } from 'react'; import './field_name.scss'; -import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; +import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiToolTip, EuiHighlight } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { FieldIcon, FieldIconProps } from '@kbn/react-field'; @@ -22,6 +22,7 @@ interface Props { fieldMapping?: DataViewField; fieldIconProps?: Omit; scripted?: boolean; + highlight?: string; } export function FieldName({ @@ -30,6 +31,7 @@ export function FieldName({ fieldType, fieldIconProps, scripted = false, + highlight = '', }: Props) { const typeName = getFieldTypeName(fieldType); const displayName = @@ -52,7 +54,7 @@ export function FieldName({ delay="long" anchorClassName="eui-textBreakAll" > - {displayName} + {displayName} diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx index 2a7b90a9feb52..0eab3a68c8218 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx +++ b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table.tsx @@ -241,7 +241,7 @@ export const DocViewerTable = ({ } else { const fieldMapping = mapping(curFieldName); const displayName = fieldMapping?.displayName ?? curFieldName; - if (displayName.includes(searchText)) { + if (displayName.toLowerCase().includes(searchText.toLowerCase())) { // filter only unpinned fields acc.restItems.push(fieldToItem(curFieldName)); } @@ -273,6 +273,7 @@ export const DocViewerTable = ({ const headers = [ !isSingleDocView && ( ), - + , - + @@ -305,10 +306,11 @@ export const DocViewerTable = ({ const renderRows = useCallback( (items: FieldRecord[]) => { + const highlight = searchText?.toLowerCase(); return items.map( ({ action: { flattenedField, onFilter }, - field: { field, fieldMapping, displayName, fieldType, scripted, pinned }, + field: { field, fieldMapping, fieldType, scripted, pinned }, value: { formattedValue, ignored }, }: FieldRecord) => { return ( @@ -344,10 +346,11 @@ export const DocViewerTable = ({ mobileOptions={MOBILE_OPTIONS} > & { attrPrefix?: string }): KueryNode { const kueryExpressions: KueryNode[] = [filterDeletedFiles({ attrPrefix })]; const addFilters = ( - fieldName: keyof FileMetadata, + fieldName: keyof FileMetadata | string, values: string[] = [], isWildcard = false ): void => { @@ -52,6 +54,8 @@ export function filterArgsToKuery({ addFilters('FileKind', kind); addFilters('Status', status); addFilters('extension', extension); + addFilters('mime_type', mimeType); + addFilters('user.id', user); if (meta) { const addMetaFilters = pipe( diff --git a/src/plugins/files/server/file_service/file_action_types.ts b/src/plugins/files/server/file_service/file_action_types.ts index ad8438fd691bb..c1264ed2b2452 100644 --- a/src/plugins/files/server/file_service/file_action_types.ts +++ b/src/plugins/files/server/file_service/file_action_types.ts @@ -90,10 +90,18 @@ export interface FindFileArgs extends Pagination { * File extension(s). */ extension?: string[]; + /** + * File mime type(s). + */ + mimeType?: string[]; /** * File status(es). */ status?: string[]; + /** + * ID of user who created the file. + */ + user?: string[]; /** * File metadata values. These values are governed by the consumer. */ diff --git a/src/plugins/files/server/integration_tests/file_service.test.ts b/src/plugins/files/server/integration_tests/file_service.test.ts index f31a5c53024ad..10aa11290a3e9 100644 --- a/src/plugins/files/server/integration_tests/file_service.test.ts +++ b/src/plugins/files/server/integration_tests/file_service.test.ts @@ -179,6 +179,58 @@ describe('FileService', () => { } }); + it('filters files by mime type', async () => { + await Promise.all([ + createDisposableFile({ fileKind, name: 'My pic', mime: 'image/png' }), + createDisposableFile({ fileKind, name: 'Vern payslip', mime: 'application/pdf' }), + ]); + + const result1 = await fileService.find({ + kind: [fileKind], + mimeType: ['image/png'], + }); + + expect(result1.files.length).toBe(1); + expect(result1.files[0].name).toBe('My pic'); + + const result2 = await fileService.find({ + kind: [fileKind], + mimeType: ['application/pdf'], + }); + + expect(result2.files.length).toBe(1); + expect(result2.files[0].name).toBe('Vern payslip'); + }); + + it('filters files by user ID', async () => { + await Promise.all([ + createDisposableFile({ fileKind, name: "Johnny's file", user: { id: '123' } }), + createDisposableFile({ fileKind, name: "Marry's file", user: { id: '456' } }), + ]); + + const result1 = await fileService.find({ + kind: [fileKind], + user: ['123'], + }); + + expect(result1.files.length).toBe(1); + expect(result1.files[0].name).toBe("Johnny's file"); + + const result2 = await fileService.find({ + kind: [fileKind], + user: ['456'], + }); + + expect(result2.files.length).toBe(1); + expect(result2.files[0].name).toBe("Marry's file"); + + const result3 = await fileService.find({ + user: ['456', '123'], + }); + + expect(result3.files.length).toBe(2); + }); + it('deletes files', async () => { const file = await fileService.create({ fileKind, name: 'test' }); const result = await fileService.find({ kind: [fileKind] }); diff --git a/src/plugins/home/public/application/components/guided_onboarding/getting_started.tsx b/src/plugins/home/public/application/components/guided_onboarding/getting_started.tsx index f7ebcbc42b88b..2af90e9be5edb 100644 --- a/src/plugins/home/public/application/components/guided_onboarding/getting_started.tsx +++ b/src/plugins/home/public/application/components/guided_onboarding/getting_started.tsx @@ -95,16 +95,18 @@ export const GettingStarted = () => { } }, [cloud, history]); + useEffect(() => { + // disable welcome screen on the home page + localStorage.setItem(KEY_ENABLE_WELCOME, JSON.stringify(false)); + }, []); + const onSkip = async () => { try { await guidedOnboardingService?.skipGuidedOnboarding(); } catch (error) { // if the state update fails, it's safe to ignore the error } - trackUiMetric(METRIC_TYPE.CLICK, 'guided_onboarding__skipped'); - // disable welcome screen on the home page - localStorage.setItem(KEY_ENABLE_WELCOME, JSON.stringify(false)); application.navigateToApp('home'); }; const { euiTheme } = useEuiTheme(); diff --git a/src/plugins/image_embeddable/kibana.json b/src/plugins/image_embeddable/kibana.json index ba79a2158425a..aa10754d5e9a6 100644 --- a/src/plugins/image_embeddable/kibana.json +++ b/src/plugins/image_embeddable/kibana.json @@ -8,6 +8,6 @@ "githubTeam": "@elastic/kibana-global-experience" }, "description": "Image embeddable", - "requiredPlugins": ["embeddable", "files"], + "requiredPlugins": ["embeddable", "files", "uiActions"], "requiredBundles": ["kibanaUtils", "kibanaReact"] } diff --git a/src/plugins/image_embeddable/public/actions/image_click_trigger.ts b/src/plugins/image_embeddable/public/actions/image_click_trigger.ts new file mode 100644 index 0000000000000..f97a80b6d89d5 --- /dev/null +++ b/src/plugins/image_embeddable/public/actions/image_click_trigger.ts @@ -0,0 +1,27 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import type { Trigger } from '@kbn/ui-actions-plugin/public'; +import type { ImageEmbeddable } from '../image_embeddable'; + +export const IMAGE_CLICK_TRIGGER = 'IMAGE_CLICK_TRIGGER'; + +export const imageClickTrigger: Trigger = { + id: IMAGE_CLICK_TRIGGER, + title: i18n.translate('imageEmbeddable.triggers.imageClickTriggerTitle', { + defaultMessage: 'Image click', + }), + description: i18n.translate('imageEmbeddable.triggers.imageClickDescription', { + defaultMessage: 'Clicking the image will trigger the action', + }), +}; + +export interface ImageClickContext { + embeddable: ImageEmbeddable; +} diff --git a/src/plugins/image_embeddable/public/actions/index.ts b/src/plugins/image_embeddable/public/actions/index.ts new file mode 100644 index 0000000000000..3a8e660c00d98 --- /dev/null +++ b/src/plugins/image_embeddable/public/actions/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './image_click_trigger'; diff --git a/src/plugins/image_embeddable/public/image_embeddable/image_embeddable.scss b/src/plugins/image_embeddable/public/image_embeddable/image_embeddable.scss new file mode 100644 index 0000000000000..8e849b721579e --- /dev/null +++ b/src/plugins/image_embeddable/public/image_embeddable/image_embeddable.scss @@ -0,0 +1,8 @@ +// By default dashboards' react-grid disables all pointer events for tags. +// We want to revert this behaviour for image embeddable images as they may be interactive. +// We also don't want to block a native context menu on images. +/* stylelint-disable-next-line selector-no-qualifying-type */ +.react-grid-item img.imageEmbeddableImage { + user-select: initial; + pointer-events: initial; +} diff --git a/src/plugins/image_embeddable/public/image_embeddable/image_embeddable.tsx b/src/plugins/image_embeddable/public/image_embeddable/image_embeddable.tsx index bf5c90e9721e3..c55ebdb6ebcaa 100644 --- a/src/plugins/image_embeddable/public/image_embeddable/image_embeddable.tsx +++ b/src/plugins/image_embeddable/public/image_embeddable/image_embeddable.tsx @@ -12,16 +12,25 @@ import { Embeddable, IContainer } from '@kbn/embeddable-plugin/public'; import { ImageEmbeddableInput } from './image_embeddable_factory'; import { ImageViewer, ImageViewerContext } from '../image_viewer'; import { createValidateUrl } from '../utils/validate_url'; +import { imageClickTrigger, ImageClickContext } from '../actions'; export const IMAGE_EMBEDDABLE_TYPE = 'image'; export class ImageEmbeddable extends Embeddable { public readonly type = IMAGE_EMBEDDABLE_TYPE; + supportedTriggers(): string[] { + return [imageClickTrigger.id]; + } + constructor( private deps: { getImageDownloadHref: (fileId: string) => string; validateUrl: ReturnType; + actions: { + executeTriggerActions: (triggerId: string, context: ImageClickContext) => void; + hasTriggerActions: (triggerId: string, context: ImageClickContext) => Promise; + }; }, initialInput: ImageEmbeddableInput, parent?: IContainer @@ -48,6 +57,27 @@ export class ImageEmbeddable extends Embeddable { private ImageEmbeddableViewer = (props: { embeddable: ImageEmbeddable }) => { const input = useObservable(props.embeddable.getInput$(), props.embeddable.getInput()); + React.useLayoutEffect(() => { + import('./image_embeddable_lazy'); + }, []); + + const [hasTriggerActions, setHasTriggerActions] = React.useState(false); + React.useEffect(() => { + let cancel = false; + + // hack: timeout to give a chance for a drilldown action to be registered just after it is created by user + setTimeout(() => { + if (cancel) return; + this.deps.actions + .hasTriggerActions(imageClickTrigger.id, { embeddable: this }) + .catch(() => false) + .then((hasActions) => !cancel && setHasTriggerActions(hasActions)); + }, 0); + return () => { + cancel = true; + }; + }); + return ( { }} > { this.renderComplete.dispatchComplete(); @@ -63,6 +94,16 @@ export class ImageEmbeddable extends Embeddable { onError={() => { this.renderComplete.dispatchError(); }} + onClick={ + // note: passing onClick enables the cursor pointer style, so we only pass it if there are compatible actions + hasTriggerActions + ? () => { + this.deps.actions.executeTriggerActions(imageClickTrigger.id, { + embeddable: this, + }); + } + : undefined + } /> ); diff --git a/src/plugins/image_embeddable/public/image_embeddable/image_embeddable_factory.tsx b/src/plugins/image_embeddable/public/image_embeddable/image_embeddable_factory.tsx index 4806c41422c21..1348cbd52c1ea 100644 --- a/src/plugins/image_embeddable/public/image_embeddable/image_embeddable_factory.tsx +++ b/src/plugins/image_embeddable/public/image_embeddable/image_embeddable_factory.tsx @@ -18,10 +18,12 @@ import { FileImageMetadata, imageEmbeddableFileKind, ThemeServiceStart, + UiActionsStart, } from '../imports'; import { ImageEmbeddable, IMAGE_EMBEDDABLE_TYPE } from './image_embeddable'; import { ImageConfig } from '../types'; import { createValidateUrl } from '../utils/validate_url'; +import { ImageClickContext } from '../actions'; export interface ImageEmbeddableFactoryDeps { start: () => { @@ -30,6 +32,7 @@ export interface ImageEmbeddableFactoryDeps { files: FilesClient; externalUrl: IExternalUrl; theme: ThemeServiceStart; + uiActions: UiActionsStart; }; } @@ -53,6 +56,16 @@ export class ImageEmbeddableFactoryDefinition { getImageDownloadHref: this.getImageDownloadHref, validateUrl: createValidateUrl(this.deps.start().externalUrl), + actions: { + executeTriggerActions: (triggerId: string, context: ImageClickContext) => + this.deps.start().uiActions.executeTriggerActions(triggerId, context), + hasTriggerActions: (triggerId: string, context: ImageClickContext) => + this.deps + .start() + .uiActions.getTriggerCompatibleActions(triggerId, context) + .catch(() => []) + .then((actions) => actions.length > 0), + }, }, initialInput, parent diff --git a/src/plugins/image_embeddable/public/image_embeddable/image_embeddable_lazy.tsx b/src/plugins/image_embeddable/public/image_embeddable/image_embeddable_lazy.tsx new file mode 100644 index 0000000000000..238e7961a8aaa --- /dev/null +++ b/src/plugins/image_embeddable/public/image_embeddable/image_embeddable_lazy.tsx @@ -0,0 +1,9 @@ +/* + * 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 './image_embeddable.scss'; diff --git a/src/plugins/image_embeddable/public/image_viewer/image_viewer.tsx b/src/plugins/image_embeddable/public/image_viewer/image_viewer.tsx index 4ee6b0d6d9364..9cebe1d21d179 100644 --- a/src/plugins/image_embeddable/public/image_viewer/image_viewer.tsx +++ b/src/plugins/image_embeddable/public/image_viewer/image_viewer.tsx @@ -34,6 +34,7 @@ export interface ImageViewerProps { onClear?: () => void; onError?: () => void; onLoad?: () => void; + onClick?: () => void; containerCSS?: SerializedStyles; } @@ -43,6 +44,7 @@ export function ImageViewer({ onClear, onError, onLoad, + onClick, className, containerCSS, }: ImageViewerProps) { @@ -87,12 +89,18 @@ export function ImageViewer({ // meta={imageConfig.src.type === 'file' ? imageConfig.src.fileImageMeta : undefined} alt={imageConfig.altText ?? ''} className={classNames(className, { 'visually-hidden': hasFailedToLoad })} - title={onChange ? 'Click to select a different image' : undefined} + title={ + onChange + ? i18n.translate('imageEmbeddable.imageViewer.selectDifferentImageTitle', { + defaultMessage: 'Select a different image', + }) + : undefined + } style={{ width: '100%', height: '100%', objectFit: imageConfig?.sizing?.objectFit ?? 'contain', - cursor: onChange ? 'pointer' : 'initial', + cursor: onChange || onClick ? 'pointer' : 'initial', display: 'block', // needed to remove gap under the image backgroundColor: imageConfig.backgroundColor, }} @@ -101,6 +109,7 @@ export function ImageViewer({ }} onClick={() => { if (onChange) onChange(); + if (onClick) onClick(); }} onLoad={() => { if (onLoad) onLoad(); diff --git a/src/plugins/image_embeddable/public/imports.ts b/src/plugins/image_embeddable/public/imports.ts index 5f3c04044acba..59acef5e42633 100644 --- a/src/plugins/image_embeddable/public/imports.ts +++ b/src/plugins/image_embeddable/public/imports.ts @@ -25,4 +25,6 @@ export type { } from '@kbn/embeddable-plugin/public'; export type { ApplicationStart, OverlayStart, ThemeServiceStart } from '@kbn/core/public'; +export type { UiActionsStart, UiActionsSetup } from '@kbn/ui-actions-plugin/public'; + export const imageEmbeddableFileKind: FileKind = defaultImageFileKind; diff --git a/src/plugins/image_embeddable/public/index.ts b/src/plugins/image_embeddable/public/index.ts index 364face9a52e5..98502954ffd40 100644 --- a/src/plugins/image_embeddable/public/index.ts +++ b/src/plugins/image_embeddable/public/index.ts @@ -9,6 +9,8 @@ import { PluginInitializerContext } from '@kbn/core/public'; import { ImageEmbeddablePlugin } from './plugin'; +export { type ImageClickContext, IMAGE_CLICK_TRIGGER } from './actions'; + export function plugin(context: PluginInitializerContext) { return new ImageEmbeddablePlugin(context); } diff --git a/src/plugins/image_embeddable/public/plugin.ts b/src/plugins/image_embeddable/public/plugin.ts index 9e14dcb91e20b..debfb5e44da2c 100644 --- a/src/plugins/image_embeddable/public/plugin.ts +++ b/src/plugins/image_embeddable/public/plugin.ts @@ -10,16 +10,20 @@ import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/cor import { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public'; import { createStartServicesGetter } from '@kbn/kibana-utils-plugin/public'; import { FilesSetup, FilesStart } from '@kbn/files-plugin/public'; +import { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public'; import { IMAGE_EMBEDDABLE_TYPE, ImageEmbeddableFactoryDefinition } from './image_embeddable'; +import { imageClickTrigger } from './actions'; export interface SetupDependencies { embeddable: EmbeddableSetup; files: FilesSetup; + uiActions: UiActionsSetup; } export interface StartDependencies { embeddable: EmbeddableStart; files: FilesStart; + uiActions: UiActionsStart; } // eslint-disable-next-line @typescript-eslint/no-empty-interface @@ -44,9 +48,12 @@ export class ImageEmbeddablePlugin files: start().plugins.files.filesClientFactory.asUnscoped(), externalUrl: start().core.http.externalUrl, theme: start().core.theme, + uiActions: start().plugins.uiActions, }), }) ); + + plugins.uiActions.registerTrigger(imageClickTrigger); return {}; } diff --git a/src/plugins/image_embeddable/tsconfig.json b/src/plugins/image_embeddable/tsconfig.json index 4d1ba66af6c02..1b7927abf086b 100644 --- a/src/plugins/image_embeddable/tsconfig.json +++ b/src/plugins/image_embeddable/tsconfig.json @@ -19,6 +19,7 @@ "@kbn/i18n", "@kbn/core-http-browser", "@kbn/shared-ux-file-image", + "@kbn/ui-actions-plugin" ], "exclude": [ "target/**/*", diff --git a/src/plugins/kibana_react/public/markdown/_markdown.scss b/src/plugins/kibana_react/public/markdown/_markdown.scss index 3c9b1cd165bab..c11aefe1f4d97 100644 --- a/src/plugins/kibana_react/public/markdown/_markdown.scss +++ b/src/plugins/kibana_react/public/markdown/_markdown.scss @@ -143,6 +143,7 @@ $kbnDefaultFontSize: 14px; max-width: 100%; box-sizing: content-box; border-style: none; + pointer-events: auto; } // 4. Blockquotes diff --git a/src/plugins/unified_field_list/common/utils/__snapshots__/field_stats_utils.test.ts.snap b/src/plugins/unified_field_list/common/utils/__snapshots__/field_stats_utils.test.ts.snap new file mode 100644 index 0000000000000..4cd6bdc44ae7f --- /dev/null +++ b/src/plugins/unified_field_list/common/utils/__snapshots__/field_stats_utils.test.ts.snap @@ -0,0 +1,184 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`fieldStatsUtils buildSearchParams() should work correctly for aggregations and a data view time field 1`] = ` +Object { + "body": Object { + "_source": undefined, + "aggs": Object { + "sample": Object { + "aggs": Object { + "sample_count": Object { + "value_count": Object { + "field": "extension.keyword", + }, + }, + "top_values": Object { + "terms": Object { + "field": "extension.keyword", + "shard_size": 25, + "size": 10, + }, + }, + }, + "sampler": Object { + "shard_size": 5000, + }, + }, + }, + "fields": undefined, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "timestamp": Object { + "format": "strict_date_optional_time", + "gte": "2022-12-05T23:00:00.000Z", + "lte": "2023-01-05T09:33:05.359Z", + }, + }, + }, + Object { + "bool": Object { + "filter": Array [ + Object { + "match_phrase": Object { + "geo.src": "US", + }, + }, + ], + "must": Array [], + "must_not": Array [], + "should": Array [], + }, + }, + ], + }, + }, + "runtime_mappings": Object { + "hour_of_day": Object { + "script": Object { + "source": "emit(doc['timestamp'].value.getHour());", + }, + "type": "long", + }, + }, + }, + "index": "kibana_sample_data_logs", + "size": 0, + "track_total_hits": true, +} +`; + +exports[`fieldStatsUtils buildSearchParams() should work correctly for aggregations without a data view time field 1`] = ` +Object { + "body": Object { + "_source": undefined, + "aggs": Object { + "sample": Object { + "aggs": Object { + "sample_count": Object { + "value_count": Object { + "field": "extension.keyword", + }, + }, + "top_values": Object { + "terms": Object { + "field": "extension.keyword", + "shard_size": 25, + "size": 10, + }, + }, + }, + "sampler": Object { + "shard_size": 5000, + }, + }, + }, + "fields": undefined, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "filter": Array [ + Object { + "match_phrase": Object { + "geo.src": "US", + }, + }, + ], + "must": Array [], + "must_not": Array [], + "should": Array [], + }, + }, + ], + }, + }, + "runtime_mappings": Object {}, + }, + "index": "kibana_sample*", + "size": 0, + "track_total_hits": true, +} +`; + +exports[`fieldStatsUtils buildSearchParams() should work correctly for fetching field examples 1`] = ` +Object { + "body": Object { + "_source": false, + "aggs": undefined, + "fields": Array [ + Object { + "field": "_id", + }, + ], + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "timestamp": Object { + "format": "strict_date_optional_time", + "gte": "2022-12-05T23:00:00.000Z", + "lte": "2023-01-05T09:35:24.109Z", + }, + }, + }, + Object { + "bool": Object { + "filter": Array [ + Object { + "match_phrase": Object { + "geo.src": "US", + }, + }, + ], + "must": Array [], + "must_not": Array [], + "should": Array [], + }, + }, + Object { + "exists": Object { + "field": "_id", + }, + }, + ], + }, + }, + "runtime_mappings": Object { + "hour_of_day": Object { + "script": Object { + "source": "emit(doc['timestamp'].value.getHour());", + }, + "type": "long", + }, + }, + }, + "index": "kibana_sample_data_logs", + "size": 100, + "track_total_hits": true, +} +`; diff --git a/src/plugins/unified_field_list/common/utils/field_stats_utils.test.ts b/src/plugins/unified_field_list/common/utils/field_stats_utils.test.ts new file mode 100644 index 0000000000000..1135f028f1702 --- /dev/null +++ b/src/plugins/unified_field_list/common/utils/field_stats_utils.test.ts @@ -0,0 +1,153 @@ +/* + * 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 { buildSearchParams } from './field_stats_utils'; + +describe('fieldStatsUtils', function () { + describe('buildSearchParams()', () => { + it('should work correctly for aggregations and a data view time field', () => { + expect( + buildSearchParams({ + dataViewPattern: 'kibana_sample_data_logs', + timeFieldName: 'timestamp', + fromDate: '2022-12-05T23:00:00.000Z', + toDate: '2023-01-05T09:33:05.359Z', + dslQuery: { + bool: { + must: [], + filter: [ + { + match_phrase: { + 'geo.src': 'US', + }, + }, + ], + should: [], + must_not: [], + }, + }, + runtimeMappings: { + hour_of_day: { + type: 'long', + script: { + source: "emit(doc['timestamp'].value.getHour());", + }, + }, + }, + aggs: { + sample: { + sampler: { + shard_size: 5000, + }, + aggs: { + sample_count: { + value_count: { + field: 'extension.keyword', + }, + }, + top_values: { + terms: { + field: 'extension.keyword', + size: 10, + shard_size: 25, + }, + }, + }, + }, + }, + }) + ).toMatchSnapshot(); + }); + + it('should work correctly for aggregations without a data view time field', () => { + expect( + buildSearchParams({ + dataViewPattern: 'kibana_sample*', + timeFieldName: '', + fromDate: '2022-12-05T23:00:00.000Z', + toDate: '2023-01-05T09:33:53.717Z', + dslQuery: { + bool: { + must: [], + filter: [ + { + match_phrase: { + 'geo.src': 'US', + }, + }, + ], + should: [], + must_not: [], + }, + }, + runtimeMappings: {}, + aggs: { + sample: { + sampler: { + shard_size: 5000, + }, + aggs: { + sample_count: { + value_count: { + field: 'extension.keyword', + }, + }, + top_values: { + terms: { + field: 'extension.keyword', + size: 10, + shard_size: 25, + }, + }, + }, + }, + }, + }) + ).toMatchSnapshot(); + }); + + it('should work correctly for fetching field examples', () => { + expect( + buildSearchParams({ + dataViewPattern: 'kibana_sample_data_logs', + timeFieldName: 'timestamp', + fromDate: '2022-12-05T23:00:00.000Z', + toDate: '2023-01-05T09:35:24.109Z', + dslQuery: { + bool: { + must: [], + filter: [ + { + match_phrase: { + 'geo.src': 'US', + }, + }, + ], + should: [], + must_not: [], + }, + }, + runtimeMappings: { + hour_of_day: { + type: 'long', + script: { + source: "emit(doc['timestamp'].value.getHour());", + }, + }, + }, + fields: [ + { + field: '_id', + }, + ], + size: 100, + }) + ).toMatchSnapshot(); + }); + }); +}); diff --git a/src/plugins/unified_field_list/common/utils/field_stats_utils.ts b/src/plugins/unified_field_list/common/utils/field_stats_utils.ts index 89bf8a44139cf..9fac4c04946c9 100644 --- a/src/plugins/unified_field_list/common/utils/field_stats_utils.ts +++ b/src/plugins/unified_field_list/common/utils/field_stats_utils.ts @@ -55,6 +55,7 @@ export function buildSearchParams({ [timeFieldName]: { gte: fromDate, lte: toDate, + format: 'strict_date_optional_time', }, }, }, diff --git a/src/plugins/unified_field_list/public/components/field_list_grouped/field_list_grouped.test.tsx b/src/plugins/unified_field_list/public/components/field_list_grouped/field_list_grouped.test.tsx index 778f38168e6c1..9190c6de2859e 100644 --- a/src/plugins/unified_field_list/public/components/field_list_grouped/field_list_grouped.test.tsx +++ b/src/plugins/unified_field_list/public/components/field_list_grouped/field_list_grouped.test.tsx @@ -431,4 +431,54 @@ describe('UnifiedFieldList + useGroupedFields()', () => { '2 selected fields. 10 popular fields. 25 available fields. 112 unmapped fields. 0 empty fields. 3 meta fields.' ); }); + + it('persists sections state in local storage', async () => { + const wrapper = await mountGroupedList({ + listProps: { + ...defaultProps, + fieldsExistenceStatus: ExistenceFetchStatus.succeeded, + localStorageKeyPrefix: 'test', + }, + hookParams: { + dataViewId: dataView.id!, + allFields: manyFields, + }, + }); + + // only Available is open + expect( + wrapper.find(FieldsAccordion).map((accordion) => accordion.prop('initialIsOpen')) + ).toStrictEqual([true, false, false, false]); + + await act(async () => { + await wrapper + .find('[data-test-subj="fieldListGroupedEmptyFields"]') + .find('button') + .first() + .simulate('click'); + await wrapper.update(); + }); + + // now Empty is open too + expect( + wrapper.find(FieldsAccordion).map((accordion) => accordion.prop('initialIsOpen')) + ).toStrictEqual([true, false, true, false]); + + const wrapper2 = await mountGroupedList({ + listProps: { + ...defaultProps, + fieldsExistenceStatus: ExistenceFetchStatus.succeeded, + localStorageKeyPrefix: 'test', + }, + hookParams: { + dataViewId: dataView.id!, + allFields: manyFields, + }, + }); + + // both Available and Empty are open for the second instance + expect( + wrapper2.find(FieldsAccordion).map((accordion) => accordion.prop('initialIsOpen')) + ).toStrictEqual([true, false, true, false]); + }); }); diff --git a/src/plugins/unified_field_list/public/components/field_list_grouped/field_list_grouped.tsx b/src/plugins/unified_field_list/public/components/field_list_grouped/field_list_grouped.tsx index 9e81cb8c5d476..1bc84a37ed7e0 100644 --- a/src/plugins/unified_field_list/public/components/field_list_grouped/field_list_grouped.tsx +++ b/src/plugins/unified_field_list/public/components/field_list_grouped/field_list_grouped.tsx @@ -8,6 +8,7 @@ import { partition, throttle } from 'lodash'; import React, { Fragment, useCallback, useEffect, useMemo, useState } from 'react'; +import useLocalStorage from 'react-use/lib/useLocalStorage'; import { i18n } from '@kbn/i18n'; import { EuiScreenReaderOnly, EuiSpacer } from '@elastic/eui'; import { type DataViewField } from '@kbn/data-views-plugin/common'; @@ -18,10 +19,13 @@ import { ExistenceFetchStatus, FieldsGroup, FieldsGroupNames } from '../../types import './field_list_grouped.scss'; const PAGINATION_SIZE = 50; +export const LOCAL_STORAGE_KEY_SECTIONS = 'unifiedFieldList.initiallyOpenSections'; + +type InitiallyOpenSections = Record; function getDisplayedFieldsLength( fieldGroups: FieldListGroups, - accordionState: Partial> + accordionState: InitiallyOpenSections ) { return Object.entries(fieldGroups) .filter(([key]) => accordionState[key]) @@ -35,6 +39,7 @@ export interface FieldListGroupedProps { renderFieldItem: FieldsAccordionProps['renderFieldItem']; scrollToTopResetCounter: number; screenReaderDescriptionId?: string; + localStorageKeyPrefix?: string; // Your app name: "discover", "lens", etc. If not provided, sections state would not be persisted. 'data-test-subj'?: string; } @@ -45,6 +50,7 @@ function InnerFieldListGrouped({ renderFieldItem, scrollToTopResetCounter, screenReaderDescriptionId, + localStorageKeyPrefix, 'data-test-subj': dataTestSubject = 'fieldListGrouped', }: FieldListGroupedProps) { const hasSyncedExistingFields = @@ -56,9 +62,22 @@ function InnerFieldListGrouped({ ); const [pageSize, setPageSize] = useState(PAGINATION_SIZE); const [scrollContainer, setScrollContainer] = useState(undefined); - const [accordionState, setAccordionState] = useState>>(() => + const [storedInitiallyOpenSections, storeInitiallyOpenSections] = + useLocalStorage( + `${localStorageKeyPrefix ? localStorageKeyPrefix + '.' : ''}${LOCAL_STORAGE_KEY_SECTIONS}`, + {} + ); + const [accordionState, setAccordionState] = useState(() => Object.fromEntries( - fieldGroupsToShow.map(([key, { isInitiallyOpen }]) => [key, isInitiallyOpen]) + fieldGroupsToShow.map(([key, { isInitiallyOpen }]) => { + const storedInitiallyOpen = localStorageKeyPrefix + ? storedInitiallyOpenSections?.[key] + : null; // from localStorage + return [ + key, + typeof storedInitiallyOpen === 'boolean' ? storedInitiallyOpen : isInitiallyOpen, + ]; + }) ) ); @@ -256,6 +275,12 @@ function InnerFieldListGrouped({ Math.min(Math.ceil(pageSize * 1.5), displayedFieldLength) ) ); + if (localStorageKeyPrefix) { + storeInitiallyOpenSections({ + ...storedInitiallyOpenSections, + [key]: open, + }); + } }} showExistenceFetchError={fieldsExistenceStatus === ExistenceFetchStatus.failed} showExistenceFetchTimeout={fieldsExistenceStatus === ExistenceFetchStatus.failed} // TODO: deprecate timeout logic? diff --git a/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx b/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx index bfc5aa5b92f14..a7f473f95b374 100644 --- a/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx +++ b/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx @@ -218,11 +218,11 @@ export function ChangeDataView({ ) : ( ), - + ); } panelItems.push( - <> + {onDataViewCreated && ( - + ); if (textBasedLanguages?.length) { panelItems.push( - , + , + key="textbasedLanguages-options" data-test-subj="text-based-languages-switcher" singleSelection="always" options={textBasedLanguages.map((lang) => ({ diff --git a/test/functional/apps/dashboard_elements/image_embeddable/image_embeddable.ts b/test/functional/apps/dashboard_elements/image_embeddable/image_embeddable.ts index 2f9aa81fe1eb3..de2d962ae854d 100644 --- a/test/functional/apps/dashboard_elements/image_embeddable/image_embeddable.ts +++ b/test/functional/apps/dashboard_elements/image_embeddable/image_embeddable.ts @@ -10,9 +10,14 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { - const PageObjects = getPageObjects(['common', 'dashboard']); + const PageObjects = getPageObjects(['common', 'dashboard', 'discover', 'header']); const testSubjects = getService('testSubjects'); const kibanaServer = getService('kibanaServer'); + const retry = getService('retry'); + + const dashboardPanelActions = getService('dashboardPanelActions'); + const dashboardDrilldownPanelActions = getService('dashboardDrilldownPanelActions'); + const dashboardDrilldownsManage = getService('dashboardDrilldownsManage'); describe('image embeddable', function () { before(async () => { @@ -44,5 +49,37 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const imgSrc = await img.getAttribute('src'); expect(imgSrc).to.contain(`files/defaultImage`); }); + + it('image embeddable should support drilldowns', async () => { + await dashboardPanelActions.openContextMenu(); + await dashboardDrilldownPanelActions.expectExistsCreateDrilldownAction(); + await dashboardDrilldownPanelActions.clickCreateDrilldown(); + await dashboardDrilldownsManage.expectsCreateDrilldownFlyoutOpen(); + + await testSubjects.click('actionFactoryItem-DASHBOARD_TO_DASHBOARD_DRILLDOWN'); + await dashboardDrilldownsManage.fillInDashboardToDashboardDrilldownWizard({ + drilldownName: `My drilldown`, + destinationDashboardTitle: `few panels`, + }); + + await dashboardDrilldownsManage.saveChanges(); + await dashboardDrilldownsManage.closeFlyout(); + + expect(await PageObjects.dashboard.getPanelDrilldownCount()).to.be(1); + + const panel = (await PageObjects.dashboard.getDashboardPanels())[0]; + const img = await panel.findByCssSelector('img.euiImage'); + + const oldDashboardId = await PageObjects.dashboard.getDashboardIdFromCurrentUrl(); + + await img.click(); + + await retry.waitFor('navigate to different dashboard', async () => { + const newDashboardId = await PageObjects.dashboard.getDashboardIdFromCurrentUrl(); + return typeof newDashboardId === 'string' && oldDashboardId !== newDashboardId; + }); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + }); }); } diff --git a/test/functional/apps/discover/group1/_sidebar.ts b/test/functional/apps/discover/group1/_sidebar.ts index 09190a0a39702..a62a379c20224 100644 --- a/test/functional/apps/discover/group1/_sidebar.ts +++ b/test/functional/apps/discover/group1/_sidebar.ts @@ -26,8 +26,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const filterBar = getService('filterBar'); const fieldEditor = getService('fieldEditor'); - // Failing: See https://github.com/elastic/kibana/issues/147687 - describe.skip('discover sidebar', function describeIndexTests() { + describe('discover sidebar', function describeIndexTests() { before(async function () { await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); }); @@ -46,6 +45,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover'); await kibanaServer.savedObjects.cleanStandardList(); await kibanaServer.uiSettings.replace({}); + await PageObjects.discover.cleanSidebarLocalStorage(); }); describe('field filtering', function () { @@ -541,6 +541,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.existOrFail('discoverNoResultsError'); // still has error // check that the sidebar is rendered event after a refresh + await PageObjects.discover.waitUntilSidebarHasLoaded(); allFields = await PageObjects.discover.getAllFieldNames(); expect(allFields.includes('_invalid-runtimefield')).to.be(true); diff --git a/test/functional/apps/home/_breadcrumbs.ts b/test/functional/apps/home/_breadcrumbs.ts index 1463e828ea0c5..06784fdec237d 100644 --- a/test/functional/apps/home/_breadcrumbs.ts +++ b/test/functional/apps/home/_breadcrumbs.ts @@ -24,23 +24,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(breadcrumb).to.be('Home'); }); - it('Getting started page should render breadcrumbs', async () => { - const isCloud = await deployment.isCloud(); - - if (isCloud) { - await PageObjects.common.navigateToUrl('home', '/getting_started', { - useActualUrl: true, - }); - await PageObjects.header.waitUntilLoadingHasFinished(); - - const firstBreadcrumb = await testSubjects.getVisibleText('breadcrumb first'); - const lastBreadcrumb = await testSubjects.getVisibleText('breadcrumb last'); - - expect(firstBreadcrumb).to.be('Home'); - expect(lastBreadcrumb).to.be('Setup guides'); - } - }); - it('Tutorials directory page should render breadcrumbs', async () => { await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', { useActualUrl: true, @@ -68,5 +51,40 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(firstBreadcrumb).to.be('Integrations'); expect(lastBreadcrumb).to.be(tutorialId.toUpperCase()); }); + + // The getting started page is only rendered on cloud, and therefore the tests are only run on cloud + describe('Getting started page', () => { + let isCloud: boolean; + + before(async () => { + isCloud = await deployment.isCloud(); + }); + + beforeEach(async () => { + if (isCloud) { + await PageObjects.common.navigateToUrl('home', '/getting_started', { + useActualUrl: true, + }); + await PageObjects.header.waitUntilLoadingHasFinished(); + } + }); + + it('Getting started page should render breadcrumbs', async () => { + if (isCloud) { + const firstBreadcrumb = await testSubjects.getVisibleText('breadcrumb first'); + const lastBreadcrumb = await testSubjects.getVisibleText('breadcrumb last'); + + expect(firstBreadcrumb).to.be('Home'); + expect(lastBreadcrumb).to.be('Setup guides'); + } + }); + + it('Home page breadcrumb should navigate to home', async () => { + if (isCloud) { + await PageObjects.home.clickHomeBreadcrumb(); + expect(await PageObjects.home.isHomePageDisplayed()).to.be(true); + } + }); + }); }); } diff --git a/test/functional/apps/management/_runtime_fields.ts b/test/functional/apps/management/_runtime_fields.ts index ee8928562cce8..913536200f7d2 100644 --- a/test/functional/apps/management/_runtime_fields.ts +++ b/test/functional/apps/management/_runtime_fields.ts @@ -63,11 +63,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.click('editFieldFormat'); await PageObjects.settings.setFieldType('Long'); await PageObjects.settings.setFieldScriptWithoutToggle('emit(6);'); + await PageObjects.settings.toggleRow('formatRow'); + await PageObjects.settings.setFieldFormat('bytes'); await testSubjects.find('changeWarning'); await PageObjects.settings.clickSaveField(); await PageObjects.settings.confirmSave(); }); + it('verify field format', async function () { + await testSubjects.click('editFieldFormat'); + const select = await testSubjects.find('editorSelectedFormatId'); + expect(await select.getAttribute('value')).to.be('bytes'); + await PageObjects.settings.closeIndexPatternFieldEditor(); + }); + it('should delete runtime field', async function () { await testSubjects.click('deleteField'); await PageObjects.settings.confirmDelete(); diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index b9be3c673448d..7db95f8063c12 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -463,6 +463,10 @@ export class DiscoverPageObject extends FtrService { ).getAttribute('innerText'); } + public async cleanSidebarLocalStorage(): Promise { + await this.browser.setLocalStorageItem('discover.unifiedFieldList.initiallyOpenSections', '{}'); + } + public async waitUntilSidebarHasLoaded() { await this.retry.waitFor('sidebar is loaded', async () => { return (await this.getSidebarAriaDescription()).length > 0; diff --git a/test/functional/page_objects/home_page.ts b/test/functional/page_objects/home_page.ts index e3e14645f2b9a..a6a5e2e6bc9ea 100644 --- a/test/functional/page_objects/home_page.ts +++ b/test/functional/page_objects/home_page.ts @@ -60,6 +60,10 @@ export class HomePageObject extends FtrService { return await this.testSubjects.isDisplayed('onboarding--landing-page'); } + async isHomePageDisplayed() { + return await this.testSubjects.isDisplayed('homeApp'); + } + async getVisibileSolutions() { const solutionPanels = await this.testSubjects.findAll('~homSolutionPanel', 2000); const panelAttributes = await Promise.all( @@ -212,6 +216,10 @@ export class HomePageObject extends FtrService { await this.testSubjects.click('homeLink'); } + async clickHomeBreadcrumb() { + await this.testSubjects.click('breadcrumb first'); + } + // open global nav if it's closed async openCollapsibleNav() { if (!(await this.testSubjects.exists('collapsibleNav'))) { diff --git a/x-pack/test/functional/services/dashboard/drilldowns_manage.ts b/test/functional/services/dashboard/drilldowns_manage.ts similarity index 92% rename from x-pack/test/functional/services/dashboard/drilldowns_manage.ts rename to test/functional/services/dashboard/drilldowns_manage.ts index 440c29bf2276e..afd1f635067e1 100644 --- a/x-pack/test/functional/services/dashboard/drilldowns_manage.ts +++ b/test/functional/services/dashboard/drilldowns_manage.ts @@ -1,8 +1,9 @@ /* * 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. + * 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 { Key } from 'selenium-webdriver'; @@ -76,7 +77,7 @@ export function DashboardDrilldownsManageProvider({ getService }: FtrProviderCon }: { drilldownName: string; destinationURLTemplate: string; - trigger: 'VALUE_CLICK_TRIGGER' | 'SELECT_RANGE_TRIGGER'; + trigger: 'VALUE_CLICK_TRIGGER' | 'SELECT_RANGE_TRIGGER' | 'IMAGE_CLICK_TRIGGER'; }) { await this.fillInDrilldownName(drilldownName); await this.selectTriggerIfNeeded(trigger); @@ -91,7 +92,9 @@ export function DashboardDrilldownsManageProvider({ getService }: FtrProviderCon await comboBox.set(DESTINATION_DASHBOARD_SELECT, title); } - async selectTriggerIfNeeded(trigger: 'VALUE_CLICK_TRIGGER' | 'SELECT_RANGE_TRIGGER') { + async selectTriggerIfNeeded( + trigger: 'VALUE_CLICK_TRIGGER' | 'SELECT_RANGE_TRIGGER' | 'IMAGE_CLICK_TRIGGER' + ) { if (await testSubjects.exists(`triggerPicker`)) { const container = await testSubjects.find(`triggerPicker-${trigger}`); const radio = await container.findByCssSelector('input[type=radio]'); diff --git a/test/functional/services/dashboard/index.ts b/test/functional/services/dashboard/index.ts index 0423b66d04102..01262efd2a16f 100644 --- a/test/functional/services/dashboard/index.ts +++ b/test/functional/services/dashboard/index.ts @@ -11,3 +11,5 @@ export { DashboardExpectService } from './expectations'; export { DashboardAddPanelService } from './add_panel'; export { DashboardReplacePanelService } from './replace_panel'; export { DashboardPanelActionsService } from './panel_actions'; +export { DashboardDrilldownPanelActionsProvider } from './panel_drilldown_actions'; +export { DashboardDrilldownsManageProvider } from './drilldowns_manage'; diff --git a/x-pack/test/functional/services/dashboard/panel_drilldown_actions.ts b/test/functional/services/dashboard/panel_drilldown_actions.ts similarity index 92% rename from x-pack/test/functional/services/dashboard/panel_drilldown_actions.ts rename to test/functional/services/dashboard/panel_drilldown_actions.ts index 6b598c229d688..222e55950c8be 100644 --- a/x-pack/test/functional/services/dashboard/panel_drilldown_actions.ts +++ b/test/functional/services/dashboard/panel_drilldown_actions.ts @@ -1,12 +1,13 @@ /* * 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. + * 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'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '../lib/web_element_wrapper'; const CREATE_DRILLDOWN_DATA_TEST_SUBJ = 'embeddablePanelAction-OPEN_FLYOUT_ADD_DRILLDOWN'; const MANAGE_DRILLDOWNS_DATA_TEST_SUBJ = 'embeddablePanelAction-OPEN_FLYOUT_EDIT_DRILLDOWN'; diff --git a/test/functional/services/index.ts b/test/functional/services/index.ts index b4f59d121bb21..4f74899e826f0 100644 --- a/test/functional/services/index.ts +++ b/test/functional/services/index.ts @@ -26,6 +26,8 @@ import { DashboardExpectService, DashboardPanelActionsService, DashboardVisualizationsService, + DashboardDrilldownPanelActionsProvider, + DashboardDrilldownsManageProvider, } from './dashboard'; import { DocTableService } from './doc_table'; import { EmbeddingService } from './embedding'; @@ -71,6 +73,8 @@ export const services = { dashboardAddPanel: DashboardAddPanelService, dashboardReplacePanel: DashboardReplacePanelService, dashboardPanelActions: DashboardPanelActionsService, + dashboardDrilldownPanelActions: DashboardDrilldownPanelActionsProvider, + dashboardDrilldownsManage: DashboardDrilldownsManageProvider, flyout: FlyoutService, comboBox: ComboBoxService, dataGrid: DataGridService, diff --git a/test/server_integration/http/ssl_with_p12_intermediate/index.js b/test/server_integration/http/ssl_with_p12_intermediate/index.js index 54ec6f53d144d..e6ea68d7f8af9 100644 --- a/test/server_integration/http/ssl_with_p12_intermediate/index.js +++ b/test/server_integration/http/ssl_with_p12_intermediate/index.js @@ -9,7 +9,8 @@ export default function ({ getService }) { const supertest = getService('supertest'); - describe('kibana server with ssl', () => { + // FLAKY: https://github.com/elastic/kibana/issues/148515 + describe.skip('kibana server with ssl', () => { it('handles requests using ssl with a P12 keystore that uses an intermediate CA', async () => { await supertest.get('/').expect(302); }); diff --git a/tsconfig.base.json b/tsconfig.base.json index a6e06ff470905..00ac0a8205740 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -816,8 +816,12 @@ "@kbn/maps-plugin/*": ["x-pack/plugins/maps/*"], "@kbn/ml-agg-utils": ["x-pack/packages/ml/agg_utils"], "@kbn/ml-agg-utils/*": ["x-pack/packages/ml/agg_utils/*"], + "@kbn/ml-is-defined": ["x-pack/packages/ml/is_defined"], + "@kbn/ml-is-defined/*": ["x-pack/packages/ml/is_defined/*"], "@kbn/ml-is-populated-object": ["x-pack/packages/ml/is_populated_object"], "@kbn/ml-is-populated-object/*": ["x-pack/packages/ml/is_populated_object/*"], + "@kbn/ml-local-storage": ["x-pack/packages/ml/local_storage"], + "@kbn/ml-local-storage/*": ["x-pack/packages/ml/local_storage/*"], "@kbn/ml-nested-property": ["x-pack/packages/ml/nested_property"], "@kbn/ml-nested-property/*": ["x-pack/packages/ml/nested_property/*"], "@kbn/ml-plugin": ["x-pack/plugins/ml"], diff --git a/x-pack/packages/ml/is_defined/README.md b/x-pack/packages/ml/is_defined/README.md new file mode 100644 index 0000000000000..c87e487b565a6 --- /dev/null +++ b/x-pack/packages/ml/is_defined/README.md @@ -0,0 +1,3 @@ +# @kbn/ml-is-defined + +Utility function to determine if a value is not `undefined` and not `null`. diff --git a/x-pack/plugins/ml/public/application/contexts/storage/index.ts b/x-pack/packages/ml/is_defined/index.ts similarity index 77% rename from x-pack/plugins/ml/public/application/contexts/storage/index.ts rename to x-pack/packages/ml/is_defined/index.ts index 8b17073d3b099..8b04a61a8bdae 100644 --- a/x-pack/plugins/ml/public/application/contexts/storage/index.ts +++ b/x-pack/packages/ml/is_defined/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { MlStorageContextProvider, useStorage } from './storage_context'; +export { isDefined } from './src/is_defined'; diff --git a/x-pack/plugins/ml/common/types/guards.ts b/x-pack/packages/ml/is_defined/jest.config.js similarity index 65% rename from x-pack/plugins/ml/common/types/guards.ts rename to x-pack/packages/ml/is_defined/jest.config.js index ead91eafc2d4e..a4deb4d18ecf8 100644 --- a/x-pack/plugins/ml/common/types/guards.ts +++ b/x-pack/packages/ml/is_defined/jest.config.js @@ -5,6 +5,8 @@ * 2.0. */ -export function isDefined(argument: T | undefined | null): argument is T { - return argument !== undefined && argument !== null; -} +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/x-pack/packages/ml/is_defined'], +}; diff --git a/x-pack/packages/ml/is_defined/kibana.jsonc b/x-pack/packages/ml/is_defined/kibana.jsonc new file mode 100644 index 0000000000000..b25718598901b --- /dev/null +++ b/x-pack/packages/ml/is_defined/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/ml-is-defined", + "owner": "@elastic/ml-ui" +} diff --git a/x-pack/packages/ml/is_defined/package.json b/x-pack/packages/ml/is_defined/package.json new file mode 100644 index 0000000000000..2ed8896c22552 --- /dev/null +++ b/x-pack/packages/ml/is_defined/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/ml-is-defined", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/x-pack/plugins/data_visualizer/public/application/common/util/is_defined.ts b/x-pack/packages/ml/is_defined/src/is_defined.ts similarity index 75% rename from x-pack/plugins/data_visualizer/public/application/common/util/is_defined.ts rename to x-pack/packages/ml/is_defined/src/is_defined.ts index ead91eafc2d4e..1cf980293277c 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/util/is_defined.ts +++ b/x-pack/packages/ml/is_defined/src/is_defined.ts @@ -5,6 +5,12 @@ * 2.0. */ +/** + * Checks whether the supplied argument is not `undefined` and not `null`. + * + * @param argument + * @returns boolean + */ export function isDefined(argument: T | undefined | null): argument is T { return argument !== undefined && argument !== null; } diff --git a/x-pack/packages/ml/is_defined/tsconfig.json b/x-pack/packages/ml/is_defined/tsconfig.json new file mode 100644 index 0000000000000..5c989599ec9ad --- /dev/null +++ b/x-pack/packages/ml/is_defined/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [] +} diff --git a/x-pack/packages/ml/local_storage/README.md b/x-pack/packages/ml/local_storage/README.md new file mode 100644 index 0000000000000..d1e7c46957397 --- /dev/null +++ b/x-pack/packages/ml/local_storage/README.md @@ -0,0 +1,3 @@ +# @kbn/ml-local-storage + +Utilities to combine url state management with local storage. diff --git a/x-pack/packages/ml/local_storage/index.ts b/x-pack/packages/ml/local_storage/index.ts new file mode 100644 index 0000000000000..f950f8791a341 --- /dev/null +++ b/x-pack/packages/ml/local_storage/index.ts @@ -0,0 +1,8 @@ +/* + * 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 { StorageContextProvider, useStorage } from './src/storage_context'; diff --git a/x-pack/packages/ml/local_storage/jest.config.js b/x-pack/packages/ml/local_storage/jest.config.js new file mode 100644 index 0000000000000..7de0a696c57ef --- /dev/null +++ b/x-pack/packages/ml/local_storage/jest.config.js @@ -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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/x-pack/packages/ml/local_storage'], +}; diff --git a/x-pack/packages/ml/local_storage/kibana.jsonc b/x-pack/packages/ml/local_storage/kibana.jsonc new file mode 100644 index 0000000000000..8afac70248f4f --- /dev/null +++ b/x-pack/packages/ml/local_storage/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/ml-local-storage", + "owner": "@elastic/ml-ui" +} diff --git a/x-pack/packages/ml/local_storage/package.json b/x-pack/packages/ml/local_storage/package.json new file mode 100644 index 0000000000000..af2452a92220b --- /dev/null +++ b/x-pack/packages/ml/local_storage/package.json @@ -0,0 +1,9 @@ +{ + "name": "@kbn/ml-local-storage", + "description": "Utilities to combine url state management with local storage.", + "author": "Machine Learning UI", + "homepage": "https://docs.elastic.dev/kibana-dev-docs/api/kbn-ml-local-storage", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/x-pack/packages/ml/local_storage/src/storage_context.tsx b/x-pack/packages/ml/local_storage/src/storage_context.tsx new file mode 100644 index 0000000000000..e8cb64d81025e --- /dev/null +++ b/x-pack/packages/ml/local_storage/src/storage_context.tsx @@ -0,0 +1,193 @@ +/* + * 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, { + type PropsWithChildren, + useEffect, + useMemo, + useCallback, + useState, + useContext, +} from 'react'; +import { omit } from 'lodash'; + +import type { Storage } from '@kbn/kibana-utils-plugin/public'; +import { isDefined } from '@kbn/ml-is-defined'; + +/** + * StorageDefinition is a dictionary with `string` based keys. + */ +interface StorageDefinition { + [key: string]: unknown; +} + +/** + * TStorage, a partial `StorageDefinition` or `null`. + */ +type TStorage = Partial | null; +/** + * TStorageKey, keys of StorageDefintion. + */ +type TStorageKey = keyof Exclude; +/** + * TStorageMapped, mapping of TStorage with TStorageKey. + */ +type TStorageMapped = T extends string ? unknown : null; + +/** + * StorageAPI definition of store TStorage with accessors. + */ +interface StorageAPI { + value: TStorage; + setValue: >(key: K, value: T) => void; + removeValue: (key: K) => void; +} + +/** + * Type guard to check if a supplied `key` is in `storageKey`. + * + * @param key + * @param storageKeys + * @returns boolean + */ +export function isStorageKey(key: unknown, storageKeys: readonly T[]): key is T { + return storageKeys.includes(key as T); +} + +/** + * React context to hold storage API. + */ +export const MlStorageContext = React.createContext({ + value: null, + setValue() { + throw new Error('MlStorageContext set method is not implemented'); + }, + removeValue() { + throw new Error('MlStorageContext remove method is not implemented'); + }, +}); + +/** + * Props for StorageContextProvider + */ +interface StorageContextProviderProps { + storage: Storage; + storageKeys: readonly K[]; +} + +/** + * Provider to manage context for the `useStorage` hook. + */ +export function StorageContextProvider({ + children, + storage, + storageKeys, +}: PropsWithChildren>) { + const initialValue = useMemo(() => { + return storageKeys.reduce((acc, curr) => { + acc[curr as K] = storage.get(curr as string); + return acc; + }, {} as Exclude); + }, [storage, storageKeys]); + + const [state, setState] = useState(initialValue); + + const setStorageValue = useCallback( + >(key: K, value: TM) => { + storage.set(key as string, value); + + setState((prevState) => ({ + ...prevState, + [key]: value, + })); + }, + [storage] + ); + + const removeStorageValue = useCallback( + (key: K) => { + storage.remove(key as string); + setState((prevState) => omit(prevState, key) as T); + }, + [storage] + ); + + useEffect( + function updateStorageOnExternalChange() { + const eventListener = (event: StorageEvent) => { + if (!isStorageKey(event.key, storageKeys)) return; + + if (isDefined(event.newValue)) { + setState((prev) => { + return { + ...prev, + [event.key as K]: + typeof event.newValue === 'string' ? JSON.parse(event.newValue) : event.newValue, + }; + }); + } else { + setState((prev) => omit(prev, event.key as K) as T); + } + }; + + /** + * This event listener is only invoked when + * the change happens in another browser's tab. + */ + window.addEventListener('storage', eventListener); + + return () => { + window.removeEventListener('storage', eventListener); + }; + }, + [storageKeys] + ); + + const value = useMemo(() => { + return { + value: state, + setValue: setStorageValue, + removeValue: removeStorageValue, + } as StorageAPI; + }, [state, setStorageValue, removeStorageValue]); + + return {children}; +} + +/** + * Hook for consuming a storage value + * @param key + * @param initValue + */ +export function useStorage>( + key: K, + initValue?: T +): [ + typeof initValue extends undefined ? T | undefined : Exclude, + (value: T) => void +] { + const { value, setValue, removeValue } = useContext(MlStorageContext); + + const resultValue = useMemo(() => { + return (value?.[key] ?? initValue) as typeof initValue extends undefined + ? T | undefined + : Exclude; + }, [value, key, initValue]); + + const setVal = useCallback( + (v: T) => { + if (isDefined(v)) { + setValue(key, v); + } else { + removeValue(key); + } + }, + [setValue, removeValue, key] + ); + + return [resultValue, setVal]; +} diff --git a/x-pack/packages/ml/local_storage/tsconfig.json b/x-pack/packages/ml/local_storage/tsconfig.json new file mode 100644 index 0000000000000..1f42768195c2b --- /dev/null +++ b/x-pack/packages/ml/local_storage/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*", + ], + "kbn_references": [ + "@kbn/kibana-utils-plugin", + "@kbn/ml-is-defined", + ] +} diff --git a/x-pack/performance/journeys/dashboard_listing_page.ts b/x-pack/performance/journeys/dashboard_listing_page.ts index 6aa51e239e86b..0c528ac7c4559 100644 --- a/x-pack/performance/journeys/dashboard_listing_page.ts +++ b/x-pack/performance/journeys/dashboard_listing_page.ts @@ -13,7 +13,20 @@ export const journey = new Journey({ 'x-pack/performance/kbn_archives/flights_no_map_dashboard', 'x-pack/performance/kbn_archives/logs_no_map_dashboard', ], -}).step('Go to Dashboards Page', async ({ page, kbnUrl }) => { - await page.goto(kbnUrl.get(`/app/dashboards`)); - await page.waitForSelector(`[data-test-subj="table-is-ready"]`); -}); +}) + .step('Go to Dashboards Page', async ({ page, kbnUrl }) => { + await page.goto(kbnUrl.get(`/app/dashboards`)); + await page.waitForSelector(`[data-test-subj="table-is-ready"]`); + }) + .step('Search dashboards page', async ({ page, inputDelays }) => { + await page.type('[data-test-subj="tableListSearchBox"]', 'Web', { + delay: inputDelays.TYPING, + }); + await page.waitForSelector(`[data-test-subj="table-is-ready"]`); + }) + .step('Delete dashboard', async ({ page, log }) => { + await page.click('[data-test-subj="checkboxSelectRow-edf84fe0-e1a0-11e7-b6d5-4dc382ef7f5b"]'); + await page.click('[data-test-subj="deleteSelectedItems"]'); + await page.click('[data-test-subj="confirmModalConfirmButton"]'); + await page.waitForSelector(`[data-test-subj="table-is-ready"]`); + }); diff --git a/x-pack/plugins/aiops/kibana.json b/x-pack/plugins/aiops/kibana.json index dba431234ec0a..08cbaf4613464 100755 --- a/x-pack/plugins/aiops/kibana.json +++ b/x-pack/plugins/aiops/kibana.json @@ -16,6 +16,6 @@ "licensing" ], "optionalPlugins": [], - "requiredBundles": ["fieldFormats", "kibanaReact"], + "requiredBundles": ["fieldFormats", "kibanaReact", "kibanaUtils"], "extraPublicDirs": ["common"] } diff --git a/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detetion_root.tsx b/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detetion_root.tsx index 44c68c6017588..f7a039c082dee 100644 --- a/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detetion_root.tsx +++ b/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detetion_root.tsx @@ -5,16 +5,25 @@ * 2.0. */ +import React, { FC } from 'react'; + import { DataView } from '@kbn/data-views-plugin/common'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; -import React, { FC } from 'react'; +import { StorageContextProvider } from '@kbn/ml-local-storage'; import { UrlStateProvider } from '@kbn/ml-url-state'; -import { PageHeader } from '../page_header'; -import { ChangePointDetectionContextProvider } from './change_point_detection_context'; +import { Storage } from '@kbn/kibana-utils-plugin/public'; + import { DataSourceContext } from '../../hooks/use_data_source'; import { SavedSearchSavedObject } from '../../application/utils/search_utils'; import { AiopsAppContext, AiopsAppDependencies } from '../../hooks/use_aiops_app_context'; +import { AIOPS_STORAGE_KEYS } from '../../types/storage'; + +import { PageHeader } from '../page_header'; + import { ChangePointDetectionPage } from './change_point_detection_page'; +import { ChangePointDetectionContextProvider } from './change_point_detection_context'; + +const localStorage = new Storage(window.localStorage); export interface ChangePointDetectionAppStateProps { dataView: DataView; @@ -31,10 +40,12 @@ export const ChangePointDetectionAppState: FC - - - - + + + + + + diff --git a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_app_state.tsx b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_app_state.tsx index 2e745894cac0a..6b6b477807d41 100644 --- a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_app_state.tsx +++ b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_app_state.tsx @@ -11,11 +11,12 @@ import { EuiCallOut } from '@elastic/eui'; import type { Filter, Query } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; - import type { SavedSearch } from '@kbn/discover-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; - +import { StorageContextProvider } from '@kbn/ml-local-storage'; import { UrlStateProvider } from '@kbn/ml-url-state'; +import { Storage } from '@kbn/kibana-utils-plugin/public'; + import { SEARCH_QUERY_LANGUAGE, SearchQueryLanguage, @@ -23,11 +24,14 @@ import { } from '../../application/utils/search_utils'; import type { AiopsAppDependencies } from '../../hooks/use_aiops_app_context'; import { AiopsAppContext } from '../../hooks/use_aiops_app_context'; +import { AIOPS_STORAGE_KEYS } from '../../types/storage'; import { SpikeAnalysisTableRowStateProvider } from '../spike_analysis_table/spike_analysis_table_row_provider'; import { ExplainLogRateSpikesPage } from './explain_log_rate_spikes_page'; +const localStorage = new Storage(window.localStorage); + export interface ExplainLogRateSpikesAppStateProps { /** The data view to analyze. */ dataView: DataView; @@ -95,7 +99,9 @@ export const ExplainLogRateSpikesAppState: FC - + + + diff --git a/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector.tsx b/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector.tsx index 592240675197c..78cf53295cc26 100644 --- a/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector.tsx +++ b/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector.tsx @@ -25,12 +25,19 @@ import { EuiToolTip, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { useStorage } from '@kbn/ml-local-storage'; import { useAiopsAppContext } from '../../hooks/use_aiops_app_context'; import { type GetTimeFieldRangeResponse, setFullTimeRange, } from './full_time_range_selector_service'; -import { AIOPS_FROZEN_TIER_PREFERENCE, useStorage } from '../../hooks/use_storage'; +import { + AIOPS_FROZEN_TIER_PREFERENCE, + FROZEN_TIER_PREFERENCE, + type AiOpsKey, + type AiOpsStorageMapped, + type FrozenTierPreference, +} from '../../types/storage'; export interface FullTimeRangeSelectorProps { timefilter: TimefilterContract; @@ -40,13 +47,6 @@ export interface FullTimeRangeSelectorProps { callback?: (a: GetTimeFieldRangeResponse) => void; } -const FROZEN_TIER_PREFERENCE = { - EXCLUDE: 'exclude-frozen', - INCLUDE: 'include-frozen', -} as const; - -type FrozenTierPreference = typeof FROZEN_TIER_PREFERENCE[keyof typeof FROZEN_TIER_PREFERENCE]; - export const FullTimeRangeSelector: FC = ({ timefilter, dataView, @@ -90,7 +90,10 @@ export const FullTimeRangeSelector: FC = ({ const [isPopoverOpen, setPopover] = useState(false); - const [frozenDataPreference, setFrozenDataPreference] = useStorage( + const [frozenDataPreference, setFrozenDataPreference] = useStorage< + AiOpsKey, + AiOpsStorageMapped + >( AIOPS_FROZEN_TIER_PREFERENCE, // By default we will exclude frozen data tier FROZEN_TIER_PREFERENCE.EXCLUDE diff --git a/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_app_state.tsx b/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_app_state.tsx index 4c0da804f5eb6..ee571d990c832 100644 --- a/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_app_state.tsx +++ b/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_app_state.tsx @@ -7,12 +7,19 @@ import React, { FC } from 'react'; import type { SavedSearch } from '@kbn/discover-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; +import { StorageContextProvider } from '@kbn/ml-local-storage'; import { UrlStateProvider } from '@kbn/ml-url-state'; -import { LogCategorizationPage } from './log_categorization_page'; +import { Storage } from '@kbn/kibana-utils-plugin/public'; + import { SavedSearchSavedObject } from '../../application/utils/search_utils'; import type { AiopsAppDependencies } from '../../hooks/use_aiops_app_context'; +import { AIOPS_STORAGE_KEYS } from '../../types/storage'; import { AiopsAppContext } from '../../hooks/use_aiops_app_context'; +import { LogCategorizationPage } from './log_categorization_page'; + +const localStorage = new Storage(window.localStorage); + export interface LogCategorizationAppStateProps { dataView: DataView; savedSearch: SavedSearch | SavedSearchSavedObject | null; @@ -27,7 +34,9 @@ export const LogCategorizationAppState: FC = ({ return ( - + + + ); diff --git a/x-pack/plugins/aiops/public/hooks/use_storage.ts b/x-pack/plugins/aiops/public/hooks/use_storage.ts deleted file mode 100644 index c377a85b3e84c..0000000000000 --- a/x-pack/plugins/aiops/public/hooks/use_storage.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 { useCallback, useState } from 'react'; -import { useAiopsAppContext } from './use_aiops_app_context'; - -export const AIOPS_FROZEN_TIER_PREFERENCE = 'aiops.frozenDataTierPreference'; - -export type AiOps = Partial<{ - [AIOPS_FROZEN_TIER_PREFERENCE]: 'exclude_frozen' | 'include_frozen'; -}> | null; - -export type AiOpsKey = keyof Exclude; - -/** - * Hook for accessing and changing a value in the storage. - * @param key - Storage key - * @param initValue - */ -export function useStorage(key: AiOpsKey, initValue?: T): [T, (value: T) => void] { - const { storage } = useAiopsAppContext(); - - const [val, setVal] = useState(storage.get(key) ?? initValue); - - const setStorage = useCallback( - (value: T): void => { - try { - storage.set(key, value); - setVal(value); - } catch (e) { - throw new Error('Unable to update storage with provided value'); - } - }, - [key, storage] - ); - - return [val, setStorage]; -} diff --git a/x-pack/plugins/aiops/public/types/storage.ts b/x-pack/plugins/aiops/public/types/storage.ts new file mode 100644 index 0000000000000..96eb612d9ca7a --- /dev/null +++ b/x-pack/plugins/aiops/public/types/storage.ts @@ -0,0 +1,28 @@ +/* + * 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 const AIOPS_FROZEN_TIER_PREFERENCE = 'aiops.frozenDataTierPreference'; + +export const FROZEN_TIER_PREFERENCE = { + EXCLUDE: 'exclude-frozen', + INCLUDE: 'include-frozen', +} as const; + +export type FrozenTierPreference = + typeof FROZEN_TIER_PREFERENCE[keyof typeof FROZEN_TIER_PREFERENCE]; + +export type AiOps = Partial<{ + [AIOPS_FROZEN_TIER_PREFERENCE]: FrozenTierPreference; +}> | null; + +export type AiOpsKey = keyof Exclude; + +export type AiOpsStorageMapped = T extends typeof AIOPS_FROZEN_TIER_PREFERENCE + ? FrozenTierPreference | undefined + : null; + +export const AIOPS_STORAGE_KEYS = [AIOPS_FROZEN_TIER_PREFERENCE] as const; diff --git a/x-pack/plugins/aiops/tsconfig.json b/x-pack/plugins/aiops/tsconfig.json index 9f2e110d0af25..9eef408f5a513 100644 --- a/x-pack/plugins/aiops/tsconfig.json +++ b/x-pack/plugins/aiops/tsconfig.json @@ -43,6 +43,7 @@ "@kbn/core-elasticsearch-server", "@kbn/es-types", "@kbn/ml-url-state", + "@kbn/ml-local-storage", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/alerting/server/invalidate_pending_api_keys/bulk_mark_api_keys_for_invalidation.ts b/x-pack/plugins/alerting/server/invalidate_pending_api_keys/bulk_mark_api_keys_for_invalidation.ts index 8999d12772f03..290740a4ddd8b 100644 --- a/x-pack/plugins/alerting/server/invalidate_pending_api_keys/bulk_mark_api_keys_for_invalidation.ts +++ b/x-pack/plugins/alerting/server/invalidate_pending_api_keys/bulk_mark_api_keys_for_invalidation.ts @@ -6,34 +6,37 @@ */ import { Logger, SavedObjectsClientContract } from '@kbn/core/server'; +import { withSpan } from '@kbn/apm-utils'; export const bulkMarkApiKeysForInvalidation = async ( { apiKeys }: { apiKeys: string[] }, logger: Logger, savedObjectsClient: SavedObjectsClientContract ): Promise => { - if (apiKeys.length === 0) { - return; - } + withSpan({ name: 'bulkMarkApiKeysForInvalidation', type: 'rules' }, async () => { + if (apiKeys.length === 0) { + return; + } - try { - const apiKeyIds = apiKeys.map( - (apiKey) => Buffer.from(apiKey, 'base64').toString().split(':')[0] - ); - await savedObjectsClient.bulkCreate( - apiKeyIds.map((apiKeyId) => ({ - attributes: { - apiKeyId, - createdAt: new Date().toISOString(), - }, - type: 'api_key_pending_invalidation', - })) - ); - } catch (e) { - logger.error( - `Failed to bulk mark list of API keys [${apiKeys - .map((key) => `"${key}"`) - .join(', ')}] for invalidation: ${e.message}` - ); - } + try { + const apiKeyIds = apiKeys.map( + (apiKey) => Buffer.from(apiKey, 'base64').toString().split(':')[0] + ); + await savedObjectsClient.bulkCreate( + apiKeyIds.map((apiKeyId) => ({ + attributes: { + apiKeyId, + createdAt: new Date().toISOString(), + }, + type: 'api_key_pending_invalidation', + })) + ); + } catch (e) { + logger.error( + `Failed to bulk mark list of API keys [${apiKeys + .map((key) => `"${key}"`) + .join(', ')}] for invalidation: ${e.message}` + ); + } + }); }; diff --git a/x-pack/plugins/alerting/server/rules_client/common/index.ts b/x-pack/plugins/alerting/server/rules_client/common/index.ts index cbff1677c631c..6019eb0f4307e 100644 --- a/x-pack/plugins/alerting/server/rules_client/common/index.ts +++ b/x-pack/plugins/alerting/server/rules_client/common/index.ts @@ -20,3 +20,4 @@ export { parseDate } from './parse_date'; export { includeFieldsRequiredForAuthentication } from './include_fields_required_for_authentication'; export { getAndValidateCommonBulkOptions } from './get_and_validate_common_bulk_options'; export * from './snooze_utils'; +export { tryToRemoveTasks } from './try_to_remove_tasks'; diff --git a/x-pack/plugins/alerting/server/rules_client/common/retry_if_bulk_operation_conflicts.ts b/x-pack/plugins/alerting/server/rules_client/common/retry_if_bulk_operation_conflicts.ts index 4210de1207623..428f43a0dcfa6 100644 --- a/x-pack/plugins/alerting/server/rules_client/common/retry_if_bulk_operation_conflicts.ts +++ b/x-pack/plugins/alerting/server/rules_client/common/retry_if_bulk_operation_conflicts.ts @@ -9,6 +9,7 @@ import pMap from 'p-map'; import { chunk } from 'lodash'; import { KueryNode } from '@kbn/es-query'; import { Logger, SavedObjectsBulkUpdateObject } from '@kbn/core/server'; +import { withSpan } from '@kbn/apm-utils'; import { convertRuleIdsToKueryNode } from '../../lib'; import { BulkOperationError } from '../types'; import { waitBeforeNextRetry, RETRY_IF_CONFLICTS_ATTEMPTS } from './wait_before_next_retry'; @@ -35,13 +36,15 @@ export const retryIfBulkOperationConflicts = async ({ filter: KueryNode | null; retries?: number; }): Promise => { - return handler({ - action, - logger, - bulkOperation, - filter, - retries, - }); + return withSpan({ name: 'retryIfBulkOperationConflicts', type: 'rules' }, () => + handler({ + action, + logger, + bulkOperation, + filter, + retries, + }) + ); }; const handler = async ({ diff --git a/x-pack/plugins/alerting/server/rules_client/common/try_to_remove_tasks.ts b/x-pack/plugins/alerting/server/rules_client/common/try_to_remove_tasks.ts new file mode 100644 index 0000000000000..89ad52d232332 --- /dev/null +++ b/x-pack/plugins/alerting/server/rules_client/common/try_to_remove_tasks.ts @@ -0,0 +1,58 @@ +/* + * 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 { Logger } from '@kbn/core/server'; +import { withSpan } from '@kbn/apm-utils'; +import { TaskManagerStartContract } from '@kbn/task-manager-plugin/server'; + +export const tryToRemoveTasks = async ({ + taskIdsToDelete, + logger, + taskManager, +}: { + taskIdsToDelete: string[]; + logger: Logger; + taskManager: TaskManagerStartContract; +}) => { + const taskIdsFailedToBeDeleted: string[] = []; + const taskIdsSuccessfullyDeleted: string[] = []; + return await withSpan({ name: 'taskManager.bulkRemoveIfExist', type: 'rules' }, async () => { + if (taskIdsToDelete.length > 0) { + try { + const resultFromDeletingTasks = await taskManager.bulkRemoveIfExist(taskIdsToDelete); + resultFromDeletingTasks?.statuses.forEach((status) => { + if (status.success) { + taskIdsSuccessfullyDeleted.push(status.id); + } else { + taskIdsFailedToBeDeleted.push(status.id); + } + }); + if (taskIdsSuccessfullyDeleted.length) { + logger.debug( + `Successfully deleted schedules for underlying tasks: ${taskIdsSuccessfullyDeleted.join( + ', ' + )}` + ); + } + if (taskIdsFailedToBeDeleted.length) { + logger.error( + `Failure to delete schedules for underlying tasks: ${taskIdsFailedToBeDeleted.join( + ', ' + )}` + ); + } + } catch (error) { + logger.error( + `Failure to delete schedules for underlying tasks: ${taskIdsToDelete.join( + ', ' + )}. TaskManager bulkRemoveIfExist failed with Error: ${error.message}` + ); + } + } + return taskIdsFailedToBeDeleted; + }); +}; diff --git a/x-pack/plugins/alerting/server/rules_client/lib/check_authorization_and_get_total.ts b/x-pack/plugins/alerting/server/rules_client/lib/check_authorization_and_get_total.ts index ecaa7fd172fa7..4327176841ad4 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/check_authorization_and_get_total.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/check_authorization_and_get_total.ts @@ -8,6 +8,7 @@ import pMap from 'p-map'; import Boom from '@hapi/boom'; import { KueryNode } from '@kbn/es-query'; +import { withSpan } from '@kbn/apm-utils'; import { RawRule } from '../../types'; import { WriteOperations, ReadOperations, AlertingAuthorizationEntity } from '../../authorization'; import { BulkAction, RuleBulkOperationAggregation } from '../types'; @@ -45,25 +46,27 @@ export const checkAuthorizationAndGetTotal = async ( RuleAuditAction: RuleAuditAction.DISABLE, }, }; - const { aggregations, total } = await context.unsecuredSavedObjectsClient.find< - RawRule, - RuleBulkOperationAggregation - >({ - filter, - page: 1, - perPage: 0, - type: 'alert', - aggs: { - alertTypeId: { - multi_terms: { - terms: [ - { field: 'alert.attributes.alertTypeId' }, - { field: 'alert.attributes.consumer' }, - ], + + const { aggregations, total } = await withSpan( + { name: 'unsecuredSavedObjectsClient.find', type: 'rules' }, + () => + context.unsecuredSavedObjectsClient.find({ + filter, + page: 1, + perPage: 0, + type: 'alert', + aggs: { + alertTypeId: { + multi_terms: { + terms: [ + { field: 'alert.attributes.alertTypeId' }, + { field: 'alert.attributes.consumer' }, + ], + }, + }, }, - }, - }, - }); + }) + ); if (total > MAX_RULES_NUMBER_FOR_BULK_OPERATION) { throw Boom.badRequest( @@ -77,28 +80,30 @@ export const checkAuthorizationAndGetTotal = async ( throw Boom.badRequest(`No rules found for bulk ${action.toLocaleLowerCase()}`); } - await pMap( - buckets, - async ({ key: [ruleType, consumer] }) => { - context.ruleTypeRegistry.ensureRuleTypeEnabled(ruleType); - try { - await context.authorization.ensureAuthorized({ - ruleTypeId: ruleType, - consumer, - operation: actionToConstantsMapping[action].WriteOperation, - entity: AlertingAuthorizationEntity.Rule, - }); - } catch (error) { - context.auditLogger?.log( - ruleAuditEvent({ - action: actionToConstantsMapping[action].RuleAuditAction, - error, - }) - ); - throw error; - } - }, - { concurrency: RULE_TYPE_CHECKS_CONCURRENCY } + await withSpan({ name: 'authorization.ensureAuthorized', type: 'rules' }, () => + pMap( + buckets, + async ({ key: [ruleType, consumer, actions] }) => { + context.ruleTypeRegistry.ensureRuleTypeEnabled(ruleType); + try { + await context.authorization.ensureAuthorized({ + ruleTypeId: ruleType, + consumer, + operation: actionToConstantsMapping[action].WriteOperation, + entity: AlertingAuthorizationEntity.Rule, + }); + } catch (error) { + context.auditLogger?.log( + ruleAuditEvent({ + action: actionToConstantsMapping[action].RuleAuditAction, + error, + }) + ); + throw error; + } + }, + { concurrency: RULE_TYPE_CHECKS_CONCURRENCY } + ) ); return { total }; }; diff --git a/x-pack/plugins/alerting/server/rules_client/lib/create_rule_saved_object.ts b/x-pack/plugins/alerting/server/rules_client/lib/create_rule_saved_object.ts index 45ade4086af4a..87bc26b31e7fa 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/create_rule_saved_object.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/create_rule_saved_object.ts @@ -6,6 +6,7 @@ */ import { SavedObjectReference, SavedObject } from '@kbn/core/server'; +import { withSpan } from '@kbn/apm-utils'; import { RawRule, RuleTypeParams } from '../../types'; import { bulkMarkApiKeysForInvalidation } from '../../invalidate_pending_api_keys/bulk_mark_api_keys_for_invalidation'; import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; @@ -41,14 +42,14 @@ export async function createRuleSavedObject; try { - createdAlert = await context.unsecuredSavedObjectsClient.create( - 'alert', - updateMeta(context, rawRule), - { - ...options, - references, - id: ruleId, - } + createdAlert = await withSpan( + { name: 'unsecuredSavedObjectsClient.create', type: 'rules' }, + () => + context.unsecuredSavedObjectsClient.create('alert', updateMeta(context, rawRule), { + ...options, + references, + id: ruleId, + }) ); } catch (e) { // Avoid unused API key @@ -61,15 +62,16 @@ export async function createRuleSavedObject('alert', createdAlert.id, { - scheduledTaskId: scheduledTask.id, - }); - createdAlert.attributes.scheduledTaskId = scheduledTask.id; + + await withSpan({ name: 'unsecuredSavedObjectsClient.update', type: 'rules' }, () => + context.unsecuredSavedObjectsClient.update('alert', createdAlert.id, { + scheduledTaskId, + }) + ); + createdAlert.attributes.scheduledTaskId = scheduledTaskId; } // Log warning if schedule interval is less than the minimum but we're not enforcing it diff --git a/x-pack/plugins/alerting/server/rules_client/lib/get_authorization_filter.ts b/x-pack/plugins/alerting/server/rules_client/lib/get_authorization_filter.ts index 28e42c6b12e42..b9cc41a0fd7c4 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/get_authorization_filter.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/get_authorization_filter.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { withSpan } from '@kbn/apm-utils'; import { AlertingAuthorizationEntity } from '../../authorization'; import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; import { RulesClientContext } from '../types'; @@ -16,9 +17,13 @@ export const getAuthorizationFilter = async ( { action }: { action: BulkAction } ) => { try { - const authorizationTuple = await context.authorization.getFindAuthorizationFilter( - AlertingAuthorizationEntity.Rule, - alertingAuthorizationFilterOpts + const authorizationTuple = await withSpan( + { name: 'authorization.getFindAuthorizationFilter', type: 'rules' }, + () => + context.authorization.getFindAuthorizationFilter( + AlertingAuthorizationEntity.Rule, + alertingAuthorizationFilterOpts + ) ); return authorizationTuple.filter; } catch (error) { diff --git a/x-pack/plugins/alerting/server/rules_client/lib/recover_rule_alerts.ts b/x-pack/plugins/alerting/server/rules_client/lib/recover_rule_alerts.ts index aaa84a8b6950b..e7027905ff956 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/recover_rule_alerts.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/recover_rule_alerts.ts @@ -7,6 +7,7 @@ import { mapValues } from 'lodash'; import { SAVED_OBJECT_REL_PRIMARY } from '@kbn/event-log-plugin/server'; +import { withSpan } from '@kbn/apm-utils'; import { RawRule, SanitizedRule, RawAlertInstance as RawAlert } from '../../types'; import { taskInstanceToAlertTaskInstance } from '../../task_runner/alert_task_instance'; import { Alert } from '../../alert'; @@ -19,51 +20,53 @@ export const recoverRuleAlerts = async ( id: string, attributes: RawRule ) => { - if (!context.eventLogger || !attributes.scheduledTaskId) return; - try { - const { state } = taskInstanceToAlertTaskInstance( - await context.taskManager.get(attributes.scheduledTaskId), - attributes as unknown as SanitizedRule - ); + return withSpan({ name: 'recoverRuleAlerts', type: 'rules' }, async () => { + if (!context.eventLogger || !attributes.scheduledTaskId) return; + try { + const { state } = taskInstanceToAlertTaskInstance( + await context.taskManager.get(attributes.scheduledTaskId), + attributes as unknown as SanitizedRule + ); - const recoveredAlerts = mapValues, Alert>( - state.alertInstances ?? {}, - (rawAlertInstance, alertId) => new Alert(alertId, rawAlertInstance) - ); - const recoveredAlertIds = Object.keys(recoveredAlerts); + const recoveredAlerts = mapValues, Alert>( + state.alertInstances ?? {}, + (rawAlertInstance, alertId) => new Alert(alertId, rawAlertInstance) + ); + const recoveredAlertIds = Object.keys(recoveredAlerts); - for (const alertId of recoveredAlertIds) { - const { group: actionGroup } = recoveredAlerts[alertId].getLastScheduledActions() ?? {}; - const instanceState = recoveredAlerts[alertId].getState(); - const message = `instance '${alertId}' has recovered due to the rule was disabled`; + for (const alertId of recoveredAlertIds) { + const { group: actionGroup } = recoveredAlerts[alertId].getLastScheduledActions() ?? {}; + const instanceState = recoveredAlerts[alertId].getState(); + const message = `instance '${alertId}' has recovered due to the rule was disabled`; - const event = createAlertEventLogRecordObject({ - ruleId: id, - ruleName: attributes.name, - ruleType: context.ruleTypeRegistry.get(attributes.alertTypeId), - consumer: attributes.consumer, - instanceId: alertId, - action: EVENT_LOG_ACTIONS.recoveredInstance, - message, - state: instanceState, - group: actionGroup, - namespace: context.namespace, - spaceId: context.spaceId, - savedObjects: [ - { - id, - type: 'alert', - typeId: attributes.alertTypeId, - relation: SAVED_OBJECT_REL_PRIMARY, - }, - ], - }); - context.eventLogger.logEvent(event); + const event = createAlertEventLogRecordObject({ + ruleId: id, + ruleName: attributes.name, + ruleType: context.ruleTypeRegistry.get(attributes.alertTypeId), + consumer: attributes.consumer, + instanceId: alertId, + action: EVENT_LOG_ACTIONS.recoveredInstance, + message, + state: instanceState, + group: actionGroup, + namespace: context.namespace, + spaceId: context.spaceId, + savedObjects: [ + { + id, + type: 'alert', + typeId: attributes.alertTypeId, + relation: SAVED_OBJECT_REL_PRIMARY, + }, + ], + }); + context.eventLogger.logEvent(event); + } + } catch (error) { + // this should not block the rest of the disable process + context.logger.warn( + `rulesClient.disable('${id}') - Could not write recovery events - ${error.message}` + ); } - } catch (error) { - // this should not block the rest of the disable process - context.logger.warn( - `rulesClient.disable('${id}') - Could not write recovery events - ${error.message}` - ); - } + }); }; diff --git a/x-pack/plugins/alerting/server/rules_client/lib/schedule_task.ts b/x-pack/plugins/alerting/server/rules_client/lib/schedule_task.ts index eecdcf0314d02..c868a2d944075 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/schedule_task.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/schedule_task.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { withSpan } from '@kbn/apm-utils'; import { RulesClientContext } from '../types'; import { ScheduleTaskOptions } from '../types'; @@ -28,7 +29,9 @@ export async function scheduleTask(context: RulesClientContext, opts: ScheduleTa enabled: true, }; try { - return await context.taskManager.schedule(taskInstance); + return await withSpan({ name: 'taskManager.schedule', type: 'rules' }, () => + context.taskManager.schedule(taskInstance) + ); } catch (err) { if (err.statusCode === 409 && !throwOnConflict) { return taskInstance; diff --git a/x-pack/plugins/alerting/server/rules_client/methods/bulk_delete.ts b/x-pack/plugins/alerting/server/rules_client/methods/bulk_delete.ts index abce18abe6802..87a4e09eda5ea 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/bulk_delete.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/bulk_delete.ts @@ -7,10 +7,12 @@ import { KueryNode, nodeBuilder } from '@kbn/es-query'; import { SavedObjectsBulkUpdateObject } from '@kbn/core/server'; +import { withSpan } from '@kbn/apm-utils'; import { RawRule } from '../../types'; import { convertRuleIdsToKueryNode } from '../../lib'; import { bulkMarkApiKeysForInvalidation } from '../../invalidate_pending_api_keys/bulk_mark_api_keys_for_invalidation'; import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; +import { tryToRemoveTasks } from '../common'; import { getAuthorizationFilter, checkAuthorizationAndGetTotal, getAlertFromRaw } from '../lib'; import { retryIfBulkOperationConflicts, @@ -35,54 +37,32 @@ export const bulkDeleteRules = async (context: RulesClientContext, options: Bulk action: 'DELETE', }); - const { rules, errors, accListSpecificForBulkOperation } = await retryIfBulkOperationConflicts({ - action: 'DELETE', - logger: context.logger, - bulkOperation: (filterKueryNode: KueryNode | null) => - bulkDeleteWithOCC(context, { filter: filterKueryNode }), - filter: kueryNodeFilterWithAuth, - }); + const { rules, errors, accListSpecificForBulkOperation } = await withSpan( + { name: 'retryIfBulkOperationConflicts', type: 'rules' }, + () => + retryIfBulkOperationConflicts({ + action: 'DELETE', + logger: context.logger, + bulkOperation: (filterKueryNode: KueryNode | null) => + bulkDeleteWithOCC(context, { filter: filterKueryNode }), + filter: kueryNodeFilterWithAuth, + }) + ); const [apiKeysToInvalidate, taskIdsToDelete] = accListSpecificForBulkOperation; - const taskIdsFailedToBeDeleted: string[] = []; - const taskIdsSuccessfullyDeleted: string[] = []; - if (taskIdsToDelete.length > 0) { - try { - const resultFromDeletingTasks = await context.taskManager.bulkRemoveIfExist(taskIdsToDelete); - resultFromDeletingTasks?.statuses.forEach((status) => { - if (status.success) { - taskIdsSuccessfullyDeleted.push(status.id); - } else { - taskIdsFailedToBeDeleted.push(status.id); - } - }); - if (taskIdsSuccessfullyDeleted.length) { - context.logger.debug( - `Successfully deleted schedules for underlying tasks: ${taskIdsSuccessfullyDeleted.join( - ', ' - )}` - ); - } - if (taskIdsFailedToBeDeleted.length) { - context.logger.error( - `Failure to delete schedules for underlying tasks: ${taskIdsFailedToBeDeleted.join(', ')}` - ); - } - } catch (error) { - context.logger.error( - `Failure to delete schedules for underlying tasks: ${taskIdsToDelete.join( - ', ' - )}. TaskManager bulkRemoveIfExist failed with Error: ${error.message}` - ); - } - } - - await bulkMarkApiKeysForInvalidation( - { apiKeys: apiKeysToInvalidate }, - context.logger, - context.unsecuredSavedObjectsClient - ); + const [result] = await Promise.allSettled([ + tryToRemoveTasks({ + taskIdsToDelete, + logger: context.logger, + taskManager: context.taskManager, + }), + bulkMarkApiKeysForInvalidation( + { apiKeys: apiKeysToInvalidate }, + context.logger, + context.unsecuredSavedObjectsClient + ), + ]); const deletedRules = rules.map(({ id, attributes, references }) => { return getAlertFromRaw( @@ -95,58 +75,74 @@ export const bulkDeleteRules = async (context: RulesClientContext, options: Bulk ); }); - return { errors, rules: deletedRules, total, taskIdsFailedToBeDeleted }; + if (result.status === 'fulfilled') { + return { errors, total, rules: deletedRules, taskIdsFailedToBeDeleted: result.value }; + } else { + return { errors, total, rules: deletedRules, taskIdsFailedToBeDeleted: [] }; + } }; const bulkDeleteWithOCC = async ( context: RulesClientContext, { filter }: { filter: KueryNode | null } ) => { - const rulesFinder = - await context.encryptedSavedObjectsClient.createPointInTimeFinderDecryptedAsInternalUser( - { + const rulesFinder = await withSpan( + { + name: 'encryptedSavedObjectsClient.createPointInTimeFinderDecryptedAsInternalUser', + type: 'rules', + }, + () => + context.encryptedSavedObjectsClient.createPointInTimeFinderDecryptedAsInternalUser({ filter, type: 'alert', perPage: 100, ...(context.namespace ? { namespaces: [context.namespace] } : undefined), - } - ); + }) + ); const rulesToDelete: Array> = []; - const apiKeysToInvalidate: string[] = []; - const taskIdsToDelete: string[] = []; - const errors: BulkOperationError[] = []; const apiKeyToRuleIdMapping: Record = {}; const taskIdToRuleIdMapping: Record = {}; const ruleNameToRuleIdMapping: Record = {}; - for await (const response of rulesFinder.find()) { - for (const rule of response.saved_objects) { - if (rule.attributes.apiKey) { - apiKeyToRuleIdMapping[rule.id] = rule.attributes.apiKey; - } - if (rule.attributes.name) { - ruleNameToRuleIdMapping[rule.id] = rule.attributes.name; - } - if (rule.attributes.scheduledTaskId) { - taskIdToRuleIdMapping[rule.id] = rule.attributes.scheduledTaskId; + await withSpan( + { name: 'Get rules, collect them and their attributes', type: 'rules' }, + async () => { + for await (const response of rulesFinder.find()) { + for (const rule of response.saved_objects) { + if (rule.attributes.apiKey) { + apiKeyToRuleIdMapping[rule.id] = rule.attributes.apiKey; + } + if (rule.attributes.name) { + ruleNameToRuleIdMapping[rule.id] = rule.attributes.name; + } + if (rule.attributes.scheduledTaskId) { + taskIdToRuleIdMapping[rule.id] = rule.attributes.scheduledTaskId; + } + rulesToDelete.push(rule); + + context.auditLogger?.log( + ruleAuditEvent({ + action: RuleAuditAction.DELETE, + outcome: 'unknown', + savedObject: { type: 'alert', id: rule.id }, + }) + ); + } } - rulesToDelete.push(rule); - - context.auditLogger?.log( - ruleAuditEvent({ - action: RuleAuditAction.DELETE, - outcome: 'unknown', - savedObject: { type: 'alert', id: rule.id }, - }) - ); + await rulesFinder.close(); } - } - await rulesFinder.close(); + ); - const result = await context.unsecuredSavedObjectsClient.bulkDelete(rulesToDelete); + const result = await withSpan( + { name: 'unsecuredSavedObjectsClient.bulkDelete', type: 'rules' }, + () => context.unsecuredSavedObjectsClient.bulkDelete(rulesToDelete) + ); const deletedRuleIds: string[] = []; + const apiKeysToInvalidate: string[] = []; + const taskIdsToDelete: string[] = []; + const errors: BulkOperationError[] = []; result.statuses.forEach((status) => { if (status.error === undefined) { diff --git a/x-pack/plugins/alerting/server/rules_client/methods/bulk_disable.ts b/x-pack/plugins/alerting/server/rules_client/methods/bulk_disable.ts index 316c3c9685a9b..5a79a38c767fd 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/bulk_disable.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/bulk_disable.ts @@ -7,6 +7,10 @@ import { KueryNode, nodeBuilder } from '@kbn/es-query'; import { SavedObjectsBulkUpdateObject } from '@kbn/core/server'; +import { withSpan } from '@kbn/apm-utils'; +import pMap from 'p-map'; +import { Logger } from '@kbn/core/server'; +import { TaskManagerStartContract } from '@kbn/task-manager-plugin/server'; import { RawRule } from '../../types'; import { convertRuleIdsToKueryNode } from '../../lib'; import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; @@ -23,6 +27,7 @@ import { updateMeta, } from '../lib'; import { BulkOptions, BulkOperationError, RulesClientContext } from '../types'; +import { tryToRemoveTasks } from '../common'; export const bulkDisableRules = async (context: RulesClientContext, options: BulkOptions) => { const { ids, filter } = getAndValidateCommonBulkOptions(options); @@ -40,75 +45,28 @@ export const bulkDisableRules = async (context: RulesClientContext, options: Bul action: 'DISABLE', }); - const { errors, rules, accListSpecificForBulkOperation } = await retryIfBulkOperationConflicts({ - action: 'DISABLE', - logger: context.logger, - bulkOperation: (filterKueryNode: KueryNode | null) => - bulkDisableRulesWithOCC(context, { filter: filterKueryNode }), - filter: kueryNodeFilterWithAuth, - }); + const { errors, rules, accListSpecificForBulkOperation } = await withSpan( + { name: 'retryIfBulkOperationConflicts', type: 'rules' }, + () => + retryIfBulkOperationConflicts({ + action: 'DISABLE', + logger: context.logger, + bulkOperation: (filterKueryNode: KueryNode | null) => + bulkDisableRulesWithOCC(context, { filter: filterKueryNode }), + filter: kueryNodeFilterWithAuth, + }) + ); const [taskIdsToDisable, taskIdsToDelete] = accListSpecificForBulkOperation; - if (taskIdsToDisable.length > 0) { - try { - const resultFromDisablingTasks = await context.taskManager.bulkDisable(taskIdsToDisable); - if (resultFromDisablingTasks.tasks.length) { - context.logger.debug( - `Successfully disabled schedules for underlying tasks: ${resultFromDisablingTasks.tasks - .map((task) => task.id) - .join(', ')}` - ); - } - if (resultFromDisablingTasks.errors.length) { - context.logger.error( - `Failure to disable schedules for underlying tasks: ${resultFromDisablingTasks.errors - .map((error) => error.task.id) - .join(', ')}` - ); - } - } catch (error) { - context.logger.error( - `Failure to disable schedules for underlying tasks: ${taskIdsToDisable.join( - ', ' - )}. TaskManager bulkDisable failed with Error: ${error.message}` - ); - } - } - - const taskIdsFailedToBeDeleted: string[] = []; - const taskIdsSuccessfullyDeleted: string[] = []; - - if (taskIdsToDelete.length > 0) { - try { - const resultFromDeletingTasks = await context.taskManager.bulkRemoveIfExist(taskIdsToDelete); - resultFromDeletingTasks?.statuses.forEach((status) => { - if (status.success) { - taskIdsSuccessfullyDeleted.push(status.id); - } else { - taskIdsFailedToBeDeleted.push(status.id); - } - }); - if (taskIdsSuccessfullyDeleted.length) { - context.logger.debug( - `Successfully deleted schedules for underlying tasks: ${taskIdsSuccessfullyDeleted.join( - ', ' - )}` - ); - } - if (taskIdsFailedToBeDeleted.length) { - context.logger.error( - `Failure to delete schedules for underlying tasks: ${taskIdsFailedToBeDeleted.join(', ')}` - ); - } - } catch (error) { - context.logger.error( - `Failure to delete schedules for underlying tasks: ${taskIdsToDelete.join( - ', ' - )}. TaskManager bulkRemoveIfExist failed with Error: ${error.message}` - ); - } - } + await Promise.allSettled([ + tryToDisableTasks({ + taskIdsToDisable, + logger: context.logger, + taskManager: context.taskManager, + }), + tryToRemoveTasks({ taskIdsToDelete, logger: context.logger, taskManager: context.taskManager }), + ]); const updatedRules = rules.map(({ id, attributes, references }) => { return getAlertFromRaw( @@ -130,77 +88,90 @@ const bulkDisableRulesWithOCC = async ( ) => { const additionalFilter = nodeBuilder.is('alert.attributes.enabled', 'true'); - const rulesFinder = - await context.encryptedSavedObjectsClient.createPointInTimeFinderDecryptedAsInternalUser( - { + const rulesFinder = await withSpan( + { + name: 'encryptedSavedObjectsClient.createPointInTimeFinderDecryptedAsInternalUser', + type: 'rules', + }, + () => + context.encryptedSavedObjectsClient.createPointInTimeFinderDecryptedAsInternalUser({ filter: filter ? nodeBuilder.and([filter, additionalFilter]) : additionalFilter, type: 'alert', perPage: 100, ...(context.namespace ? { namespaces: [context.namespace] } : undefined), - } - ); + }) + ); const rulesToDisable: Array> = []; const errors: BulkOperationError[] = []; const ruleNameToRuleIdMapping: Record = {}; const username = await context.getUserName(); - for await (const response of rulesFinder.find()) { - response.saved_objects.forEach((rule) => { - try { - if (rule.attributes.enabled === false) return; - - recoverRuleAlerts(context, rule.id, rule.attributes); - - if (rule.attributes.name) { - ruleNameToRuleIdMapping[rule.id] = rule.attributes.name; - } - - const updatedAttributes = updateMeta(context, { - ...rule.attributes, - enabled: false, - scheduledTaskId: - rule.attributes.scheduledTaskId === rule.id ? rule.attributes.scheduledTaskId : null, - updatedBy: username, - updatedAt: new Date().toISOString(), - }); - - rulesToDisable.push({ - ...rule, - attributes: { - ...updatedAttributes, - }, - }); - - context.auditLogger?.log( - ruleAuditEvent({ - action: RuleAuditAction.DISABLE, - outcome: 'unknown', - savedObject: { type: 'alert', id: rule.id }, - }) - ); - } catch (error) { - errors.push({ - message: error.message, - rule: { - id: rule.id, - name: rule.attributes?.name, - }, + await withSpan( + { name: 'Get rules, collect them and their attributes', type: 'rules' }, + async () => { + for await (const response of rulesFinder.find()) { + await pMap(response.saved_objects, async (rule) => { + try { + await recoverRuleAlerts(context, rule.id, rule.attributes); + + if (rule.attributes.name) { + ruleNameToRuleIdMapping[rule.id] = rule.attributes.name; + } + + const updatedAttributes = updateMeta(context, { + ...rule.attributes, + enabled: false, + scheduledTaskId: + rule.attributes.scheduledTaskId === rule.id + ? rule.attributes.scheduledTaskId + : null, + updatedBy: username, + updatedAt: new Date().toISOString(), + }); + + rulesToDisable.push({ + ...rule, + attributes: { + ...updatedAttributes, + }, + }); + + context.auditLogger?.log( + ruleAuditEvent({ + action: RuleAuditAction.DISABLE, + outcome: 'unknown', + savedObject: { type: 'alert', id: rule.id }, + }) + ); + } catch (error) { + errors.push({ + message: error.message, + rule: { + id: rule.id, + name: rule.attributes?.name, + }, + }); + context.auditLogger?.log( + ruleAuditEvent({ + action: RuleAuditAction.DISABLE, + error, + }) + ); + } }); - context.auditLogger?.log( - ruleAuditEvent({ - action: RuleAuditAction.DISABLE, - error, - }) - ); } - }); - } - await rulesFinder.close(); + await rulesFinder.close(); + } + ); - const result = await context.unsecuredSavedObjectsClient.bulkCreate(rulesToDisable, { - overwrite: true, - }); + const result = await withSpan( + { name: 'unsecuredSavedObjectsClient.bulkCreate', type: 'rules' }, + () => + context.unsecuredSavedObjectsClient.bulkCreate(rulesToDisable, { + overwrite: true, + }) + ); const taskIdsToDisable: string[] = []; const taskIdsToDelete: string[] = []; @@ -234,3 +205,41 @@ const bulkDisableRulesWithOCC = async ( accListSpecificForBulkOperation: [taskIdsToDisable, taskIdsToDelete], }; }; + +const tryToDisableTasks = async ({ + taskIdsToDisable, + logger, + taskManager, +}: { + taskIdsToDisable: string[]; + logger: Logger; + taskManager: TaskManagerStartContract; +}) => { + return await withSpan({ name: 'taskManager.bulkDisable', type: 'rules' }, async () => { + if (taskIdsToDisable.length > 0) { + try { + const resultFromDisablingTasks = await taskManager.bulkDisable(taskIdsToDisable); + if (resultFromDisablingTasks.tasks.length) { + logger.debug( + `Successfully disabled schedules for underlying tasks: ${resultFromDisablingTasks.tasks + .map((task) => task.id) + .join(', ')}` + ); + } + if (resultFromDisablingTasks.errors.length) { + logger.error( + `Failure to disable schedules for underlying tasks: ${resultFromDisablingTasks.errors + .map((error) => error.task.id) + .join(', ')}` + ); + } + } catch (error) { + logger.error( + `Failure to disable schedules for underlying tasks: ${taskIdsToDisable.join( + ', ' + )}. TaskManager bulkDisable failed with Error: ${error.message}` + ); + } + } + }); +}; diff --git a/x-pack/plugins/alerting/server/rules_client/methods/bulk_enable.ts b/x-pack/plugins/alerting/server/rules_client/methods/bulk_enable.ts index 0546906b04313..16107ca8a3e9a 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/bulk_enable.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/bulk_enable.ts @@ -8,6 +8,9 @@ import pMap from 'p-map'; import { KueryNode, nodeBuilder } from '@kbn/es-query'; import { SavedObjectsBulkUpdateObject } from '@kbn/core/server'; +import { withSpan } from '@kbn/apm-utils'; +import { Logger } from '@kbn/core/server'; +import { TaskManagerStartContract } from '@kbn/task-manager-plugin/server'; import { RawRule, IntervalSchedule } from '../../types'; import { convertRuleIdsToKueryNode } from '../../lib'; import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; @@ -33,7 +36,9 @@ const getShouldScheduleTask = async ( if (!scheduledTaskId) return true; try { // make sure scheduledTaskId exist - await context.taskManager.get(scheduledTaskId); + await withSpan({ name: 'getShouldScheduleTask', type: 'rules' }, () => + context.taskManager.get(scheduledTaskId) + ); return false; } catch (err) { return true; @@ -66,36 +71,11 @@ export const bulkEnableRules = async (context: RulesClientContext, options: Bulk const [taskIdsToEnable] = accListSpecificForBulkOperation; - const taskIdsFailedToBeEnabled: string[] = []; - if (taskIdsToEnable.length > 0) { - try { - const resultFromEnablingTasks = await context.taskManager.bulkEnable(taskIdsToEnable); - resultFromEnablingTasks?.errors?.forEach((error) => { - taskIdsFailedToBeEnabled.push(error.task.id); - }); - if (resultFromEnablingTasks.tasks.length) { - context.logger.debug( - `Successfully enabled schedules for underlying tasks: ${resultFromEnablingTasks.tasks - .map((task) => task.id) - .join(', ')}` - ); - } - if (resultFromEnablingTasks.errors.length) { - context.logger.error( - `Failure to enable schedules for underlying tasks: ${resultFromEnablingTasks.errors - .map((error) => error.task.id) - .join(', ')}` - ); - } - } catch (error) { - taskIdsFailedToBeEnabled.push(...taskIdsToEnable); - context.logger.error( - `Failure to enable schedules for underlying tasks: ${taskIdsToEnable.join( - ', ' - )}. TaskManager bulkEnable failed with Error: ${error.message}` - ); - } - } + const taskIdsFailedToBeEnabled = await tryToEnableTasks({ + taskIdsToEnable, + logger: context.logger, + taskManager: context.taskManager, + }); const updatedRules = rules.map(({ id, attributes, references }) => { return getAlertFromRaw( @@ -117,109 +97,123 @@ const bulkEnableRulesWithOCC = async ( ) => { const additionalFilter = nodeBuilder.is('alert.attributes.enabled', 'false'); - const rulesFinder = - await context.encryptedSavedObjectsClient.createPointInTimeFinderDecryptedAsInternalUser( - { - filter: filter ? nodeBuilder.and([filter, additionalFilter]) : additionalFilter, - type: 'alert', - perPage: 100, - ...(context.namespace ? { namespaces: [context.namespace] } : undefined), - } - ); + const rulesFinder = await withSpan( + { + name: 'encryptedSavedObjectsClient.createPointInTimeFinderDecryptedAsInternalUser', + type: 'rules', + }, + async () => + await context.encryptedSavedObjectsClient.createPointInTimeFinderDecryptedAsInternalUser( + { + filter: filter ? nodeBuilder.and([filter, additionalFilter]) : additionalFilter, + type: 'alert', + perPage: 100, + ...(context.namespace ? { namespaces: [context.namespace] } : undefined), + } + ) + ); const rulesToEnable: Array> = []; - const taskIdsToEnable: string[] = []; const errors: BulkOperationError[] = []; const ruleNameToRuleIdMapping: Record = {}; const username = await context.getUserName(); - for await (const response of rulesFinder.find()) { - await pMap(response.saved_objects, async (rule) => { - try { - if (rule.attributes.enabled === true) return; - if (rule.attributes.actions.length) { + await withSpan( + { name: 'Get rules, collect them and their attributes', type: 'rules' }, + async () => { + for await (const response of rulesFinder.find()) { + await pMap(response.saved_objects, async (rule) => { try { - await context.actionsAuthorization.ensureAuthorized('execute'); - } catch (error) { - throw Error(`Rule not authorized for bulk enable - ${error.message}`); - } - } - if (rule.attributes.name) { - ruleNameToRuleIdMapping[rule.id] = rule.attributes.name; - } + if (rule.attributes.actions.length) { + try { + await context.actionsAuthorization.ensureAuthorized('execute'); + } catch (error) { + throw Error(`Rule not authorized for bulk enable - ${error.message}`); + } + } + if (rule.attributes.name) { + ruleNameToRuleIdMapping[rule.id] = rule.attributes.name; + } - const updatedAttributes = updateMeta(context, { - ...rule.attributes, - ...(!rule.attributes.apiKey && - (await createNewAPIKeySet(context, { attributes: rule.attributes, username }))), - enabled: true, - updatedBy: username, - updatedAt: new Date().toISOString(), - executionStatus: { - status: 'pending', - lastDuration: 0, - lastExecutionDate: new Date().toISOString(), - error: null, - warning: null, - }, - }); + const updatedAttributes = updateMeta(context, { + ...rule.attributes, + ...(!rule.attributes.apiKey && + (await createNewAPIKeySet(context, { attributes: rule.attributes, username }))), + enabled: true, + updatedBy: username, + updatedAt: new Date().toISOString(), + executionStatus: { + status: 'pending', + lastDuration: 0, + lastExecutionDate: new Date().toISOString(), + error: null, + warning: null, + }, + }); - const shouldScheduleTask = await getShouldScheduleTask( - context, - rule.attributes.scheduledTaskId - ); + const shouldScheduleTask = await getShouldScheduleTask( + context, + rule.attributes.scheduledTaskId + ); - let scheduledTaskId; - if (shouldScheduleTask) { - const scheduledTask = await scheduleTask(context, { - id: rule.id, - consumer: rule.attributes.consumer, - ruleTypeId: rule.attributes.alertTypeId, - schedule: rule.attributes.schedule as IntervalSchedule, - throwOnConflict: false, - }); - scheduledTaskId = scheduledTask.id; - } + let scheduledTaskId; + if (shouldScheduleTask) { + const scheduledTask = await scheduleTask(context, { + id: rule.id, + consumer: rule.attributes.consumer, + ruleTypeId: rule.attributes.alertTypeId, + schedule: rule.attributes.schedule as IntervalSchedule, + throwOnConflict: false, + }); + scheduledTaskId = scheduledTask.id; + } - rulesToEnable.push({ - ...rule, - attributes: { - ...updatedAttributes, - ...(scheduledTaskId ? { scheduledTaskId } : undefined), - }, - }); + rulesToEnable.push({ + ...rule, + attributes: { + ...updatedAttributes, + ...(scheduledTaskId ? { scheduledTaskId } : undefined), + }, + }); - context.auditLogger?.log( - ruleAuditEvent({ - action: RuleAuditAction.ENABLE, - outcome: 'unknown', - savedObject: { type: 'alert', id: rule.id }, - }) - ); - } catch (error) { - errors.push({ - message: error.message, - rule: { - id: rule.id, - name: rule.attributes?.name, - }, + context.auditLogger?.log( + ruleAuditEvent({ + action: RuleAuditAction.ENABLE, + outcome: 'unknown', + savedObject: { type: 'alert', id: rule.id }, + }) + ); + } catch (error) { + errors.push({ + message: error.message, + rule: { + id: rule.id, + name: rule.attributes?.name, + }, + }); + context.auditLogger?.log( + ruleAuditEvent({ + action: RuleAuditAction.ENABLE, + error, + }) + ); + } }); - context.auditLogger?.log( - ruleAuditEvent({ - action: RuleAuditAction.ENABLE, - error, - }) - ); } - }); - } - await rulesFinder.close(); + await rulesFinder.close(); + } + ); - const result = await context.unsecuredSavedObjectsClient.bulkCreate(rulesToEnable, { - overwrite: true, - }); + const result = await withSpan( + { name: 'unsecuredSavedObjectsClient.bulkCreate', type: 'rules' }, + () => + context.unsecuredSavedObjectsClient.bulkCreate(rulesToEnable, { + overwrite: true, + }) + ); const rules: Array> = []; + const taskIdsToEnable: string[] = []; result.saved_objects.forEach((rule) => { if (rule.error === undefined) { @@ -240,3 +234,49 @@ const bulkEnableRulesWithOCC = async ( }); return { errors, rules, accListSpecificForBulkOperation: [taskIdsToEnable] }; }; + +export const tryToEnableTasks = async ({ + taskIdsToEnable, + logger, + taskManager, +}: { + taskIdsToEnable: string[]; + logger: Logger; + taskManager: TaskManagerStartContract; +}) => { + const taskIdsFailedToBeEnabled: string[] = []; + + if (taskIdsToEnable.length > 0) { + try { + const resultFromEnablingTasks = await withSpan( + { name: 'taskManager.bulkEnable', type: 'rules' }, + async () => taskManager.bulkEnable(taskIdsToEnable) + ); + resultFromEnablingTasks?.errors?.forEach((error) => { + taskIdsFailedToBeEnabled.push(error.task.id); + }); + if (resultFromEnablingTasks.tasks.length) { + logger.debug( + `Successfully enabled schedules for underlying tasks: ${resultFromEnablingTasks.tasks + .map((task) => task.id) + .join(', ')}` + ); + } + if (resultFromEnablingTasks.errors.length) { + logger.error( + `Failure to enable schedules for underlying tasks: ${resultFromEnablingTasks.errors + .map((error) => error.task.id) + .join(', ')}` + ); + } + } catch (error) { + taskIdsFailedToBeEnabled.push(...taskIdsToEnable); + logger.error( + `Failure to enable schedules for underlying tasks: ${taskIdsToEnable.join( + ', ' + )}. TaskManager bulkEnable failed with Error: ${error.message}` + ); + } + } + return taskIdsFailedToBeEnabled; +}; diff --git a/x-pack/plugins/alerting/server/rules_client/methods/clone.ts b/x-pack/plugins/alerting/server/rules_client/methods/clone.ts index b4ebe5891885c..e1cabc50280e6 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/clone.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/clone.ts @@ -9,6 +9,7 @@ import Semver from 'semver'; import Boom from '@hapi/boom'; import { AlertConsumers } from '@kbn/rule-data-utils'; import { SavedObject, SavedObjectsUtils } from '@kbn/core/server'; +import { withSpan } from '@kbn/apm-utils'; import { RawRule, SanitizedRule, RuleTypeParams } from '../../types'; import { getDefaultMonitoring } from '../../lib'; import { WriteOperations, AlertingAuthorizationEntity } from '../../authorization'; @@ -30,12 +31,12 @@ export async function clone( let ruleSavedObject: SavedObject; try { - ruleSavedObject = await context.encryptedSavedObjectsClient.getDecryptedAsInternalUser( - 'alert', - id, - { - namespace: context.namespace, - } + ruleSavedObject = await withSpan( + { name: 'encryptedSavedObjectsClient.getDecryptedAsInternalUser', type: 'rules' }, + () => + context.encryptedSavedObjectsClient.getDecryptedAsInternalUser('alert', id, { + namespace: context.namespace, + }) ); } catch (e) { // We'll skip invalidating the API key since we failed to load the decrypted saved object @@ -43,7 +44,10 @@ export async function clone( `update(): Failed to load API key to invalidate on alert ${id}: ${e.message}` ); // Still attempt to load the object using SOC - ruleSavedObject = await context.unsecuredSavedObjectsClient.get('alert', id); + ruleSavedObject = await withSpan( + { name: 'unsecuredSavedObjectsClient.get', type: 'rules' }, + () => context.unsecuredSavedObjectsClient.get('alert', id) + ); } /* @@ -65,12 +69,14 @@ export async function clone( : `${ruleSavedObject.attributes.name} [Clone]`; const ruleId = newId ?? SavedObjectsUtils.generateId(); try { - await context.authorization.ensureAuthorized({ - ruleTypeId: ruleSavedObject.attributes.alertTypeId, - consumer: ruleSavedObject.attributes.consumer, - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }); + await withSpan({ name: 'authorization.ensureAuthorized', type: 'rules' }, () => + context.authorization.ensureAuthorized({ + ruleTypeId: ruleSavedObject.attributes.alertTypeId, + consumer: ruleSavedObject.attributes.consumer, + operation: WriteOperations.Create, + entity: AlertingAuthorizationEntity.Rule, + }) + ); } catch (error) { context.auditLogger?.log( ruleAuditEvent({ @@ -122,10 +128,12 @@ export async function clone( }) ); - return await createRuleSavedObject(context, { - intervalInMs: parseDuration(rawRule.schedule.interval), - rawRule, - references: ruleSavedObject.references, - ruleId, - }); + return await withSpan({ name: 'createRuleSavedObject', type: 'rules' }, () => + createRuleSavedObject(context, { + intervalInMs: parseDuration(rawRule.schedule.interval), + rawRule, + references: ruleSavedObject.references, + ruleId, + }) + ); } diff --git a/x-pack/plugins/alerting/server/rules_client/methods/create.ts b/x-pack/plugins/alerting/server/rules_client/methods/create.ts index 31707726b4e24..a0b5e26061a8d 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/create.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/create.ts @@ -7,6 +7,7 @@ import Semver from 'semver'; import Boom from '@hapi/boom'; import { SavedObjectsUtils } from '@kbn/core/server'; +import { withSpan } from '@kbn/apm-utils'; import { parseDuration } from '../../../common/parse_duration'; import { RawRule, SanitizedRule, RuleTypeParams, RuleAction, Rule } from '../../types'; import { WriteOperations, AlertingAuthorizationEntity } from '../../authorization'; @@ -52,12 +53,14 @@ export async function create( const id = options?.id || SavedObjectsUtils.generateId(); try { - await context.authorization.ensureAuthorized({ - ruleTypeId: data.alertTypeId, - consumer: data.consumer, - operation: WriteOperations.Create, - entity: AlertingAuthorizationEntity.Rule, - }); + await withSpan({ name: 'authorization.ensureAuthorized', type: 'rules' }, () => + context.authorization.ensureAuthorized({ + ruleTypeId: data.alertTypeId, + consumer: data.consumer, + operation: WriteOperations.Create, + entity: AlertingAuthorizationEntity.Rule, + }) + ); } catch (error) { context.auditLogger?.log( ruleAuditEvent({ @@ -80,14 +83,18 @@ export async function create( let createdAPIKey = null; try { createdAPIKey = data.enabled - ? await context.createAPIKey(generateAPIKeyName(ruleType.id, data.name)) + ? await withSpan({ name: 'createAPIKey', type: 'rules' }, () => + context.createAPIKey(generateAPIKeyName(ruleType.id, data.name)) + ) : null; } catch (error) { throw Boom.badRequest(`Error creating rule: could not create API key - ${error.message}`); } await validateActions(context, ruleType, data); - + await withSpan({ name: 'validateActions', type: 'rules' }, () => + validateActions(context, ruleType, data) + ); // Throw error if schedule interval is less than the minimum and we are enforcing it const intervalInMs = parseDuration(data.schedule.interval); if ( @@ -104,7 +111,9 @@ export async function create( references, params: updatedParams, actions, - } = await extractReferences(context, ruleType, data.actions, validatedAlertTypeParams); + } = await withSpan({ name: 'extractReferences', type: 'rules' }, () => + extractReferences(context, ruleType, data.actions, validatedAlertTypeParams) + ); const createTime = Date.now(); const lastRunTimestamp = new Date(); @@ -137,11 +146,13 @@ export async function create( rawRule.mapped_params = mappedParams; } - return await createRuleSavedObject(context, { - intervalInMs, - rawRule, - references, - ruleId: id, - options, - }); + return await withSpan({ name: 'createRuleSavedObject', type: 'rules' }, () => + createRuleSavedObject(context, { + intervalInMs, + rawRule, + references, + ruleId: id, + options, + }) + ); } diff --git a/x-pack/plugins/alerting/server/rules_client/methods/disable.ts b/x-pack/plugins/alerting/server/rules_client/methods/disable.ts index 3eae1d2df7b5d..bbdb1ade167eb 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/disable.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/disable.ts @@ -39,7 +39,7 @@ async function disableWithOCC(context: RulesClientContext, { id }: { id: string version = alert.version; } - recoverRuleAlerts(context, id, attributes); + await recoverRuleAlerts(context, id, attributes); try { await context.authorization.ensureAuthorized({ diff --git a/x-pack/plugins/alerting/server/rules_client/tests/bulk_enable.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/bulk_enable.test.ts index c4d3e1a253d95..dcb8b6e512c3f 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/bulk_enable.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/bulk_enable.test.ts @@ -318,6 +318,7 @@ describe('bulkEnableRules', () => { mockCreatePointInTimeFinderAsInternalUser({ saved_objects: [disabledRuleWithAction1, disabledRuleWithAction2], }); + actionsAuthorization.ensureAuthorized.mockImplementation(() => { throw new Error('UPS'); }); diff --git a/x-pack/plugins/alerting/tsconfig.json b/x-pack/plugins/alerting/tsconfig.json index 0d59ff6ac7865..a1fb0d3892d2a 100644 --- a/x-pack/plugins/alerting/tsconfig.json +++ b/x-pack/plugins/alerting/tsconfig.json @@ -36,6 +36,7 @@ "@kbn/core-logging-server-mocks", "@kbn/core-saved-objects-common", "@kbn/securitysolution-rules", + "@kbn/apm-utils", "@kbn/data-views-plugin", "@kbn/share-plugin", ], diff --git a/x-pack/plugins/apm/ftr_e2e/cypress.config.ts b/x-pack/plugins/apm/ftr_e2e/cypress.config.ts index 81a2939b9c9a4..16a0e8effb28a 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress.config.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress.config.ts @@ -32,6 +32,5 @@ export default defineCypressConfig({ baseUrl: 'http://localhost:5601', supportFile: './cypress/support/e2e.ts', specPattern: './cypress/e2e/**/*.cy.{js,jsx,ts,tsx}', - experimentalSessionAndOrigin: false, }, }); diff --git a/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/alert_details_app_section.tsx b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/alert_details_app_section.tsx index 92cd229333062..3bf792840ab71 100644 --- a/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/alert_details_app_section.tsx +++ b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/alert_details_app_section.tsx @@ -12,9 +12,13 @@ import { i18n } from '@kbn/i18n'; import { EuiPanel } from '@elastic/eui'; import { EuiTitle } from '@elastic/eui'; import { EuiIconTip } from '@elastic/eui'; -import { ALERT_DURATION, ALERT_END } from '@kbn/rule-data-utils'; +import { + ALERT_DURATION, + ALERT_END, + ALERT_EVALUATION_THRESHOLD, + ALERT_RULE_TYPE_ID, +} from '@kbn/rule-data-utils'; import moment from 'moment'; -import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values'; import { getTransactionType } from '../../../../context/apm_service/apm_service_context'; import { useServiceAgentFetcher } from '../../../../context/apm_service/use_service_agent_fetcher'; import { useServiceTransactionTypesFetcher } from '../../../../context/apm_service/use_service_transaction_types_fetcher'; @@ -41,9 +45,16 @@ import { SERVICE_NAME, TRANSACTION_TYPE, } from './types'; -import { getAggsTypeFromRule } from './helpers'; +import { getAggsTypeFromRule, isLatencyThresholdRuleType } from './helpers'; import { filterNil } from '../../../shared/charts/latency_chart'; import { errorRateI18n } from '../../../shared/charts/failed_transaction_rate_chart'; +import { + AlertActiveRect, + AlertAnnotation, + AlertThresholdRect, + AlertThresholdAnnotation, +} from './latency_chart_components'; +import { SERVICE_ENVIRONMENT } from '../../../../../common/es_fields/apm'; export function AlertDetailsAppSection({ rule, @@ -51,10 +62,8 @@ export function AlertDetailsAppSection({ timeZone, }: AlertDetailsAppSectionProps) { const params = rule.params; - const environment = String(params.environment) || ENVIRONMENT_ALL.value; - const latencyAggregationType = getAggsTypeFromRule( - params.aggregationType as string - ); + const environment = alert.fields[SERVICE_ENVIRONMENT]; + const latencyAggregationType = getAggsTypeFromRule(params.aggregationType); // duration is us, convert it to MS const alertDurationMS = alert.fields[ALERT_DURATION]! / 1000; @@ -103,7 +112,7 @@ export function AlertDetailsAppSection({ }); const transactionType = getTransactionType({ - transactionType: String(alert.fields[TRANSACTION_TYPE]), + transactionType: alert.fields[TRANSACTION_TYPE], transactionTypes, agentName, }); @@ -289,9 +298,32 @@ export function AlertDetailsAppSection({ }), }, ]; - /* Error Rate */ + const getLatencyChartAdditionalData = () => { + if (isLatencyThresholdRuleType(alert.fields[ALERT_RULE_TYPE_ID])) { + return [ + , + , + , + , + ]; + } + }; + return ( @@ -313,6 +345,7 @@ export function AlertDetailsAppSection({ + ruleTypeId === 'apm.transaction_duration'; diff --git a/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/alert_active_rect.tsx b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/alert_active_rect.tsx new file mode 100644 index 0000000000000..ff6d76165c1fa --- /dev/null +++ b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/alert_active_rect.tsx @@ -0,0 +1,32 @@ +/* + * 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 { RectAnnotation } from '@elastic/charts'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; + +export function AlertActiveRect({ alertStarted }: { alertStarted: number }) { + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/alert_annotation.tsx b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/alert_annotation.tsx new file mode 100644 index 0000000000000..27354ea2ac3b8 --- /dev/null +++ b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/alert_annotation.tsx @@ -0,0 +1,47 @@ +/* + * 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 { + AnnotationDomainType, + LineAnnotation, + Position, +} from '@elastic/charts'; +import moment from 'moment'; +import { EuiIcon } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { DEFAULT_DATE_FORMAT } from '../constants'; + +export function AlertAnnotation({ alertStarted }: { alertStarted: number }) { + return ( + } + markerPosition={Position.Top} + /> + ); +} diff --git a/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/alert_threshold_annotation.tsx b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/alert_threshold_annotation.tsx new file mode 100644 index 0000000000000..c1c6ddefd32f1 --- /dev/null +++ b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/alert_threshold_annotation.tsx @@ -0,0 +1,37 @@ +/* + * 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 { AnnotationDomainType, LineAnnotation } from '@elastic/charts'; + +export function AlertThresholdAnnotation({ + threshold, +}: { + threshold?: number; +}) { + if (!threshold) return <>; + + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/alert_threshold_rect.tsx b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/alert_threshold_rect.tsx new file mode 100644 index 0000000000000..24897dce1f63c --- /dev/null +++ b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/alert_threshold_rect.tsx @@ -0,0 +1,39 @@ +/* + * 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 { RectAnnotation } from '@elastic/charts'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; + +export function AlertThresholdRect({ + threshold, + alertStarted, +}: { + threshold?: number; + alertStarted: number; +}) { + if (!threshold) return <>; + + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/index.ts b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/index.ts new file mode 100644 index 0000000000000..a5d53b0ee3766 --- /dev/null +++ b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/latency_chart_components/index.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. + */ + +export { AlertAnnotation } from './alert_annotation'; +export { AlertThresholdRect } from './alert_threshold_rect'; +export { AlertActiveRect } from './alert_active_rect'; +export { AlertThresholdAnnotation } from './alert_threshold_annotation'; diff --git a/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/types.ts b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/types.ts index 0094d9332009a..99fafb00bcac0 100644 --- a/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/types.ts +++ b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/types.ts @@ -8,17 +8,21 @@ import { Rule } from '@kbn/alerting-plugin/common'; import { TopAlert } from '@kbn/observability-plugin/public/pages/alerts'; import { TIME_UNITS } from '@kbn/triggers-actions-ui-plugin/public'; -import { LatencyAggregationType } from '../../../../../common/latency_aggregation_types'; +import { SERVICE_ENVIRONMENT } from '../../../../../common/es_fields/apm'; export const SERVICE_NAME = 'service.name' as const; export const TRANSACTION_TYPE = 'transaction.type' as const; export interface AlertDetailsAppSectionProps { rule: Rule<{ environment: string; - aggregationType: LatencyAggregationType; + aggregationType: string; windowSize: number; windowUnit: TIME_UNITS; }>; - alert: TopAlert<{ [SERVICE_NAME]: string; [TRANSACTION_TYPE]: string }>; + alert: TopAlert<{ + [SERVICE_NAME]: string; + [TRANSACTION_TYPE]: string; + [SERVICE_ENVIRONMENT]: string; + }>; timeZone: string; } diff --git a/x-pack/plugins/apm/public/components/app/error_group_details/error_sampler/error_sample_detail.tsx b/x-pack/plugins/apm/public/components/app/error_group_details/error_sampler/error_sample_detail.tsx index 397bfa5e4c1a6..5366f467826c0 100644 --- a/x-pack/plugins/apm/public/components/app/error_group_details/error_sampler/error_sample_detail.tsx +++ b/x-pack/plugins/apm/public/components/app/error_group_details/error_sampler/error_sample_detail.tsx @@ -145,6 +145,7 @@ export function ErrorSampleDetails({ const status = error.http?.response?.status_code; const environment = error.service.environment; const serviceVersion = error.service.version; + const isUnhandled = error.error.exception?.[0].handled === false; const traceExplorerLink = router.link('/traces/explorer/waterfall', { query: { @@ -294,6 +295,13 @@ export function ErrorSampleDetails({ {serviceVersion} ) : null, + isUnhandled ? ( + + {i18n.translate('xpack.apm.errorGroupDetails.unhandledLabel', { + defaultMessage: 'Unhandled', + })} + + ) : null, ]} /> )} diff --git a/x-pack/plugins/apm/public/components/app/error_group_details/error_sampler/sample_summary.tsx b/x-pack/plugins/apm/public/components/app/error_group_details/error_sampler/sample_summary.tsx index af5bd2cc46b17..01fe2505d8b38 100644 --- a/x-pack/plugins/apm/public/components/app/error_group_details/error_sampler/sample_summary.tsx +++ b/x-pack/plugins/apm/public/components/app/error_group_details/error_sampler/sample_summary.tsx @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { EuiText, EuiSpacer, EuiCodeBlock, EuiBadge } from '@elastic/eui'; +import { EuiText, EuiSpacer, EuiCodeBlock } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; @@ -24,20 +24,9 @@ export function SampleSummary({ error }: Props) { const logMessage = error.error.log?.message; const excMessage = error.error.exception?.[0].message; const culprit = error.error.culprit; - const isUnhandled = error.error.exception?.[0].handled === false; return ( <> - {isUnhandled && ( - <> - - {i18n.translate('xpack.apm.errorGroupDetails.unhandledLabel', { - defaultMessage: 'Unhandled', - })} - - - - )} {logMessage && ( <> diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/waterfall_flyout.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/waterfall_flyout.tsx index 10333af97c6d8..29521134ff076 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/waterfall_flyout.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/waterfall_flyout.tsx @@ -36,6 +36,7 @@ export function WaterfallFlyout({ } = useAnyOfApmParams( '/services/{serviceName}/transactions/view', '/mobile-services/{serviceName}/transactions/view', + '/traces/explorer/waterfall', '/dependencies/operation' ); const currentItem = waterfall.items.find( diff --git a/x-pack/plugins/apm/public/components/routing/home/index.tsx b/x-pack/plugins/apm/public/components/routing/home/index.tsx index 4186dc7be9a0c..d0c251de08971 100644 --- a/x-pack/plugins/apm/public/components/routing/home/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/home/index.tsx @@ -159,16 +159,21 @@ export const home = { '/traces/explorer/waterfall': { element: , params: t.type({ - query: t.type({ - traceId: t.string, - transactionId: t.string, - waterfallItemId: t.string, - detailTab: t.union([ - t.literal(TransactionTab.timeline), - t.literal(TransactionTab.metadata), - t.literal(TransactionTab.logs), - ]), - }), + query: t.intersection([ + t.type({ + traceId: t.string, + transactionId: t.string, + waterfallItemId: t.string, + detailTab: t.union([ + t.literal(TransactionTab.timeline), + t.literal(TransactionTab.metadata), + t.literal(TransactionTab.logs), + ]), + }), + t.partial({ + flyoutDetailTab: t.string, + }), + ]), }), defaults: { query: { diff --git a/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx b/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx index 59d52658682d5..6f5bf5819e240 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx @@ -6,7 +6,6 @@ */ import { - AnnotationDomainType, AreaSeries, Axis, BarSeries, @@ -26,12 +25,11 @@ import { } from '@elastic/charts'; import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import React from 'react'; +import React, { ReactElement } from 'react'; import { useHistory } from 'react-router-dom'; import { useChartTheme } from '@kbn/observability-plugin/public'; import { isExpectedBoundsComparison } from '../time_comparison/get_comparison_options'; -import { asAbsoluteDateTime } from '../../../../common/utils/formatters'; -import { useAnnotationsContext } from '../../../context/annotations/use_annotations_context'; + import { useChartPointerEventContext } from '../../../context/chart_pointer_event/use_chart_pointer_event_context'; import { useTheme } from '../../../hooks/use_theme'; import { unit } from '../../../utils/style'; @@ -51,6 +49,9 @@ interface TimeseriesChartProps extends TimeseriesChartWithContextProps { comparisonEnabled: boolean; offset?: string; timeZone: string; + annotations?: Array< + ReactElement + >; } export function TimeseriesChart({ id, @@ -67,9 +68,9 @@ export function TimeseriesChart({ comparisonEnabled, offset, timeZone, + annotations, }: TimeseriesChartProps) { const history = useHistory(); - const { annotations } = useAnnotationsContext(); const { chartRef, updatePointerEvent } = useChartPointerEventContext(); const theme = useTheme(); const chartTheme = useChartTheme(); @@ -79,7 +80,6 @@ export function TimeseriesChart({ anomalyTimeseriesColor: anomalyTimeseries?.color, }); const isEmpty = isTimeseriesEmpty(timeseries); - const annotationColor = theme.eui.euiColorSuccess; const isComparingExpectedBounds = comparisonEnabled && isExpectedBoundsComparison(offset); const allSeries = [ @@ -219,26 +219,7 @@ export function TimeseriesChart({ tickFormat={yTickFormat ? yTickFormat : yLabelFormat} labelFormat={yLabelFormat} /> - - {showAnnotations && ( - ({ - dataValue: annotation['@timestamp'], - header: asAbsoluteDateTime(annotation['@timestamp']), - details: `${i18n.translate('xpack.apm.chart.annotation.version', { - defaultMessage: 'Version', - })} ${annotation.text}`, - }))} - style={{ - line: { strokeWidth: 1, stroke: annotationColor, opacity: 1 }, - }} - marker={} - markerPosition={Position.Top} - /> - )} - + {showAnnotations && annotations} - {allSeries.map((serie) => { const Series = getChartType(serie.type); diff --git a/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart_with_context.tsx b/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart_with_context.tsx index 5c9aac5d28bdf..101fe2b9c8967 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart_with_context.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart_with_context.tsx @@ -5,8 +5,18 @@ * 2.0. */ -import { LegendItemListener, YDomainRange } from '@elastic/charts'; +import { + AnnotationDomainType, + LegendItemListener, + LineAnnotation, + Position, + YDomainRange, +} from '@elastic/charts'; import React from 'react'; +import { EuiIcon } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { asAbsoluteDateTime } from '../../../../common/utils/formatters'; +import { useAnnotationsContext } from '../../../context/annotations/use_annotations_context'; import { useAnyOfApmParams } from '../../../hooks/use_apm_params'; import { ServiceAnomalyTimeseries } from '../../../../common/anomaly_detection/service_anomaly_timeseries'; import { Coordinate, TimeSeries } from '../../../../typings/timeseries'; @@ -15,6 +25,7 @@ import { FETCH_STATUS } from '../../../hooks/use_fetcher'; import { unit } from '../../../utils/style'; import { getTimeZone } from './helper/timezone'; import { TimeseriesChart } from './timeseries_chart'; +import { useTheme } from '../../../hooks/use_theme'; interface AnomalyTimeseries extends ServiceAnomalyTimeseries { color?: string; @@ -62,7 +73,28 @@ export function TimeseriesChartWithContext({ ); const { core } = useApmPluginContext(); const timeZone = getTimeZone(core.uiSettings); + const theme = useTheme(); + const annotationColor = theme.eui.euiColorSuccess; + const { annotations } = useAnnotationsContext(); + const getAnnotations = () => ( + ({ + dataValue: annotation['@timestamp'], + header: asAbsoluteDateTime(annotation['@timestamp']), + details: `${i18n.translate('xpack.apm.chart.annotation.version', { + defaultMessage: 'Version', + })} ${annotation.text}`, + }))} + style={{ + line: { strokeWidth: 1, stroke: annotationColor, opacity: 1 }, + }} + marker={} + markerPosition={Position.Top} + /> + ); return ( { } as unknown as ReturnType); }; -describe('AllCasesListGeneric', () => { +// Flaky: https://github.com/elastic/kibana/issues/148486 +describe.skip('AllCasesListGeneric', () => { const refetchCases = jest.fn(); const onRowClick = jest.fn(); const updateCaseProperty = jest.fn(); @@ -1085,7 +1086,8 @@ describe('AllCasesListGeneric', () => { }); }); -describe('Assignees', () => { +// Flaky: https://github.com/elastic/kibana/issues/148490 +describe.skip('Assignees', () => { it('should hide the assignees column on basic license', async () => { useLicenseMock.mockReturnValue({ isAtLeastPlatinum: () => false }); diff --git a/x-pack/plugins/cases/public/components/markdown_editor/renderer.tsx b/x-pack/plugins/cases/public/components/markdown_editor/renderer.tsx index 4831944f460b0..f896da64cf021 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/renderer.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/renderer.tsx @@ -42,7 +42,7 @@ const MarkdownRendererComponent: React.FC = ({ children, disableLinks, te {children} diff --git a/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx b/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx index 60b1a2bda3b6a..3ddb62eb4fb7a 100644 --- a/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx @@ -19,6 +19,10 @@ import { UserActionMarkdownFooter } from './markdown_form_footer'; export const ContentWrapper = styled.div` padding: ${({ theme }) => `${theme.eui.euiSizeM} ${theme.eui.euiSizeL}`}; + text-overflow: ellipsis; + word-break: break-word; + display: -webkit-box; + -webkit-box-orient: vertical; `; interface UserActionMarkdownProps { diff --git a/x-pack/plugins/cases/server/services/user_actions/__snapshots__/audit_logger.test.ts.snap b/x-pack/plugins/cases/server/services/user_actions/__snapshots__/audit_logger.test.ts.snap index b419945a73616..a5c52d6dc4298 100644 --- a/x-pack/plugins/cases/server/services/user_actions/__snapshots__/audit_logger.test.ts.snap +++ b/x-pack/plugins/cases/server/services/user_actions/__snapshots__/audit_logger.test.ts.snap @@ -8,6 +8,7 @@ Array [ "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], @@ -31,6 +32,7 @@ Array [ "category": Array [ "database", ], + "outcome": "success", "type": Array [ "creation", ], @@ -54,6 +56,7 @@ Array [ "category": Array [ "database", ], + "outcome": "success", "type": Array [ "deletion", ], @@ -77,8 +80,9 @@ Array [ "category": Array [ "database", ], + "outcome": "success", "type": Array [ - "creation", + "change", ], }, "kibana": Object { @@ -100,6 +104,7 @@ Array [ "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], diff --git a/x-pack/plugins/cases/server/services/user_actions/__snapshots__/index.test.ts.snap b/x-pack/plugins/cases/server/services/user_actions/__snapshots__/index.test.ts.snap index 6a576b04bc547..350fa6c55e134 100644 --- a/x-pack/plugins/cases/server/services/user_actions/__snapshots__/index.test.ts.snap +++ b/x-pack/plugins/cases/server/services/user_actions/__snapshots__/index.test.ts.snap @@ -8,6 +8,7 @@ Array [ "category": Array [ "database", ], + "outcome": "success", "type": Array [ "creation", ], @@ -31,6 +32,7 @@ Array [ "category": Array [ "database", ], + "outcome": "success", "type": Array [ "deletion", ], @@ -54,6 +56,7 @@ Array [ "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], diff --git a/x-pack/plugins/cases/server/services/user_actions/audit_logger.ts b/x-pack/plugins/cases/server/services/user_actions/audit_logger.ts index 63158e8a3d39e..82a016d2a0c3e 100644 --- a/x-pack/plugins/cases/server/services/user_actions/audit_logger.ts +++ b/x-pack/plugins/cases/server/services/user_actions/audit_logger.ts @@ -14,7 +14,7 @@ const actionsToEcsType: Record = { add: 'change', delete: 'deletion', create: 'creation', - push_to_service: 'creation', + push_to_service: 'change', update: 'change', }; @@ -32,6 +32,7 @@ export class UserActionAuditLogger { action: event.descriptiveAction, category: ['database'], type: [actionsToEcsType[event.action]], + outcome: 'success', }, kibana: { saved_object: { 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 5ba80b05f7194..e2aa6192cdccf 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 @@ -741,6 +741,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "creation", ], @@ -799,6 +800,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], @@ -858,6 +860,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], @@ -936,8 +939,9 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ - "creation", + "change", ], }, "kibana": Object { @@ -1030,6 +1034,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "deletion", ], @@ -1050,6 +1055,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "deletion", ], @@ -1255,6 +1261,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], @@ -1275,6 +1282,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], @@ -1295,6 +1303,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], @@ -1315,6 +1324,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], @@ -1335,6 +1345,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], @@ -1355,6 +1366,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "deletion", ], @@ -1375,6 +1387,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], @@ -1395,6 +1408,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], @@ -1477,6 +1491,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], @@ -1579,6 +1594,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "deletion", ], @@ -1709,6 +1725,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], @@ -1729,6 +1746,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "deletion", ], @@ -1836,6 +1854,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "change", ], @@ -1856,6 +1875,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "deletion", ], @@ -1951,6 +1971,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "deletion", ], @@ -1971,6 +1992,7 @@ describe('CaseUserActionService', () => { "category": Array [ "database", ], + "outcome": "success", "type": Array [ "deletion", ], diff --git a/x-pack/plugins/cloud_security_posture/common/constants.ts b/x-pack/plugins/cloud_security_posture/common/constants.ts index 797b29ad2be32..794ec8b912294 100644 --- a/x-pack/plugins/cloud_security_posture/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/common/constants.ts @@ -6,7 +6,7 @@ */ export const STATUS_ROUTE_PATH = '/internal/cloud_security_posture/status'; -export const STATS_ROUTE_PATH = '/internal/cloud_security_posture/stats'; +export const STATS_ROUTE_PATH = '/internal/cloud_security_posture/stats/{policy_template}'; export const BENCHMARKS_ROUTE_PATH = '/internal/cloud_security_posture/benchmarks'; export const CLOUD_SECURITY_POSTURE_PACKAGE_NAME = 'cloud_security_posture'; diff --git a/x-pack/plugins/cloud_security_posture/common/types.ts b/x-pack/plugins/cloud_security_posture/common/types.ts index 757ec5ebb0eb5..797cb5ddc86c4 100644 --- a/x-pack/plugins/cloud_security_posture/common/types.ts +++ b/x-pack/plugins/cloud_security_posture/common/types.ts @@ -76,6 +76,7 @@ interface BaseCspSetupStatus { installedPackagePolicies: number; healthyAgents: number; isPluginInitialized: boolean; + installedPolicyTemplates: PosturePolicyTemplate[]; } interface CspSetupNotInstalledStatus extends BaseCspSetupStatus { diff --git a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts index 37575e4adda42..d128713e6fdd6 100644 --- a/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts +++ b/x-pack/plugins/cloud_security_posture/common/utils/helpers.ts @@ -64,7 +64,8 @@ const getInputType = (inputType: string): string => { // Get the last part of the input type, input type structure: cloudbeat/ return inputType.split('/')[1]; }; -export const getCSPKuery = `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:${CLOUD_SECURITY_POSTURE_PACKAGE_NAME}`; + +export const CSP_FLEET_PACKAGE_KUERY = `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:${CLOUD_SECURITY_POSTURE_PACKAGE_NAME}`; export function assert(condition: any, msg?: string): asserts condition { if (!condition) { diff --git a/x-pack/plugins/cloud_security_posture/public/assets/icons/cis_eks_logo.svg b/x-pack/plugins/cloud_security_posture/public/assets/icons/cis_eks_logo.svg index e31c56edc8f08..f892a500e5ee3 100644 --- a/x-pack/plugins/cloud_security_posture/public/assets/icons/cis_eks_logo.svg +++ b/x-pack/plugins/cloud_security_posture/public/assets/icons/cis_eks_logo.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/x-pack/plugins/cloud_security_posture/public/assets/illustrations/no_data_illustration.svg b/x-pack/plugins/cloud_security_posture/public/assets/illustrations/no_data_illustration.svg new file mode 100644 index 0000000000000..025262d2513b0 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/assets/illustrations/no_data_illustration.svg @@ -0,0 +1 @@ + diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/index.ts b/x-pack/plugins/cloud_security_posture/public/common/api/index.ts index 2468e095ff5f9..fb3caf4fa9814 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/api/index.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/api/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export * from './use_compliance_dashboard_data_api'; +export * from './use_stats_api'; diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/use_compliance_dashboard_data_api.ts b/x-pack/plugins/cloud_security_posture/public/common/api/use_compliance_dashboard_data_api.ts deleted file mode 100644 index c1b108bb5f98a..0000000000000 --- a/x-pack/plugins/cloud_security_posture/public/common/api/use_compliance_dashboard_data_api.ts +++ /dev/null @@ -1,20 +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 { type QueryObserverOptions, useQuery } from '@tanstack/react-query'; -import { useKibana } from '../hooks/use_kibana'; -import { ComplianceDashboardData } from '../../../common/types'; -import { STATS_ROUTE_PATH } from '../../../common/constants'; - -const getStatsKey = ['csp_dashboard_stats']; - -export const useComplianceDashboardDataApi = ( - options: QueryObserverOptions -) => { - const { http } = useKibana().services; - return useQuery(getStatsKey, () => http.get(STATS_ROUTE_PATH), options); -}; diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/use_stats_api.ts b/x-pack/plugins/cloud_security_posture/public/common/api/use_stats_api.ts new file mode 100644 index 0000000000000..14c48b7a17208 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/common/api/use_stats_api.ts @@ -0,0 +1,43 @@ +/* + * 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 { useQuery, UseQueryOptions } from '@tanstack/react-query'; +import { useKibana } from '../hooks/use_kibana'; +import { PosturePolicyTemplate, ComplianceDashboardData } from '../../../common/types'; +import { STATS_ROUTE_PATH } from '../../../common/constants'; + +// TODO: consolidate both hooks into one hook with a dynamic key +const getCspmStatsKey = ['csp_cspm_dashboard_stats']; +const getKspmStatsKey = ['csp_kspm_dashboard_stats']; + +export const getStatsRoute = (policyTemplate: PosturePolicyTemplate) => { + return STATS_ROUTE_PATH.replace('{policy_template}', policyTemplate); +}; + +export const useCspmStatsApi = ( + options: UseQueryOptions +) => { + const { http } = useKibana().services; + return useQuery( + getCspmStatsKey, + // TODO: CIS AWS - remove casting and use actual policy template instead of benchmark_id + () => http.get(getStatsRoute('cis_aws' as PosturePolicyTemplate)), + options + ); +}; + +export const useKspmStatsApi = ( + options: UseQueryOptions +) => { + const { http } = useKibana().services; + return useQuery( + getKspmStatsKey, + // TODO: CIS AWS - remove casting and use actual policy template + () => http.get(getStatsRoute('cis_k8s' as PosturePolicyTemplate)), + options + ); +}; diff --git a/x-pack/plugins/cloud_security_posture/public/common/navigation/use_navigate_to_cis_integration.ts b/x-pack/plugins/cloud_security_posture/public/common/navigation/use_csp_integration_link.ts similarity index 80% rename from x-pack/plugins/cloud_security_posture/public/common/navigation/use_navigate_to_cis_integration.ts rename to x-pack/plugins/cloud_security_posture/public/common/navigation/use_csp_integration_link.ts index a19be2f8fd629..8d6e0f6c38583 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/navigation/use_navigate_to_cis_integration.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/navigation/use_csp_integration_link.ts @@ -6,11 +6,13 @@ */ import { pagePathGetters, pkgKeyFromPackageInfo } from '@kbn/fleet-plugin/public'; -import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../../../common/constants'; +import type { PosturePolicyTemplate } from '../../../common/types'; import { useCisKubernetesIntegration } from '../api/use_cis_kubernetes_integration'; import { useKibana } from '../hooks/use_kibana'; -export const useCISIntegrationLink = (): string | undefined => { +export const useCspIntegrationLink = ( + policyTemplate: PosturePolicyTemplate +): string | undefined => { const { http } = useKibana().services; const cisIntegration = useCisKubernetesIntegration(); @@ -18,7 +20,7 @@ export const useCISIntegrationLink = (): string | undefined => { const path = pagePathGetters .add_integration_to_policy({ - integration: CLOUD_SECURITY_POSTURE_PACKAGE_NAME, + integration: policyTemplate, pkgkey: pkgKeyFromPackageInfo({ name: cisIntegration.data.item.name, version: cisIntegration.data.item.version, diff --git a/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx index 5eba5fabe51df..749aa1ccb038a 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx @@ -24,12 +24,13 @@ import { UseQueryResult } from '@tanstack/react-query'; import { CloudPosturePage } from './cloud_posture_page'; import { NoDataPage } from '@kbn/kibana-react-plugin/public'; import { useCspSetupStatusApi } from '../common/api/use_setup_status_api'; -import { useCISIntegrationLink } from '../common/navigation/use_navigate_to_cis_integration'; +import { useCspIntegrationLink } from '../common/navigation/use_csp_integration_link'; const chance = new Chance(); + jest.mock('../common/api/use_setup_status_api'); -jest.mock('../common/navigation/use_navigate_to_cis_integration'); jest.mock('../common/hooks/use_subscription_status'); +jest.mock('../common/navigation/use_csp_integration_link'); describe('', () => { beforeEach(() => { @@ -146,7 +147,7 @@ describe('', () => { data: { status: 'not-installed' }, }) ); - (useCISIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); const children = chance.sentence(); renderCloudPosturePage({ children }); diff --git a/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.tsx b/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.tsx index da4038cc18854..027112add1517 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.tsx @@ -7,20 +7,32 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import type { UseQueryResult } from '@tanstack/react-query'; -import { EuiEmptyPrompt, EuiLink } from '@elastic/eui'; +import { + EuiButton, + EuiEmptyPrompt, + EuiImage, + EuiFlexGroup, + EuiFlexItem, + EuiLink, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { NoDataPage } from '@kbn/kibana-react-plugin/public'; +import { NoDataPage, NoDataPageProps } from '@kbn/kibana-react-plugin/public'; import { css } from '@emotion/react'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../common/constants'; import { SubscriptionNotAllowed } from './subscription_not_allowed'; import { useSubscriptionStatus } from '../common/hooks/use_subscription_status'; import { FullSizeCenteredPage } from './full_size_centered_page'; import { useCspSetupStatusApi } from '../common/api/use_setup_status_api'; import { CspLoadingState } from './csp_loading_state'; -import { useCISIntegrationLink } from '../common/navigation/use_navigate_to_cis_integration'; +import { useCspIntegrationLink } from '../common/navigation/use_csp_integration_link'; + +import noDataIllustration from '../assets/illustrations/no_data_illustration.svg'; export const LOADING_STATE_TEST_SUBJECT = 'cloud_posture_page_loading'; export const ERROR_STATE_TEST_SUBJECT = 'cloud_posture_page_error'; export const PACKAGE_NOT_INSTALLED_TEST_SUBJECT = 'cloud_posture_page_package_not_installed'; +export const CSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT = 'cloud_posture_page_cspm_not_installed'; +export const KSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT = 'cloud_posture_page_kspm_not_installed'; export const DEFAULT_NO_DATA_TEST_SUBJECT = 'cloud_posture_page_no_data'; export const SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT = 'cloud_posture_page_subscription_not_allowed'; @@ -45,49 +57,110 @@ export const isCommonError = (error: unknown): error is CommonError => { return true; }; -const packageNotInstalledRenderer = (cisIntegrationLink?: string) => ( - - ( + +); + +const packageNotInstalledRenderer = ({ + kspmIntegrationLink, + cspmIntegrationLink, +}: { + kspmIntegrationLink?: string; + cspmIntegrationLink?: string; +}) => { + return ( + + } + title={ +

+

+ } + layout="horizontal" + color="plain" + body={ +

+ + learnMore: ( + // TODO: CIS AWS - replace link with general doc for both integartions + ), }} /> - ), - }, - }} - /> - -); +

+ } + actions={ + + + + + + + + + + + + + } + /> +
+ ); +}; const defaultLoadingRenderer = () => ( @@ -172,7 +245,8 @@ export const CloudPosturePage = ({ }: CloudPosturePageProps) => { const subscriptionStatus = useSubscriptionStatus(); const getSetupStatus = useCspSetupStatusApi(); - const cisIntegrationLink = useCISIntegrationLink(); + const kspmIntegrationLink = useCspIntegrationLink(KSPM_POLICY_TEMPLATE); + const cspmIntegrationLink = useCspIntegrationLink(CSPM_POLICY_TEMPLATE); const render = () => { if (subscriptionStatus.isError) { @@ -196,7 +270,7 @@ export const CloudPosturePage = ({ } if (getSetupStatus.data.status === 'not-installed') { - return packageNotInstalledRenderer(cisIntegrationLink); + return packageNotInstalledRenderer({ kspmIntegrationLink, cspmIntegrationLink }); } if (!query) { diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts index dde25b7477543..afbd7ffac9bf8 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts @@ -19,7 +19,7 @@ import { SUPPORTED_POLICY_TEMPLATES, SUPPORTED_CLOUDBEAT_INPUTS, } from '../../../common/constants'; -import { type PostureInput, type PosturePolicyTemplate } from '../../../common/types'; +import type { PostureInput, PosturePolicyTemplate } from '../../../common/types'; import { assert } from '../../../common/utils/helpers'; import { cloudPostureIntegrations } from '../../common/constants'; diff --git a/x-pack/plugins/cloud_security_posture/public/components/test_subjects.ts b/x-pack/plugins/cloud_security_posture/public/components/test_subjects.ts index 4f154805aae05..95f3a83de9708 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/test_subjects.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/test_subjects.ts @@ -17,4 +17,5 @@ export const NO_FINDINGS_STATUS_TEST_SUBJ = { INDEXING: 'status-api-indexing', INDEX_TIMEOUT: 'status-api-index-timeout', UNPRIVILEGED: 'status-api-unprivileged', + NO_FINDINGS: 'no-findings-found', }; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.test.tsx index f9172a93457dc..1d8b3d6e55a91 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.test.tsx @@ -16,12 +16,13 @@ import * as TEST_SUBJ from './test_subjects'; import { useCspBenchmarkIntegrations } from './use_csp_benchmark_integrations'; import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import { useSubscriptionStatus } from '../../common/hooks/use_subscription_status'; -import { useCISIntegrationLink } from '../../common/navigation/use_navigate_to_cis_integration'; +import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; jest.mock('./use_csp_benchmark_integrations'); jest.mock('../../common/api/use_setup_status_api'); jest.mock('../../common/hooks/use_subscription_status'); -jest.mock('../../common/navigation/use_navigate_to_cis_integration'); +jest.mock('../../common/navigation/use_csp_integration_link'); + const chance = new Chance(); describe('', () => { @@ -41,7 +42,7 @@ describe('', () => { }) ); - (useCISIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); }); const renderBenchmarks = ( diff --git a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.tsx b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.tsx index 29bc94dd739ec..b013f6b33dac5 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.tsx @@ -7,22 +7,23 @@ import React, { useState } from 'react'; import { + EuiButton, EuiFieldSearch, EuiFieldSearchProps, - EuiButton, - EuiSpacer, EuiFlexGroup, EuiFlexItem, - EuiTextColor, - EuiText, EuiPageHeader, + EuiSpacer, + EuiText, + EuiTextColor, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import useDebounce from 'react-use/lib/useDebounce'; import { i18n } from '@kbn/i18n'; +import { KSPM_POLICY_TEMPLATE } from '../../../common/constants'; +import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; import { CloudPosturePageTitle } from '../../components/cloud_posture_page_title'; import { CloudPosturePage } from '../../components/cloud_posture_page'; -import { useCISIntegrationLink } from '../../common/navigation/use_navigate_to_cis_integration'; import { BenchmarksTable } from './benchmarks_table'; import { useCspBenchmarkIntegrations, @@ -35,8 +36,9 @@ import { usePageSize } from '../../common/hooks/use_page_size'; const SEARCH_DEBOUNCE_MS = 300; +// TODO: CIS AWS - add cspm integration button as well const AddCisIntegrationButton = () => { - const cisIntegrationLink = useCISIntegrationLink(); + const cisIntegrationLink = useCspIntegrationLink(KSPM_POLICY_TEMPLATE); return (
- + diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx index d7a03e0cb679c..6aace059a5cc4 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx @@ -13,20 +13,25 @@ import { TestProvider } from '../../test/test_provider'; import { ComplianceDashboard } from '.'; import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import { useSubscriptionStatus } from '../../common/hooks/use_subscription_status'; -import { useComplianceDashboardDataApi } from '../../common/api/use_compliance_dashboard_data_api'; -import { DASHBOARD_CONTAINER } from './test_subjects'; +import { useKspmStatsApi, useCspmStatsApi } from '../../common/api/use_stats_api'; +import { + CLOUD_DASHBOARD_CONTAINER, + DASHBOARD_CONTAINER, + KUBERNETES_DASHBOARD_CONTAINER, +} from './test_subjects'; import { createReactQueryResponse } from '../../test/fixtures/react_query'; import { NO_FINDINGS_STATUS_TEST_SUBJ } from '../../components/test_subjects'; import { useCISIntegrationPoliciesLink } from '../../common/navigation/use_navigate_to_cis_integration_policies'; -import { useCISIntegrationLink } from '../../common/navigation/use_navigate_to_cis_integration'; +import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; import { expectIdsInDoc } from '../../test/utils'; import { ComplianceDashboardData } from '../../../common/types'; jest.mock('../../common/api/use_setup_status_api'); -jest.mock('../../common/api/use_compliance_dashboard_data_api'); +jest.mock('../../common/api/use_stats_api'); jest.mock('../../common/hooks/use_subscription_status'); jest.mock('../../common/navigation/use_navigate_to_cis_integration_policies'); -jest.mock('../../common/navigation/use_navigate_to_cis_integration'); +jest.mock('../../common/navigation/use_csp_integration_link'); + const chance = new Chance(); export const mockDashboardData: ComplianceDashboardData = { @@ -205,6 +210,17 @@ describe('', () => { data: true, }) ); + + (useCspmStatsApi as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + }) + ); + (useKspmStatsApi as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + }) + ); }); const renderComplianceDashboardPage = () => { @@ -233,11 +249,11 @@ describe('', () => { (useCspSetupStatusApi as jest.Mock).mockImplementation(() => createReactQueryResponse({ status: 'success', - data: { status: 'not-deployed' }, + data: { status: 'not-deployed', installedPolicyTemplates: [] }, }) ); (useCISIntegrationPoliciesLink as jest.Mock).mockImplementation(() => chance.url()); - (useCISIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); renderComplianceDashboardPage(); @@ -256,10 +272,10 @@ describe('', () => { (useCspSetupStatusApi as jest.Mock).mockImplementation(() => createReactQueryResponse({ status: 'success', - data: { status: 'indexing' }, + data: { status: 'indexing', installedPolicyTemplates: [] }, }) ); - (useCISIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); renderComplianceDashboardPage(); @@ -278,10 +294,10 @@ describe('', () => { (useCspSetupStatusApi as jest.Mock).mockImplementation(() => createReactQueryResponse({ status: 'success', - data: { status: 'index-timeout' }, + data: { status: 'index-timeout', installedPolicyTemplates: [] }, }) ); - (useCISIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); renderComplianceDashboardPage(); @@ -300,10 +316,10 @@ describe('', () => { (useCspSetupStatusApi as jest.Mock).mockImplementation(() => createReactQueryResponse({ status: 'success', - data: { status: 'unprivileged' }, + data: { status: 'unprivileged', installedPolicyTemplates: [] }, }) ); - (useCISIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); renderComplianceDashboardPage(); @@ -319,7 +335,18 @@ describe('', () => { }); it('shows dashboard when there are findings in latest findings index', () => { - (useComplianceDashboardDataApi as jest.Mock).mockImplementation(() => ({ + (useCspSetupStatusApi as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + data: { status: 'indexed', installedPolicyTemplates: ['cspm', 'kspm'] }, + }) + ); + (useKspmStatsApi as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: mockDashboardData, + })); + (useCspmStatsApi as jest.Mock).mockImplementation(() => ({ isSuccess: true, isLoading: false, data: mockDashboardData, @@ -337,4 +364,196 @@ describe('', () => { ], }); }); + + it('Show Kubernetes dashboard if there are KSPM findings', () => { + (useCspSetupStatusApi as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + data: { status: 'indexed', installedPolicyTemplates: ['cspm', 'kspm'] }, + }) + ); + (useKspmStatsApi as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: mockDashboardData, + })); + (useCspmStatsApi as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: undefined, + })); + + renderComplianceDashboardPage(); + + expectIdsInDoc({ + be: [KUBERNETES_DASHBOARD_CONTAINER], + notToBe: [ + CLOUD_DASHBOARD_CONTAINER, + NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT, + NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED, + NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING, + NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED, + ], + }); + }); + + it('Show Cloud dashboard if there are CSPM findings', () => { + (useCspSetupStatusApi as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + data: { status: 'indexed', installedPolicyTemplates: ['cspm', 'kspm'] }, + }) + ); + (useKspmStatsApi as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: undefined, + })); + (useCspmStatsApi as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: mockDashboardData, + })); + + renderComplianceDashboardPage(); + + expectIdsInDoc({ + be: [CLOUD_DASHBOARD_CONTAINER], + notToBe: [ + KUBERNETES_DASHBOARD_CONTAINER, + NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT, + NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED, + NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING, + NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED, + ], + }); + }); + + it('Show Cloud dashboard "no findings prompt" if the CSPM integration is installed without findings', () => { + (useCspSetupStatusApi as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + data: { status: 'indexed', installedPolicyTemplates: ['cspm'] }, + }) + ); + (useKspmStatsApi as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: { stats: { totalFindings: 0 } }, + })); + (useCspmStatsApi as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: { stats: { totalFindings: 0 } }, + })); + + renderComplianceDashboardPage(); + + expectIdsInDoc({ + be: [CLOUD_DASHBOARD_CONTAINER, NO_FINDINGS_STATUS_TEST_SUBJ.NO_FINDINGS], + notToBe: [ + KUBERNETES_DASHBOARD_CONTAINER, + NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT, + NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED, + NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING, + NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED, + ], + }); + }); + + it('Show Kubernetes dashboard "no findings prompt" if the KSPM integration is installed without findings', () => { + (useCspSetupStatusApi as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + data: { status: 'indexed', installedPolicyTemplates: ['kspm'] }, + }) + ); + (useKspmStatsApi as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: { stats: { totalFindings: 0 } }, + })); + (useCspmStatsApi as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: { stats: { totalFindings: 0 } }, + })); + + renderComplianceDashboardPage(); + + expectIdsInDoc({ + be: [KUBERNETES_DASHBOARD_CONTAINER, NO_FINDINGS_STATUS_TEST_SUBJ.NO_FINDINGS], + notToBe: [ + CLOUD_DASHBOARD_CONTAINER, + NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT, + NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED, + NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING, + NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED, + ], + }); + }); + + it('Prefer Cloud dashboard if both integration are installed', () => { + (useCspSetupStatusApi as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + data: { status: 'indexed', installedPolicyTemplates: ['cspm', 'kspm'] }, + }) + ); + (useKspmStatsApi as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: { stats: { totalFindings: 0 } }, + })); + (useCspmStatsApi as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: { stats: { totalFindings: 0 } }, + })); + + renderComplianceDashboardPage(); + + expectIdsInDoc({ + be: [CLOUD_DASHBOARD_CONTAINER, NO_FINDINGS_STATUS_TEST_SUBJ.NO_FINDINGS], + notToBe: [ + KUBERNETES_DASHBOARD_CONTAINER, + NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT, + NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED, + NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING, + NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED, + ], + }); + }); + + it('Prefer Cloud dashboard if both integration have findings', () => { + (useCspSetupStatusApi as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + data: { status: 'indexed', installedPolicyTemplates: ['cspm', 'kspm'] }, + }) + ); + (useKspmStatsApi as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: mockDashboardData, + })); + (useCspmStatsApi as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: mockDashboardData, + })); + + renderComplianceDashboardPage(); + + expectIdsInDoc({ + be: [CLOUD_DASHBOARD_CONTAINER], + notToBe: [ + KUBERNETES_DASHBOARD_CONTAINER, + NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT, + NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED, + NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING, + NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED, + ], + }); + }); }); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx index 33fa8756c631d..78ee59684896c 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx @@ -5,30 +5,284 @@ * 2.0. */ -import React from 'react'; -import { EuiSpacer, EuiPageHeader } from '@elastic/eui'; +import React, { useEffect, useMemo, useState } from 'react'; +import { EuiEmptyPrompt, EuiIcon, EuiLink, EuiPageHeader, EuiSpacer } from '@elastic/eui'; import { css } from '@emotion/react'; import { i18n } from '@kbn/i18n'; -import { CloudSummarySection } from './dashboard_sections/cloud_summary_section'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { NO_FINDINGS_STATUS_TEST_SUBJ } from '../../components/test_subjects'; +import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; +import type { PosturePolicyTemplate, ComplianceDashboardData } from '../../../common/types'; import { CloudPosturePageTitle } from '../../components/cloud_posture_page_title'; -import { CloudPosturePage } from '../../components/cloud_posture_page'; -import { DASHBOARD_CONTAINER } from './test_subjects'; -import { useComplianceDashboardDataApi } from '../../common/api'; +import { + CloudPosturePage, + CspNoDataPage, + CspNoDataPageProps, + KSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT, + CSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT, +} from '../../components/cloud_posture_page'; +import { + CLOUD_DASHBOARD_CONTAINER, + DASHBOARD_CONTAINER, + KUBERNETES_DASHBOARD_CONTAINER, +} from './test_subjects'; +import { useCspmStatsApi, useKspmStatsApi } from '../../common/api'; import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import { NoFindingsStates } from '../../components/no_findings_states'; +import { CloudSummarySection } from './dashboard_sections/cloud_summary_section'; import { CloudBenchmarksSection } from './dashboard_sections/cloud_benchmarks_section'; +import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../../common/constants'; + +const noDataOptions: Record< + PosturePolicyTemplate, + Pick & { testId: string } +> = { + kspm: { + testId: KSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT, + docsLink: 'https://ela.st/kspm', + actionTitle: i18n.translate( + 'xpack.csp.cloudPosturePage.kspmIntegration.packageNotInstalled.buttonLabel', + { defaultMessage: 'Add a KSPM integration' } + ), + actionDescription: ( + + + + ), + }} + /> + ), + }, + cspm: { + testId: CSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT, + // TODO: CIS AWS - replace link or create the docs + docsLink: 'https://ela.st/cspm', + actionTitle: i18n.translate( + 'xpack.csp.cloudPosturePage.cspmIntegration.packageNotInstalled.buttonLabel', + { defaultMessage: 'Add a CSPM integration' } + ), + actionDescription: ( + + + + ), + }} + /> + ), + }, +}; + +const getNotInstalledConfig = ( + policyTemplate: PosturePolicyTemplate, + actionHref: CspNoDataPageProps['actionHref'] +) => { + const policyTemplateNoDataConfig = noDataOptions[policyTemplate]; + + return { + pageTitle: i18n.translate('xpack.csp.cloudPosturePage.packageNotInstalled.pageTitle', { + defaultMessage: 'Install Integration to get started', + }), + docsLink: policyTemplateNoDataConfig.docsLink, + actionHref, + actionTitle: policyTemplateNoDataConfig.actionTitle, + actionDescription: policyTemplateNoDataConfig.actionDescription, + testId: policyTemplateNoDataConfig.testId, + }; +}; + +const KIBANA_HEADERS_HEIGHT = 265; + +const IntegrationPostureDashboard = ({ + complianceData, + notInstalledConfig, + isIntegrationInstalled, +}: { + complianceData: ComplianceDashboardData | undefined; + notInstalledConfig: CspNoDataPageProps; + isIntegrationInstalled?: boolean; +}) => { + const noFindings = !complianceData || complianceData.stats.totalFindings === 0; + + // integration is not installed, and there are no findings for this integration + if (noFindings && !isIntegrationInstalled) { + return ; + } + + // integration is installed, but there are no findings for this integration + if (noFindings) { + return ( + // height is calculated for the screen height minus the kibana header, page title, and tabs +
+ } + title={ +

+ +

+ } + body={ +

+ +

+ } + /> +
+ ); + } + + // there are findings, displays dashboard even if integration is not installed + return ( + <> + + + + + + ); +}; export const ComplianceDashboard = () => { + const [selectedTab, setSelectedTab] = useState(CSPM_POLICY_TEMPLATE); const getSetupStatus = useCspSetupStatusApi(); const hasFindings = getSetupStatus.data?.status === 'indexed'; - const getDashboardData = useComplianceDashboardDataApi({ + const cspmIntegrationLink = useCspIntegrationLink(CSPM_POLICY_TEMPLATE); + const kspmIntegrationLink = useCspIntegrationLink(KSPM_POLICY_TEMPLATE); + + const getCspmDashboardData = useCspmStatsApi({ enabled: hasFindings, }); + const getKspmDashboardData = useKspmStatsApi({ + enabled: hasFindings, + }); + + useEffect(() => { + const selectInitialTab = () => { + const cspmTotalFindings = getCspmDashboardData.data?.stats.totalFindings; + const kspmTotalFindings = getKspmDashboardData.data?.stats.totalFindings; + const installedPolicyTemplates = getSetupStatus.data?.installedPolicyTemplates; + + let preferredDashboard = CSPM_POLICY_TEMPLATE; + + // cspm has findings + if (!!cspmTotalFindings) { + preferredDashboard = CSPM_POLICY_TEMPLATE; + } + // kspm has findings + else if (!!kspmTotalFindings) { + preferredDashboard = KSPM_POLICY_TEMPLATE; + } + // cspm is installed + else if (installedPolicyTemplates?.includes(CSPM_POLICY_TEMPLATE)) { + preferredDashboard = CSPM_POLICY_TEMPLATE; + } + // kspm is installed + else if (installedPolicyTemplates?.includes(KSPM_POLICY_TEMPLATE)) { + preferredDashboard = KSPM_POLICY_TEMPLATE; + } + + setSelectedTab(preferredDashboard); + }; + selectInitialTab(); + }, [ + getCspmDashboardData.data?.stats.totalFindings, + getKspmDashboardData.data?.stats.totalFindings, + getSetupStatus.data?.installedPolicyTemplates, + ]); + + const tabs = useMemo( + () => [ + { + label: i18n.translate('xpack.csp.dashboardTabs.cloudTab.tabTitle', { + defaultMessage: 'Cloud', + }), + isSelected: selectedTab === CSPM_POLICY_TEMPLATE, + onClick: () => setSelectedTab(CSPM_POLICY_TEMPLATE), + content: ( + +
+ +
+
+ ), + }, + { + label: i18n.translate('xpack.csp.dashboardTabs.kubernetesTab.tabTitle', { + defaultMessage: 'Kubernetes', + }), + isSelected: selectedTab === KSPM_POLICY_TEMPLATE, + onClick: () => setSelectedTab(KSPM_POLICY_TEMPLATE), + content: ( + +
+ +
+
+ ), + }, + ], + [ + cspmIntegrationLink, + getCspmDashboardData, + getKspmDashboardData, + getSetupStatus.data?.installedPolicyTemplates, + kspmIntegrationLink, + selectedTab, + ] + ); if (!hasFindings) return ; return ( - + { })} /> } + tabs={tabs.map(({ content, ...rest }) => rest)} />
- <> - - - - - + {tabs.find((t) => t.isSelected)?.content}
); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/cloud_benchmarks_section.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/cloud_benchmarks_section.tsx index 288a41d0a7a96..5ab9552d5d2da 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/cloud_benchmarks_section.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/cloud_benchmarks_section.tsx @@ -49,7 +49,6 @@ export const CloudBenchmarksSection = ({ style={{ borderBottom: euiTheme.border.thick, borderBottomColor: euiTheme.colors.text, - marginBottom: euiTheme.size.m, paddingBottom: euiTheme.size.s, }} > @@ -91,51 +90,52 @@ export const CloudBenchmarksSection = ({
{complianceData.clusters.map((cluster) => ( - - - - - -
- - handleEvalCounterClick(cluster.meta.clusterId, evaluation) - } - /> -
-
- -
- - handleCellClick(cluster.meta.clusterId, resourceTypeName) - } - viewAllButtonTitle={i18n.translate( - 'xpack.csp.dashboard.risksTable.clusterCardViewAllButtonTitle', - { defaultMessage: 'View all failed findings for this cluster' } - )} - onViewAllClick={() => handleViewAllClick(cluster.meta.clusterId)} - /> -
-
-
+ + + + + + +
+ + handleEvalCounterClick(cluster.meta.clusterId, evaluation) + } + /> +
+
+ +
+ + handleCellClick(cluster.meta.clusterId, resourceTypeName) + } + viewAllButtonTitle={i18n.translate( + 'xpack.csp.dashboard.risksTable.clusterCardViewAllButtonTitle', + { defaultMessage: 'View all failed findings for this cluster' } + )} + onViewAllClick={() => handleViewAllClick(cluster.meta.clusterId)} + /> +
+
+
+
))} ); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/test_subjects.ts b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/test_subjects.ts index 50b4e7a2b03d3..264f848dd5886 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/test_subjects.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/test_subjects.ts @@ -7,6 +7,8 @@ export const MISSING_FINDINGS_NO_DATA_CONFIG = 'missing-findings-no-data-config'; export const DASHBOARD_CONTAINER = 'dashboard-container'; +export const KUBERNETES_DASHBOARD_CONTAINER = 'kubernetes-dashboard-container'; +export const CLOUD_DASHBOARD_CONTAINER = 'cloud-dashboard-container'; export const DASHBOARD_COUNTER_CARDS = { CLUSTERS_EVALUATED: 'dashboard-counter-card-clusters-evaluated', RESOURCES_EVALUATED: 'dashboard-counter-card-resources-evaluated', diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.test.tsx index 70420f61d2176..02f2ec8ffee73 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.test.tsx @@ -23,7 +23,7 @@ import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import { useSubscriptionStatus } from '../../common/hooks/use_subscription_status'; import { createReactQueryResponse } from '../../test/fixtures/react_query'; import { useCISIntegrationPoliciesLink } from '../../common/navigation/use_navigate_to_cis_integration_policies'; -import { useCISIntegrationLink } from '../../common/navigation/use_navigate_to_cis_integration'; +import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; import { NO_FINDINGS_STATUS_TEST_SUBJ } from '../../components/test_subjects'; import { render } from '@testing-library/react'; import { expectIdsInDoc } from '../../test/utils'; @@ -34,7 +34,8 @@ jest.mock('../../common/api/use_latest_findings_data_view'); jest.mock('../../common/api/use_setup_status_api'); jest.mock('../../common/hooks/use_subscription_status'); jest.mock('../../common/navigation/use_navigate_to_cis_integration_policies'); -jest.mock('../../common/navigation/use_navigate_to_cis_integration'); +jest.mock('../../common/navigation/use_csp_integration_link'); + const chance = new Chance(); beforeEach(() => { @@ -74,7 +75,7 @@ describe('', () => { }) ); (useCISIntegrationPoliciesLink as jest.Mock).mockImplementation(() => chance.url()); - (useCISIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); renderFindingsPage(); @@ -96,7 +97,7 @@ describe('', () => { data: { status: 'indexing' }, }) ); - (useCISIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); renderFindingsPage(); @@ -118,7 +119,7 @@ describe('', () => { data: { status: 'index-timeout' }, }) ); - (useCISIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); renderFindingsPage(); @@ -140,7 +141,7 @@ describe('', () => { data: { status: 'unprivileged' }, }) ); - (useCISIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); renderFindingsPage(); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx index 45e19b9fba5bd..762df0380a6d2 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx @@ -19,14 +19,15 @@ import { createReactQueryResponse } from '../../test/fixtures/react_query'; import { coreMock } from '@kbn/core/public/mocks'; import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import { useSubscriptionStatus } from '../../common/hooks/use_subscription_status'; -import { useCISIntegrationLink } from '../../common/navigation/use_navigate_to_cis_integration'; +import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; jest.mock('./use_csp_integration', () => ({ useCspIntegrationInfo: jest.fn(), })); jest.mock('../../common/api/use_setup_status_api'); jest.mock('../../common/hooks/use_subscription_status'); -jest.mock('../../common/navigation/use_navigate_to_cis_integration'); +jest.mock('../../common/navigation/use_csp_integration_link'); + const chance = new Chance(); const queryClient = new QueryClient({ @@ -78,7 +79,7 @@ describe('', () => { }) ); - (useCISIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); }); it('calls API with URL params', async () => { diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts index 22097dbfc69fd..0e9cf02ad0663 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts @@ -9,7 +9,7 @@ import { SavedObjectsClientContract } from '@kbn/core/server'; import { PackagePolicyClient } from '@kbn/fleet-plugin/server'; import { PackagePolicy } from '@kbn/fleet-plugin/common'; import { DataViewSavedObjectAttrs } from '@kbn/data-views-plugin/common'; -import { getCSPKuery } from '../../common/utils/helpers'; +import { CSP_FLEET_PACKAGE_KUERY } from '../../common/utils/helpers'; import { CLOUD_SECURITY_POSTURE_PACKAGE_NAME } from '../../common/constants'; export const onPackagePolicyPostCreateCallback = async ( @@ -41,7 +41,7 @@ export const isCspPackagePolicyInstalled = async ( ): Promise => { try { const { total } = await packagePolicyClient.list(soClient, { - kuery: getCSPKuery, + kuery: CSP_FLEET_PACKAGE_KUERY, page: 1, }); diff --git a/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts b/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts index 7d348f2d70250..ada8548240ae9 100644 --- a/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts +++ b/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts @@ -4,19 +4,22 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { uniq, map } from 'lodash'; +import { map, uniq } from 'lodash'; import type { SavedObjectsClientContract } from '@kbn/core/server'; import type { - PackagePolicyClient, AgentPolicyServiceInterface, AgentService, + PackagePolicyClient, } from '@kbn/fleet-plugin/server'; import type { - GetAgentStatusResponse, - PackagePolicy, AgentPolicy, + GetAgentStatusResponse, ListResult, + PackagePolicy, } from '@kbn/fleet-plugin/common'; +import { PosturePolicyTemplate } from '../../common/types'; +import { SUPPORTED_POLICY_TEMPLATES } from '../../common/constants'; +import { CSP_FLEET_PACKAGE_KUERY } from '../../common/utils/helpers'; import { BENCHMARK_PACKAGE_POLICY_PREFIX, BenchmarksQueryParams, @@ -24,6 +27,9 @@ import { export const PACKAGE_POLICY_SAVED_OBJECT_TYPE = 'ingest-package-policies'; +const isPolicyTemplate = (input: any): input is PosturePolicyTemplate => + SUPPORTED_POLICY_TEMPLATES.includes(input); + const getPackageNameQuery = (packageName: string, benchmarkFilter?: string): string => { const integrationNameQuery = `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:${packageName}`; const kquery = benchmarkFilter @@ -79,3 +85,28 @@ export const getCspPackagePolicies = ( sortOrder: queryParams.sort_order, }); }; + +export const getInstalledPolicyTemplates = async ( + packagePolicyClient: PackagePolicyClient, + soClient: SavedObjectsClientContract +) => { + try { + // getting all installed csp package policies + const queryResult = await packagePolicyClient.list(soClient, { + kuery: CSP_FLEET_PACKAGE_KUERY, + perPage: 1000, + }); + + // getting installed policy templates by findings enabled inputs + const enabledPolicyTemplates = queryResult.items + .map((policy) => { + return policy.inputs.find((input) => input.enabled)?.policy_template; + }) + .filter(isPolicyTemplate); + + // removing duplicates + return [...new Set(enabledPolicyTemplates)]; + } catch (e) { + return []; + } +}; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts index 00c32f1b46f4a..eafacfac12f4e 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts @@ -69,7 +69,7 @@ const createBenchmarks = ( const agentPolicyStatus = { id: agentPolicy.id, name: agentPolicy.name, - agents: agentStatusByAgentPolicyId[agentPolicy.id].total, + agents: agentStatusByAgentPolicyId[agentPolicy.id]?.total, }; return { package_policy: cspPackage, diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/compliance_dashboard.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/compliance_dashboard.ts index aa82b5844ce26..b59ad93d8f254 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/compliance_dashboard.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/compliance_dashboard.ts @@ -7,7 +7,8 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import type { ComplianceDashboardData } from '../../../common/types'; +import { schema } from '@kbn/config-schema'; +import type { PosturePolicyTemplate, ComplianceDashboardData } from '../../../common/types'; import { LATEST_FINDINGS_INDEX_DEFAULT_NS, STATS_ROUTE_PATH } from '../../../common/constants'; import { getGroupedFindingsEvaluation } from './get_grouped_findings_evaluation'; import { ClusterWithoutTrend, getClusters } from './get_clusters'; @@ -32,16 +33,23 @@ const getClustersTrends = (clustersWithoutTrends: ClusterWithoutTrend[], trends: const getSummaryTrend = (trends: Trends) => trends.map(({ timestamp, summary }) => ({ timestamp, ...summary })); +const queryParamsSchema = { + params: schema.object({ + // TODO: CIS AWS - replace with strict policy template values once available + policy_template: schema.string(), + }), +}; + export const defineGetComplianceDashboardRoute = (router: CspRouter): void => router.get( { path: STATS_ROUTE_PATH, - validate: false, + validate: queryParamsSchema, options: { tags: ['access:cloud-security-posture-read'], }, }, - async (context, _, response) => { + async (context, request, response) => { const cspContext = await context.csp; try { @@ -52,8 +60,13 @@ export const defineGetComplianceDashboardRoute = (router: CspRouter): void => keep_alive: '30s', }); + const policyTemplate = request.params.policy_template as PosturePolicyTemplate; + const query: QueryDslQueryContainer = { - match_all: {}, + bool: { + // TODO: CIS AWS - replace filtered field to `policy_template` when available + filter: [{ term: { 'rule.benchmark.id': policyTemplate } }], + }, }; const [stats, groupedFindingsEvaluation, clustersWithoutTrends, trends] = await Promise.all( @@ -61,7 +74,7 @@ export const defineGetComplianceDashboardRoute = (router: CspRouter): void => getStats(esClient, query, pitId), getGroupedFindingsEvaluation(esClient, query, pitId), getClusters(esClient, query, pitId), - getTrends(esClient), + getTrends(esClient, policyTemplate), ] ); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.test.ts index 9c006a0ccbecc..aff4e39f9d49c 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.test.ts @@ -38,7 +38,7 @@ const oneIsZeroQueryResult: FindingsEvaluationsQueryResult = { const bothAreZeroQueryResult: FindingsEvaluationsQueryResult = { resources_evaluated: { - value: 30, + value: 0, }, failed_findings: { doc_count: 0, @@ -90,8 +90,13 @@ describe('getStatsFromFindingsEvaluationsAggs', () => { }); }); - it('should throw error if both evaluations are zero', async () => { - // const stats = getStatsFromFindingsEvaluationsAggs(bothAreZeroQueryResult); - expect(() => getStatsFromFindingsEvaluationsAggs(bothAreZeroQueryResult)).toThrow(); + it('should return zero on all stats if there are no failed or passed findings', async () => { + const stats = getStatsFromFindingsEvaluationsAggs(bothAreZeroQueryResult); + expect(stats).toEqual({ + totalFailed: 0, + totalPassed: 0, + totalFindings: 0, + postureScore: 0, + }); }); }); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.ts index abb1ecd510ab6..d0fcd5b796774 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.ts @@ -68,8 +68,7 @@ export const getStatsFromFindingsEvaluationsAggs = ( const failedFindings = findingsEvaluationsAggs.failed_findings.doc_count || 0; const passedFindings = findingsEvaluationsAggs.passed_findings.doc_count || 0; const totalFindings = failedFindings + passedFindings; - if (!totalFindings) throw new Error("couldn't calculate posture score"); - const postureScore = calculatePostureScore(passedFindings, failedFindings); + const postureScore = calculatePostureScore(passedFindings, failedFindings) || 0; return { totalFailed: failedFindings, diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_trends.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_trends.ts index 270ce4f1ce177..a47b63e1fb921 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_trends.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_trends.ts @@ -7,7 +7,7 @@ import { ElasticsearchClient } from '@kbn/core/server'; import { BENCHMARK_SCORE_INDEX_DEFAULT_NS } from '../../../common/constants'; -import { Stats } from '../../../common/types'; +import type { PosturePolicyTemplate, Stats } from '../../../common/types'; import { calculatePostureScore } from './get_stats'; export interface ScoreTrendDoc { @@ -25,13 +25,20 @@ export interface ScoreTrendDoc { >; } -export const getTrendsQuery = () => ({ +export type Trends = Array<{ + timestamp: string; + summary: Stats; + clusters: Record; +}>; + +export const getTrendsQuery = (policyTemplate: PosturePolicyTemplate) => ({ index: BENCHMARK_SCORE_INDEX_DEFAULT_NS, // large number that should be sufficient for 24 hours considering we write to the score index every 5 minutes size: 999, sort: '@timestamp:desc', query: { bool: { + filter: [{ term: { policy_template: policyTemplate } }], must: { range: { '@timestamp': { @@ -44,12 +51,6 @@ export const getTrendsQuery = () => ({ }, }); -export type Trends = Array<{ - timestamp: string; - summary: Stats; - clusters: Record; -}>; - export const getTrendsFromQueryResult = (scoreTrendDocs: ScoreTrendDoc[]): Trends => scoreTrendDocs.map((data) => ({ timestamp: data['@timestamp'], @@ -72,8 +73,11 @@ export const getTrendsFromQueryResult = (scoreTrendDocs: ScoreTrendDoc[]): Trend ), })); -export const getTrends = async (esClient: ElasticsearchClient): Promise => { - const trendsQueryResult = await esClient.search(getTrendsQuery()); +export const getTrends = async ( + esClient: ElasticsearchClient, + policyTemplate: PosturePolicyTemplate +): Promise => { + const trendsQueryResult = await esClient.search(getTrendsQuery(policyTemplate)); if (!trendsQueryResult.hits.hits) throw new Error('missing trend results from score index'); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts b/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts index 49dbf07883b23..33627389511a1 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts @@ -24,6 +24,7 @@ import { getAgentStatusesByAgentPolicies, getCspAgentPolicies, getCspPackagePolicies, + getInstalledPolicyTemplates, } from '../../lib/fleet_util'; import { checkIndexStatus } from '../../lib/check_index_status'; @@ -105,6 +106,7 @@ const getCspStatus = async ({ installation, latestCspPackage, installedPackagePolicies, + installedPolicyTemplates, ] = await Promise.all([ checkIndexStatus(esClient.asCurrentUser, LATEST_FINDINGS_INDEX_DEFAULT_NS, logger), checkIndexStatus(esClient.asCurrentUser, FINDINGS_INDEX_PATTERN, logger), @@ -114,6 +116,7 @@ const getCspStatus = async ({ getCspPackagePolicies(soClient, packagePolicyService, CLOUD_SECURITY_POSTURE_PACKAGE_NAME, { per_page: 10000, }), + getInstalledPolicyTemplates(packagePolicyService, soClient), ]); const healthyAgents = await getHealthyAgents( @@ -158,6 +161,7 @@ const getCspStatus = async ({ status, indicesDetails, latestPackageVersion: latestCspPackageVersion, + installedPolicyTemplates, healthyAgents, installedPackagePolicies: installedPackagePoliciesTotal, isPluginInitialized: isPluginInitialized(), @@ -168,6 +172,7 @@ const getCspStatus = async ({ indicesDetails, latestPackageVersion: latestCspPackageVersion, healthyAgents, + installedPolicyTemplates, installedPackagePolicies: installedPackagePoliciesTotal, installedPackageVersion: installation?.install_version, isPluginInitialized: isPluginInitialized(), diff --git a/x-pack/plugins/cloud_security_posture/server/tasks/findings_stats_task.ts b/x-pack/plugins/cloud_security_posture/server/tasks/findings_stats_task.ts index df1edb464c112..96a410d3cdaea 100644 --- a/x-pack/plugins/cloud_security_posture/server/tasks/findings_stats_task.ts +++ b/x-pack/plugins/cloud_security_posture/server/tasks/findings_stats_task.ts @@ -14,12 +14,7 @@ import { import { SearchRequest } from '@kbn/data-plugin/common'; import { ElasticsearchClient } from '@kbn/core/server'; import type { Logger } from '@kbn/core/server'; -import { - AggregatedFindingsByCluster, - ScoreBucket, - FindingsStatsTaskResult, - TaskHealthStatus, -} from './types'; +import { FindingsStatsTaskResult, TaskHealthStatus, ScoreByPolicyTemplateBucket } from './types'; import { BENCHMARK_SCORE_INDEX_DEFAULT_NS, LATEST_FINDINGS_INDEX_DEFAULT_NS, @@ -109,16 +104,81 @@ export function taskRunner(coreStartServices: CspServerPluginStartServices, logg }; } -const aggregateLatestFindings = async ( +const getScoreQuery = (): SearchRequest => ({ + index: LATEST_FINDINGS_INDEX_DEFAULT_NS, + size: 0, + query: { + match_all: {}, + }, + aggs: { + score_by_policy_template: { + terms: { + // TODO: CIS AWS - replace with policy_template when available + field: 'rule.benchmark.id', + }, + aggs: { + total_findings: { + value_count: { + field: 'result.evaluation', + }, + }, + passed_findings: { + filter: { + term: { + 'result.evaluation': 'passed', + }, + }, + }, + failed_findings: { + filter: { + term: { + 'result.evaluation': 'failed', + }, + }, + }, + score_by_cluster_id: { + terms: { + field: 'cluster_id', + }, + aggregations: { + total_findings: { + value_count: { + field: 'result.evaluation', + }, + }, + passed_findings: { + filter: { + term: { + 'result.evaluation': 'passed', + }, + }, + }, + failed_findings: { + filter: { + term: { + 'result.evaluation': 'failed', + }, + }, + }, + }, + }, + }, + }, + }, +}); + +export const aggregateLatestFindings = async ( esClient: ElasticsearchClient, stateRuns: number, logger: Logger ): Promise => { try { const startAggTime = performance.now(); - const evaluationsQueryResult = await esClient.search(getScoreQuery()); + const scoreIndexQueryResult = await esClient.search( + getScoreQuery() + ); - if (!evaluationsQueryResult.aggregations) { + if (!scoreIndexQueryResult.aggregations) { logger.warn(`No data found in latest findings index`); return 'warning'; } @@ -130,31 +190,45 @@ const aggregateLatestFindings = async ( ).toFixed(2)}ms]` ); - const clustersStats = Object.fromEntries( - evaluationsQueryResult.aggregations.score_by_cluster_id.buckets.map( - (clusterStats: AggregatedFindingsByCluster) => { + // getting score per policy template buckets + const scoresByPolicyTemplatesBuckets = + scoreIndexQueryResult.aggregations.score_by_policy_template.buckets; + + // iterating over the buckets and return promises which will index a modified document into the scores index + const docIndexingPromises = scoresByPolicyTemplatesBuckets.map((policyTemplateTrend) => { + // creating score per cluster id objects + const clustersStats = Object.fromEntries( + policyTemplateTrend.score_by_cluster_id.buckets.map((clusterStats) => { + const clusterId = clusterStats.key; + return [ - clusterStats.key, + clusterId, { total_findings: clusterStats.total_findings.value, passed_findings: clusterStats.passed_findings.doc_count, failed_findings: clusterStats.failed_findings.doc_count, }, ]; - } - ) - ); + }) + ); + + // each document contains the policy template and its scores + return esClient.index({ + index: BENCHMARK_SCORE_INDEX_DEFAULT_NS, + document: { + policy_template: policyTemplateTrend.key, + passed_findings: policyTemplateTrend.passed_findings.doc_count, + failed_findings: policyTemplateTrend.failed_findings.doc_count, + total_findings: policyTemplateTrend.total_findings.value, + score_by_cluster_id: clustersStats, + }, + }); + }); const startIndexTime = performance.now(); - await esClient.index({ - index: BENCHMARK_SCORE_INDEX_DEFAULT_NS, - document: { - passed_findings: evaluationsQueryResult.aggregations.passed_findings.doc_count, - failed_findings: evaluationsQueryResult.aggregations.failed_findings.doc_count, - total_findings: evaluationsQueryResult.aggregations.total_findings.value, - score_by_cluster_id: clustersStats, - }, - }); + + // executing indexing commands + await Promise.all(docIndexingPromises); const totalIndexTime = Number(performance.now() - startIndexTime).toFixed(2); logger.debug( @@ -176,58 +250,3 @@ const aggregateLatestFindings = async ( return 'error'; } }; - -const getScoreQuery = (): SearchRequest => ({ - index: LATEST_FINDINGS_INDEX_DEFAULT_NS, - size: 0, - query: { - match_all: {}, - }, - aggs: { - total_findings: { - value_count: { - field: 'result.evaluation', - }, - }, - passed_findings: { - filter: { - term: { - 'result.evaluation': 'passed', - }, - }, - }, - failed_findings: { - filter: { - term: { - 'result.evaluation': 'failed', - }, - }, - }, - score_by_cluster_id: { - terms: { - field: 'cluster_id', - }, - aggregations: { - total_findings: { - value_count: { - field: 'result.evaluation', - }, - }, - passed_findings: { - filter: { - term: { - 'result.evaluation': 'passed', - }, - }, - }, - failed_findings: { - filter: { - term: { - 'result.evaluation': 'failed', - }, - }, - }, - }, - }, - }, -}); diff --git a/x-pack/plugins/cloud_security_posture/server/tasks/types.ts b/x-pack/plugins/cloud_security_posture/server/tasks/types.ts index 783d534b7d550..0e2ab6f655d4b 100644 --- a/x-pack/plugins/cloud_security_posture/server/tasks/types.ts +++ b/x-pack/plugins/cloud_security_posture/server/tasks/types.ts @@ -5,18 +5,23 @@ * 2.0. */ -export interface AggregatedFindings { - passed_findings: { doc_count: number }; - failed_findings: { doc_count: number }; - total_findings: { value: number }; -} - -export interface AggregatedFindingsByCluster extends AggregatedFindings { - key: string; -} -export interface ScoreBucket extends AggregatedFindings { - score_by_cluster_id: { - buckets: AggregatedFindingsByCluster[]; +export interface ScoreByPolicyTemplateBucket { + score_by_policy_template: { + buckets: Array<{ + key: string; // policy template + doc_count: number; + passed_findings: { doc_count: number }; + failed_findings: { doc_count: number }; + total_findings: { value: number }; + score_by_cluster_id: { + buckets: Array<{ + key: string; // cluster id + passed_findings: { doc_count: number }; + failed_findings: { doc_count: number }; + total_findings: { value: number }; + }>; + }; + }>; }; } diff --git a/x-pack/plugins/dashboard_enhanced/kibana.json b/x-pack/plugins/dashboard_enhanced/kibana.json index eb9e5241503d1..0d5daf1574c5d 100644 --- a/x-pack/plugins/dashboard_enhanced/kibana.json +++ b/x-pack/plugins/dashboard_enhanced/kibana.json @@ -8,6 +8,19 @@ "server": true, "ui": true, "configPath": ["xpack", "dashboardEnhanced"], - "requiredPlugins": ["dashboard", "data", "embeddable", "share", "uiActionsEnhanced", "unifiedSearch"], - "requiredBundles": ["embeddable", "embeddableEnhanced", "kibanaReact", "kibanaUtils"] + "requiredPlugins": [ + "dashboard", + "data", + "embeddable", + "share", + "uiActionsEnhanced", + "unifiedSearch" + ], + "requiredBundles": [ + "embeddable", + "embeddableEnhanced", + "kibanaReact", + "kibanaUtils", + "imageEmbeddable" + ] } diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx index 39c0b07ddd4ad..468cbaf9940a9 100644 --- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx +++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/embeddable_to_dashboard_drilldown/embeddable_to_dashboard_drilldown.tsx @@ -13,6 +13,7 @@ import { extractTimeRange } from '@kbn/es-query'; import { ApplyGlobalFilterActionContext } from '@kbn/unified-search-plugin/public'; import { IEmbeddable, EmbeddableInput } from '@kbn/embeddable-plugin/public'; import { EnhancedEmbeddableContext } from '@kbn/embeddable-enhanced-plugin/public'; +import { IMAGE_CLICK_TRIGGER } from '@kbn/image-embeddable-plugin/public'; import { AbstractDashboardDrilldown, AbstractDashboardDrilldownParams, @@ -40,7 +41,7 @@ export type Params = AbstractDashboardDrilldownParams; export class EmbeddableToDashboardDrilldown extends AbstractDashboardDrilldown { public readonly id = EMBEDDABLE_TO_DASHBOARD_DRILLDOWN; - public readonly supportedTriggers = () => [APPLY_FILTER_TRIGGER]; + public readonly supportedTriggers = () => [APPLY_FILTER_TRIGGER, IMAGE_CLICK_TRIGGER]; protected async getLocation( config: Config, diff --git a/x-pack/plugins/dashboard_enhanced/tsconfig.json b/x-pack/plugins/dashboard_enhanced/tsconfig.json index f5a6c6faaeb8c..dd5a78b87dc4f 100644 --- a/x-pack/plugins/dashboard_enhanced/tsconfig.json +++ b/x-pack/plugins/dashboard_enhanced/tsconfig.json @@ -22,6 +22,7 @@ "@kbn/es-query", "@kbn/unified-search-plugin", "@kbn/ui-actions-plugin", + "@kbn/image-embeddable-plugin" ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/data_visualizer/kibana.json b/x-pack/plugins/data_visualizer/kibana.json index afc9fe34be640..98d27ba9f0481 100644 --- a/x-pack/plugins/data_visualizer/kibana.json +++ b/x-pack/plugins/data_visualizer/kibana.json @@ -26,6 +26,7 @@ ], "requiredBundles": [ "kibanaReact", + "kibanaUtils", "maps", "esUiShared", "fieldFormats", diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx index 09b59cf10abb5..4e3ed74c4470e 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx @@ -22,7 +22,7 @@ import { import { i18n } from '@kbn/i18n'; import { debounce, sortedIndex } from 'lodash'; import { FormattedMessage } from '@kbn/i18n-react'; -import { isDefined } from '../../util/is_defined'; +import { isDefined } from '@kbn/ml-is-defined'; import type { DocumentCountChartPoint } from './document_count_chart'; import { RANDOM_SAMPLER_STEP, diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx index 387c41f2b44f9..9f84bb6d1debd 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx @@ -14,9 +14,9 @@ import { RefreshInterval } from '@kbn/data-plugin/public'; import { FindFileStructureResponse } from '@kbn/file-upload-plugin/common'; import type { FileUploadPluginStart } from '@kbn/file-upload-plugin/public'; import { flatten } from 'lodash'; +import { isDefined } from '@kbn/ml-is-defined'; import { LinkCardProps } from '../link_card/link_card'; import { useDataVisualizerKibana } from '../../../kibana_context'; -import { isDefined } from '../../util/is_defined'; type LinkType = 'file' | 'index'; diff --git a/x-pack/plugins/data_visualizer/public/application/common/util/example_utils.ts b/x-pack/plugins/data_visualizer/public/application/common/util/example_utils.ts index cc4a9a3ca9bfa..e3e97666844c4 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/util/example_utils.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/util/example_utils.ts @@ -6,7 +6,7 @@ */ import { isPopulatedObject } from '@kbn/ml-is-populated-object'; -import { isDefined } from './is_defined'; +import { isDefined } from '@kbn/ml-is-defined'; import { GeoPointExample, LatLongExample } from '../../../../common/types/field_request_config'; export function isGeoPointExample(arg: unknown): arg is GeoPointExample { diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx index fc2efab6610bc..a8f454816e2b6 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx @@ -14,12 +14,12 @@ import { i18n } from '@kbn/i18n'; import { EuiSpacer, EuiTitle } from '@elastic/eui'; import { DataView } from '@kbn/data-views-plugin/public'; import { useUrlState } from '@kbn/ml-url-state'; +import { isDefined } from '@kbn/ml-is-defined'; import { LinkCardProps } from '../../../common/components/link_card/link_card'; import { useDataVisualizerKibana } from '../../../kibana_context'; import { LinkCard } from '../../../common/components/link_card'; import { GetAdditionalLinks } from '../../../common/components/results_links'; -import { isDefined } from '../../../common/util/is_defined'; interface Props { dataView: DataView; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector.tsx index 1cade1deaa59a..57c9f4fa18a40 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector.tsx @@ -23,9 +23,16 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; +import { useStorage } from '@kbn/ml-local-storage'; import { setFullTimeRange } from './full_time_range_selector_service'; import { useDataVisualizerKibana } from '../../../kibana_context'; -import { DV_FROZEN_TIER_PREFERENCE, useStorage } from '../../hooks/use_storage'; +import { + DV_FROZEN_TIER_PREFERENCE, + FROZEN_TIER_PREFERENCE, + type DVKey, + type DVStorageMapped, + type FrozenTierPreference, +} from '../../types/storage'; export const ML_FROZEN_TIER_PREFERENCE = 'ml.frozenDataTierPreference'; @@ -37,13 +44,6 @@ interface Props { callback?: (a: any) => void; } -const FROZEN_TIER_PREFERENCE = { - EXCLUDE: 'exclude-frozen', - INCLUDE: 'include-frozen', -} as const; - -type FrozenTierPreference = typeof FROZEN_TIER_PREFERENCE[keyof typeof FROZEN_TIER_PREFERENCE]; - // Component for rendering a button which automatically sets the range of the time filter // to the time range of data in the index(es) mapped to the supplied Kibana data view or query. export const FullTimeRangeSelector: FC = ({ @@ -83,7 +83,10 @@ export const FullTimeRangeSelector: FC = ({ const [isPopoverOpen, setPopover] = useState(false); - const [frozenDataPreference, setFrozenDataPreference] = useStorage( + const [frozenDataPreference, setFrozenDataPreference] = useStorage< + DVKey, + DVStorageMapped + >( DV_FROZEN_TIER_PREFERENCE, // By default we will exclude frozen data tier FROZEN_TIER_PREFERENCE.EXCLUDE diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx index 8e13ce92a5c1e..9ec8b90d84f02 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx @@ -27,8 +27,13 @@ import { generateFilters } from '@kbn/data-plugin/public'; import { DataView, DataViewField } from '@kbn/data-views-plugin/public'; import { usePageUrlState, useUrlState } from '@kbn/ml-url-state'; +import { useStorage } from '@kbn/ml-local-storage'; import { useCurrentEuiTheme } from '../../../common/hooks/use_current_eui_theme'; -import { DV_RANDOM_SAMPLER_PREFERENCE, useStorage } from '../../hooks/use_storage'; +import { + DV_RANDOM_SAMPLER_PREFERENCE, + type DVKey, + type DVStorageMapped, +} from '../../types/storage'; import { FullTimeRangeSelector } from '../full_time_range_selector'; import { DataVisualizerTable, @@ -58,7 +63,7 @@ import { DataVisualizerDataViewManagement } from '../data_view_management'; import { GetAdditionalLinks } from '../../../common/components/results_links'; import { useDataVisualizerGridData } from '../../hooks/use_data_visualizer_grid_data'; import { DataVisualizerGridInput } from '../../embeddables/grid_embeddable/grid_embeddable'; -import { RANDOM_SAMPLER_OPTION, RandomSamplerOption } from '../../constants/random_sampler'; +import { RANDOM_SAMPLER_OPTION } from '../../constants/random_sampler'; interface DataVisualizerPageState { overallStats: OverallStats; @@ -126,18 +131,17 @@ export interface IndexDataVisualizerViewProps { export const IndexDataVisualizerView: FC = (dataVisualizerProps) => { const euiTheme = useCurrentEuiTheme(); - const [savedRandomSamplerPreference, saveRandomSamplerPreference] = - useStorage( - DV_RANDOM_SAMPLER_PREFERENCE, - RANDOM_SAMPLER_OPTION.ON_AUTOMATIC - ); + const [savedRandomSamplerPreference, saveRandomSamplerPreference] = useStorage< + DVKey, + DVStorageMapped + >(DV_RANDOM_SAMPLER_PREFERENCE, RANDOM_SAMPLER_OPTION.ON_AUTOMATIC); const restorableDefaults = useMemo( () => getDefaultDataVisualizerListState({ rndSamplerPref: savedRandomSamplerPreference, }), - // We just need to load the saved preference when the page is first loaded + // We just need to load the saved preference when the page is first loaded // eslint-disable-next-line react-hooks/exhaustive-deps [] ); diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx index b6981bf996da2..ee4a002071b3f 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx @@ -12,7 +12,7 @@ import { i18n } from '@kbn/i18n'; import { Query, Filter } from '@kbn/es-query'; import type { TimeRange } from '@kbn/es-query'; import { DataView, DataViewField } from '@kbn/data-views-plugin/public'; -import { isDefined } from '../../../common/util/is_defined'; +import { isDefined } from '@kbn/ml-is-defined'; import { DataVisualizerFieldNamesFilter } from './field_name_filter'; import { DataVisualizerFieldTypeFilter } from './field_type_filter'; import { SupportedFieldType } from '../../../../../common/types'; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_storage.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_storage.ts deleted file mode 100644 index cd09967a81fa0..0000000000000 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_storage.ts +++ /dev/null @@ -1,48 +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 { useCallback, useState } from 'react'; -import { useDataVisualizerKibana } from '../../kibana_context'; - -export const DV_FROZEN_TIER_PREFERENCE = 'dataVisualizer.frozenDataTierPreference'; -export const DV_RANDOM_SAMPLER_PREFERENCE = 'dataVisualizer.randomSamplerPreference'; -export const DV_RANDOM_SAMPLER_P_VALUE = 'dataVisualizer.randomSamplerPValue'; - -export type DV = Partial<{ - [DV_FROZEN_TIER_PREFERENCE]: 'exclude_frozen' | 'include_frozen'; - [DV_RANDOM_SAMPLER_PREFERENCE]: 'true' | 'false'; - [DV_RANDOM_SAMPLER_P_VALUE]: number; -}> | null; - -export type DVKey = keyof Exclude; - -/** - * Hook for accessing and changing a value in the storage. - * @param key - Storage key - * @param initValue - */ -export function useStorage(key: DVKey, initValue?: T): [T, (value: T) => void] { - const { - services: { storage }, - } = useDataVisualizerKibana(); - - const [val, setVal] = useState(storage.get(key) ?? initValue); - - const setStorage = useCallback( - (value: T): void => { - try { - storage.set(key, value); - setVal(value); - } catch (e) { - throw new Error('Unable to update storage with provided value'); - } - }, - [key, storage] - ); - - return [val, setStorage]; -} diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx index 671d410523fdd..156898449ee79 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx @@ -13,7 +13,9 @@ import { EuiResizeObserver } from '@elastic/eui'; import { encode } from '@kbn/rison'; import { SimpleSavedObject } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; +import { Storage } from '@kbn/kibana-utils-plugin/public'; import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { StorageContextProvider } from '@kbn/ml-local-storage'; import { DataView } from '@kbn/data-views-plugin/public'; import { getNestedProperty } from '@kbn/ml-nested-property'; import { @@ -34,6 +36,9 @@ import { GetAdditionalLinks } from '../common/components/results_links'; import { DATA_VISUALIZER_APP_LOCATOR, IndexDataVisualizerLocatorParams } from './locator'; import { DATA_VISUALIZER_INDEX_VIEWER } from './constants/index_data_visualizer_viewer'; import { INDEX_DATA_VISUALIZER_NAME } from '../common/constants'; +import { DV_STORAGE_KEYS } from './types/storage'; + +const localStorage = new Storage(window.localStorage); export interface DataVisualizerStateContextProviderProps { IndexDataVisualizerComponent: FC; @@ -316,10 +321,12 @@ export const IndexDataVisualizer: FC<{ return ( - + + + ); diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_document_stats.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_document_stats.ts index f74a8800d2bd0..e6fc220ea7f3c 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_document_stats.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_document_stats.ts @@ -10,7 +10,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; import { DataPublicPluginStart, ISearchOptions } from '@kbn/data-plugin/public'; import seedrandom from 'seedrandom'; -import { isDefined } from '../../../common/util/is_defined'; +import { isDefined } from '@kbn/ml-is-defined'; import { RANDOM_SAMPLER_PROBABILITIES } from '../../constants/random_sampler'; import { buildBaseFilterCriteria } from '../../../../../common/utils/query_utils'; import type { diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_numeric_field_stats.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_numeric_field_stats.ts index 66a7134919760..20143f5fc1581 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_numeric_field_stats.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_numeric_field_stats.ts @@ -17,8 +17,8 @@ import type { } from '@kbn/data-plugin/common'; import type { ISearchStart } from '@kbn/data-plugin/public'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; +import { isDefined } from '@kbn/ml-is-defined'; import { processTopValues } from './utils'; -import { isDefined } from '../../../common/util/is_defined'; import { buildAggregationWithSamplingOption } from './build_random_sampler_agg'; import { MAX_PERCENT, PERCENTILE_SPACING, SAMPLER_TOP_TERMS_THRESHOLD } from './constants'; import type { diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/types/storage.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/types/storage.ts new file mode 100644 index 0000000000000..f2718bc8e803f --- /dev/null +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/types/storage.ts @@ -0,0 +1,42 @@ +/* + * 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 { RandomSamplerOption } from '../constants/random_sampler'; + +export const DV_FROZEN_TIER_PREFERENCE = 'dataVisualizer.frozenDataTierPreference'; +export const DV_RANDOM_SAMPLER_PREFERENCE = 'dataVisualizer.randomSamplerPreference'; +export const DV_RANDOM_SAMPLER_P_VALUE = 'dataVisualizer.randomSamplerPValue'; + +export const FROZEN_TIER_PREFERENCE = { + EXCLUDE: 'exclude-frozen', + INCLUDE: 'include-frozen', +} as const; + +export type FrozenTierPreference = + typeof FROZEN_TIER_PREFERENCE[keyof typeof FROZEN_TIER_PREFERENCE]; + +export type DV = Partial<{ + [DV_FROZEN_TIER_PREFERENCE]: FrozenTierPreference; + [DV_RANDOM_SAMPLER_PREFERENCE]: RandomSamplerOption; + [DV_RANDOM_SAMPLER_P_VALUE]: number; +}> | null; + +export type DVKey = keyof Exclude; + +export type DVStorageMapped = T extends typeof DV_FROZEN_TIER_PREFERENCE + ? FrozenTierPreference | undefined + : T extends typeof DV_RANDOM_SAMPLER_PREFERENCE + ? RandomSamplerOption | undefined + : T extends typeof DV_RANDOM_SAMPLER_P_VALUE + ? number | undefined + : null; + +export const DV_STORAGE_KEYS = [ + DV_FROZEN_TIER_PREFERENCE, + DV_RANDOM_SAMPLER_PREFERENCE, + DV_RANDOM_SAMPLER_P_VALUE, +] as const; diff --git a/x-pack/plugins/data_visualizer/tsconfig.json b/x-pack/plugins/data_visualizer/tsconfig.json index b6c5477266e4c..3098da0f61bc2 100644 --- a/x-pack/plugins/data_visualizer/tsconfig.json +++ b/x-pack/plugins/data_visualizer/tsconfig.json @@ -52,6 +52,8 @@ "@kbn/field-types", "@kbn/ml-nested-property", "@kbn/ml-url-state", + "@kbn/ml-local-storage", + "@kbn/ml-is-defined", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/drilldowns/url_drilldown/kibana.json b/x-pack/plugins/drilldowns/url_drilldown/kibana.json index 83ea4b7be54bf..8e7c290cfd185 100644 --- a/x-pack/plugins/drilldowns/url_drilldown/kibana.json +++ b/x-pack/plugins/drilldowns/url_drilldown/kibana.json @@ -9,5 +9,5 @@ }, "description": "Adds drilldown implementations to Kibana", "requiredPlugins": ["embeddable", "uiActions", "uiActionsEnhanced"], - "requiredBundles": ["kibanaUtils", "kibanaReact"] + "requiredBundles": ["kibanaUtils", "kibanaReact", "imageEmbeddable"] } diff --git a/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown.tsx b/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown.tsx index f1a25398c7e4c..6f16c47df15df 100644 --- a/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown.tsx +++ b/x-pack/plugins/drilldowns/url_drilldown/public/lib/url_drilldown.tsx @@ -15,6 +15,7 @@ import { SELECT_RANGE_TRIGGER, VALUE_CLICK_TRIGGER, } from '@kbn/embeddable-plugin/public'; +import { IMAGE_CLICK_TRIGGER } from '@kbn/image-embeddable-plugin/public'; import { ActionExecutionContext, ROW_CLICK_TRIGGER } from '@kbn/ui-actions-plugin/public'; import type { Query, Filter, TimeRange } from '@kbn/es-query'; import type { @@ -65,7 +66,8 @@ export type UrlTrigger = | typeof VALUE_CLICK_TRIGGER | typeof SELECT_RANGE_TRIGGER | typeof ROW_CLICK_TRIGGER - | typeof CONTEXT_MENU_TRIGGER; + | typeof CONTEXT_MENU_TRIGGER + | typeof IMAGE_CLICK_TRIGGER; export interface ActionFactoryContext extends BaseActionFactoryContext { embeddable?: EmbeddableWithQueryInput; @@ -110,7 +112,13 @@ export class UrlDrilldown implements Drilldown = ({ @@ -231,6 +239,7 @@ export class UrlDrilldown implements Drilldown { events: [ { eventId: '1', - triggers: [OTHER_TRIGGER], + triggers: [OTHER_TRIGGER, VALUE_CLICK_TRIGGER], + action: { + factoryId: 'DASHBOARD_TO_DASHBOARD_DRILLDOWN', + name: '', + config: {}, + }, + }, + { + eventId: '3', + triggers: [OTHER_TRIGGER, SELECT_RANGE_TRIGGER], action: { factoryId: 'DASHBOARD_TO_DASHBOARD_DRILLDOWN', name: '', @@ -561,7 +575,7 @@ describe('EmbeddableActionStorage', () => { }, }, { - eventId: '2', + eventId: '3', triggers: [OTHER_TRIGGER], action: { factoryId: 'SOME_OTHER', @@ -575,9 +589,10 @@ describe('EmbeddableActionStorage', () => { }); const storage = new EmbeddableActionStorage(embeddable); - const [event1, event2] = await storage.list(); - expect(event1.triggers).toEqual([APPLY_FILTER_TRIGGER]); - expect(event2.triggers).toEqual([OTHER_TRIGGER]); + const [event1, event2, event3] = await storage.list(); + expect(event1.triggers).toEqual([OTHER_TRIGGER, APPLY_FILTER_TRIGGER]); + expect(event2.triggers).toEqual([OTHER_TRIGGER, APPLY_FILTER_TRIGGER]); + expect(event3.triggers).toEqual([OTHER_TRIGGER]); }); }); }); diff --git a/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.ts b/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.ts index 63291f652d3f3..2eebc52ba55cf 100644 --- a/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.ts +++ b/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.ts @@ -11,7 +11,13 @@ import { UiActionsEnhancedAbstractActionStorage as AbstractActionStorage, UiActionsEnhancedSerializedEvent as SerializedEvent, } from '@kbn/ui-actions-enhanced-plugin/public'; -import { EmbeddableInput, EmbeddableOutput, IEmbeddable } from '@kbn/embeddable-plugin/public'; +import { + EmbeddableInput, + EmbeddableOutput, + IEmbeddable, + VALUE_CLICK_TRIGGER, + SELECT_RANGE_TRIGGER, +} from '@kbn/embeddable-plugin/public'; export interface EmbeddableWithDynamicActionsInput extends EmbeddableInput { enhancements?: { @@ -114,16 +120,26 @@ export class EmbeddableActionStorage extends AbstractActionStorage { return this.migrate(events); } - // TODO: https://github.com/elastic/kibana/issues/71431 + // TODO: https://github.com/elastic/kibana/issues/148005 // Migration implementation should use registry // Action factories implementations should register own migrations private migrate(events: SerializedEvent[]): SerializedEvent[] { return events.map((event) => { // Initially dashboard drilldown relied on VALUE_CLICK & RANGE_SELECT if (event.action.factoryId === 'DASHBOARD_TO_DASHBOARD_DRILLDOWN') { + const migratedTriggers = event.triggers.filter( + (t) => t !== VALUE_CLICK_TRIGGER && t !== SELECT_RANGE_TRIGGER + ); + if ( + migratedTriggers.length !== event.triggers.length && + !migratedTriggers.includes(`FILTER_TRIGGER`) + ) { + migratedTriggers.push(`FILTER_TRIGGER`); + } + return { ...event, - triggers: ['FILTER_TRIGGER'], + triggers: migratedTriggers, }; } return event; diff --git a/x-pack/plugins/enterprise_search/README.md b/x-pack/plugins/enterprise_search/README.md index 76160d3fcc8db..5694258001dd4 100644 --- a/x-pack/plugins/enterprise_search/README.md +++ b/x-pack/plugins/enterprise_search/README.md @@ -49,11 +49,14 @@ To debug Kea state in-browser, Kea recommends [Redux Devtools](https://v2.keajs. Documentation: https://www.elastic.co/guide/en/kibana/current/development-tests.html#_unit_testing -Jest tests can be run directly from the `x-pack/plugins/enterprise_search` folder. This also works for any subfolders or subcomponents. +Jest tests can be run from the root kibana directory, however, since the tests take so long to run you will likely want to apply the appropriate Jest configuration file to test only your changes. For example: +- `x-pack/plugins/enterprise_search/common/jest.config.js` +- `x-pack/plugins/enterprise_search/public/jest.config.js` +- `x-pack/plugins/enterprise_search/server/jest.config.js` ```bash -yarn test:jest -yarn test:jest --watch +yarn test:jest --config {YOUR_JEST_CONFIG_FILE} +yarn test:jest --config {YOUR_JEST_CONFIG_FILE} --watch ``` Unfortunately coverage collection does not work as automatically, and requires using our handy jest.sh script if you want to run tests on a specific file or folder and only get coverage numbers for that file or folder: diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/api/delete_analytics_collection/delete_analytics_collection_api_logic.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/api/delete_analytics_collection/delete_analytics_collection_api_logic.tsx index bdc01e65e95f7..1cd07433721d5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/api/delete_analytics_collection/delete_analytics_collection_api_logic.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/api/delete_analytics_collection/delete_analytics_collection_api_logic.tsx @@ -5,6 +5,8 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; + import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; @@ -20,5 +22,11 @@ export const deleteAnalyticsCollection = async ({ id }: { id: string }) => { export const DeleteAnalyticsCollectionAPILogic = createApiLogic( ['analytics', 'delete_analytics_collection_api_logic'], - deleteAnalyticsCollection + deleteAnalyticsCollection, + { + showSuccessFlashFn: () => + i18n.translate('xpack.enterpriseSearch.analytics.collectionsDelete.action.successMessage', { + defaultMessage: 'The collection has been successfully deleted', + }), + } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection_logic.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection_logic.ts index 2e71bee479e68..1e97b48975d68 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection_logic.ts @@ -13,7 +13,7 @@ import { Status } from '../../../../../common/types/api'; import { Actions } from '../../../shared/api_logic/create_api_logic'; import { generateEncodedPath } from '../../../shared/encode_path_params'; -import { flashAPIErrors, flashSuccessToast } from '../../../shared/flash_messages'; +import { flashSuccessToast } from '../../../shared/flash_messages'; import { KibanaLogic } from '../../../shared/kibana'; import { AddAnalyticsCollectionsAPILogic, @@ -59,7 +59,6 @@ export const AddAnalyticsCollectionLogic = kea< values: [AddAnalyticsCollectionsAPILogic, ['status']], }, listeners: ({ values, actions }) => ({ - apiError: (error) => flashAPIErrors(error), apiSuccess: async ({ name, id }, breakpoint) => { // Wait for propagation of the new collection flashSuccessToast( diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/analytics_collection_integrate_javascript_client_embed.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/analytics_collection_integrate_javascript_client_embed.tsx index 3d9988fef12ea..136617db09112 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/analytics_collection_integrate_javascript_client_embed.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/analytics_collection_integrate_javascript_client_embed.tsx @@ -58,10 +58,10 @@ export const javascriptClientEmbedSteps = (analyticsDNSUrl: string) => [

{`import { -createTracker, -trackPageView, -trackEvent, -} from "@elastic/behavioural-analytics-javascript-tracker";`} + createTracker, + trackPageView, + trackEvent, +} from "@elastic/behavioral-analytics-javascript-tracker";`}
@@ -82,7 +82,7 @@ trackEvent, 'xpack.enterpriseSearch.analytics.collections.collectionsView.integrateTab.javascriptClientEmbed.stepThree.description', { defaultMessage: - ' Use createTracker method to initialize the tracker with your DSN. You will then be able to use the tracker to send events to Behavioural Analytics.', + ' Use createTracker method to initialize the tracker with your DSN. You will then be able to use the tracker to send events to Behavioral Analytics.', } )}

@@ -91,7 +91,7 @@ trackEvent, 'xpack.enterpriseSearch.analytics.collections.collectionsView.integrateTab.javascriptClientEmbed.stepThree.descriptionTwo', { defaultMessage: - 'Once you have called createTracker, you can use the tracker methods such as trackPageView to send events to Behavioural Analytics.', + 'Once you have called createTracker, you can use the tracker methods such as trackPageView to send events to Behavioral Analytics.', } )}

@@ -119,7 +119,7 @@ trackEvent, 'xpack.enterpriseSearch.analytics.collections.collectionsView.integrateTab.javascriptClientEmbed.stepFour.description', { defaultMessage: - 'Once you have called createTracker, you can use the tracker methods such as trackPageView to send events to Behavioural Analytics.', + 'Once you have called createTracker, you can use the tracker methods such as trackPageView to send events to Behavioral Analytics.', } )}

@@ -133,7 +133,9 @@ trackEvent, )}

- {`// track a page view in React + {`import { useEffect } from 'react'; + +// track a page view in React const SearchPage = (props) => { useEffect(() => { @@ -153,13 +155,13 @@ const SearchPage = (props) => { 'xpack.enterpriseSearch.analytics.collections.collectionsView.integrateTab.javascriptClientEmbed.stepFour.descriptionThree', { defaultMessage: - 'You can also dispatch custom events to Behavioural Analytics by calling the trackEvent method.', + 'You can also dispatch custom events to Behavioral Analytics by calling the trackEvent method.', } )}

{`// track a custom event in React -import { trackEvent } from '@elastic/behavioural-analytics-javascript-tracker'; +import { trackEvent } from '@elastic/behavioral-analytics-javascript-tracker'; const ProductDetailPage = (props) => { @@ -173,11 +175,9 @@ const ProductDetailPage = (props) => { label: "product_id", value: "123" }) - }} /> - }}>Add to Basket + }} value="Add to Basket"/> - ) - } + ) }`} diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/analytics_collection_integrate_searchui.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/analytics_collection_integrate_searchui.tsx index b12dbc6e45773..cae8799544033 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/analytics_collection_integrate_searchui.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate/analytics_collection_integrate_searchui.tsx @@ -106,7 +106,7 @@ export const searchUIEmbedSteps = (setSelectedTab: (tab: TabKey) => void) => [ 'xpack.enterpriseSearch.analytics.collections.collectionsView.integrateTab.searchui.stepTwo.setupDescription', { defaultMessage: - 'Finally, add the plugin to your Search UI configuration. Depending on how you have embedded Behavioural analytics, you may need to pass in the client. The example below shows how to pass in the client when using the Javascript client.', + 'Finally, add the plugin to your Search UI configuration. Depending on how you have embedded Behavioral analytics, you may need to pass in the client. The example below shows how to pass in the client when using the Javascript client.', } )}

@@ -116,9 +116,11 @@ import { getTracker } from "@elastic/behavioral-analytics-tracker"; const searchUIConfig = { ... -plugins: [AnalyticsPlugin( -client: getTracker(); -)], +plugins: [ + AnalyticsPlugin({ + client: getTracker(); + }) +], ... }`}
diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.test.ts index 0e5db4adacb54..7db951a31ea93 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.test.ts @@ -14,7 +14,7 @@ import { import { nextTick } from '@kbn/test-jest-helpers'; import { AnalyticsCollection } from '../../../../../common/types/analytics'; -import { HttpError, Status } from '../../../../../common/types/api'; +import { Status } from '../../../../../common/types/api'; import { DeleteAnalyticsCollectionLogic } from './delete_analytics_collection_logic'; @@ -48,12 +48,6 @@ describe('deleteAnalyticsCollectionLogic', () => { expect(mockFlashMessageHelpers.clearFlashMessages).toHaveBeenCalledTimes(1); }); - it('calls flashAPIErrors on apiError', () => { - DeleteAnalyticsCollectionLogic.actions.apiError({} as HttpError); - expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1); - expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledWith({}); - }); - it('calls makeRequest on deleteAnalyticsCollections', async () => { const collectionName = 'name'; diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.ts index 1804dbe7f4fc2..f78e8ee76aff4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.ts @@ -7,16 +7,9 @@ import { kea, MakeLogicType } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { AnalyticsCollection } from '../../../../../common/types/analytics'; import { Status } from '../../../../../common/types/api'; import { Actions } from '../../../shared/api_logic/create_api_logic'; -import { - flashAPIErrors, - clearFlashMessages, - flashSuccessToast, -} from '../../../shared/flash_messages'; import { KibanaLogic } from '../../../shared/kibana'; import { DeleteAnalyticsCollectionAPILogic, @@ -25,7 +18,6 @@ import { import { ROOT_PATH } from '../../routes'; export interface DeleteAnalyticsCollectionActions { - apiError: Actions<{}, DeleteAnalyticsCollectionApiLogicResponse>['apiError']; apiSuccess: Actions<{}, DeleteAnalyticsCollectionApiLogicResponse>['apiSuccess']; deleteAnalyticsCollection(id: string): { id: string }; makeRequest: Actions<{}, DeleteAnalyticsCollectionApiLogicResponse>['makeRequest']; @@ -43,17 +35,11 @@ export const DeleteAnalyticsCollectionLogic = kea< deleteAnalyticsCollection: (id) => ({ id }), }, connect: { - actions: [DeleteAnalyticsCollectionAPILogic, ['makeRequest', 'apiSuccess', 'apiError']], + actions: [DeleteAnalyticsCollectionAPILogic, ['makeRequest', 'apiSuccess']], values: [DeleteAnalyticsCollectionAPILogic, ['status']], }, listeners: ({ actions }) => ({ - apiError: (e) => flashAPIErrors(e), - apiSuccess: async (undefined, breakpoint) => { - flashSuccessToast( - i18n.translate('xpack.enterpriseSearch.analytics.collectionsDelete.action.successMessage', { - defaultMessage: 'The collection has been successfully deleted', - }) - ); + apiSuccess: async (_, breakpoint) => { // Wait for propagation of the collection deletion await breakpoint(1000); KibanaLogic.values.navigateToUrl(ROOT_PATH); @@ -61,7 +47,6 @@ export const DeleteAnalyticsCollectionLogic = kea< deleteAnalyticsCollection: ({ id }) => { actions.makeRequest({ id }); }, - makeRequest: () => clearFlashMessages(), }), path: ['enterprise_search', 'analytics', 'collections', 'delete'], selectors: ({ selectors }) => ({ diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.test.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.test.tsx index efd6993a8411e..89c422da5739d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.test.tsx @@ -10,14 +10,18 @@ import { LogicMounter, mockFlashMessageHelpers } from '../../../__mocks__/kea_lo import { AnalyticsCollection } from '../../../../../common/types/analytics'; import { HttpError, Status } from '../../../../../common/types/api'; +import { FetchAnalyticsCollectionAPILogic } from '../../api/fetch_analytics_collection/fetch_analytics_collection_api_logic'; + import { FetchAnalyticsCollectionLogic } from './fetch_analytics_collection_logic'; describe('fetchAnalyticsCollectionLogic', () => { + const { mount: apiLogicMount } = new LogicMounter(FetchAnalyticsCollectionAPILogic); const { mount } = new LogicMounter(FetchAnalyticsCollectionLogic); beforeEach(() => { jest.clearAllMocks(); jest.useRealTimers(); + apiLogicMount(); mount(); }); @@ -39,7 +43,7 @@ describe('fetchAnalyticsCollectionLogic', () => { }); it('calls flashAPIErrors on apiError', () => { - FetchAnalyticsCollectionLogic.actions.apiError({} as HttpError); + FetchAnalyticsCollectionAPILogic.actions.apiError({} as HttpError); expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1); expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledWith({}); }); @@ -58,7 +62,7 @@ describe('fetchAnalyticsCollectionLogic', () => { describe('selectors', () => { describe('analyticsCollections', () => { it('updates when apiSuccess listener triggered', () => { - FetchAnalyticsCollectionLogic.actions.apiSuccess({} as AnalyticsCollection); + FetchAnalyticsCollectionAPILogic.actions.apiSuccess({} as AnalyticsCollection); expect(FetchAnalyticsCollectionLogic.values).toEqual({ ...DEFAULT_VALUES, diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.ts index bf9af189d79cc..6f9ab441716d4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.ts @@ -10,15 +10,12 @@ import { kea, MakeLogicType } from 'kea'; import { AnalyticsCollection } from '../../../../../common/types/analytics'; import { Status } from '../../../../../common/types/api'; import { Actions } from '../../../shared/api_logic/create_api_logic'; -import { flashAPIErrors, clearFlashMessages } from '../../../shared/flash_messages'; import { FetchAnalyticsCollectionAPILogic, FetchAnalyticsCollectionApiLogicResponse, } from '../../api/fetch_analytics_collection/fetch_analytics_collection_api_logic'; export interface FetchAnalyticsCollectionActions { - apiError: Actions<{}, FetchAnalyticsCollectionApiLogicResponse>['apiError']; - apiSuccess: Actions<{}, FetchAnalyticsCollectionApiLogicResponse>['apiSuccess']; fetchAnalyticsCollection(name: string): AnalyticsCollection; makeRequest: Actions<{}, FetchAnalyticsCollectionApiLogicResponse>['makeRequest']; } @@ -36,15 +33,13 @@ export const FetchAnalyticsCollectionLogic = kea< fetchAnalyticsCollection: (id) => ({ id }), }, connect: { - actions: [FetchAnalyticsCollectionAPILogic, ['makeRequest', 'apiSuccess', 'apiError']], + actions: [FetchAnalyticsCollectionAPILogic, ['makeRequest']], values: [FetchAnalyticsCollectionAPILogic, ['data', 'status']], }, listeners: ({ actions }) => ({ - apiError: (e) => flashAPIErrors(e), fetchAnalyticsCollection: ({ id }) => { actions.makeRequest({ id }); }, - makeRequest: () => clearFlashMessages(), }), path: ['enterprise_search', 'analytics', 'collection'], selectors: ({ selectors }) => ({ diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collections_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collections_logic.test.ts index 0089b30dc8cf1..888ab558f3006 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collections_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collections_logic.test.ts @@ -10,14 +10,18 @@ import { LogicMounter, mockFlashMessageHelpers } from '../../../__mocks__/kea_lo import { AnalyticsCollection } from '../../../../../common/types/analytics'; import { HttpError, Status } from '../../../../../common/types/api'; +import { FetchAnalyticsCollectionsAPILogic } from '../../api/index/fetch_analytics_collections_api_logic'; + import { AnalyticsCollectionsLogic } from './analytics_collections_logic'; describe('analyticsCollectionsLogic', () => { + const { mount: apiMount } = new LogicMounter(FetchAnalyticsCollectionsAPILogic); const { mount } = new LogicMounter(AnalyticsCollectionsLogic); beforeEach(() => { jest.clearAllMocks(); jest.useRealTimers(); + apiMount(); mount(); }); @@ -36,7 +40,7 @@ describe('analyticsCollectionsLogic', () => { describe('reducers', () => { describe('hasNoAnalyticsCollections', () => { it('updates to true when apiSuccess returns empty analytics collections array', () => { - AnalyticsCollectionsLogic.actions.apiSuccess([]); + FetchAnalyticsCollectionsAPILogic.actions.apiSuccess([]); expect(AnalyticsCollectionsLogic.values.hasNoAnalyticsCollections).toBe(true); expect(AnalyticsCollectionsLogic.values).toEqual({ ...DEFAULT_VALUES, @@ -57,7 +61,7 @@ describe('analyticsCollectionsLogic', () => { name: 'collection1', }, ]; - AnalyticsCollectionsLogic.actions.apiSuccess(collections); + FetchAnalyticsCollectionsAPILogic.actions.apiSuccess(collections); expect(AnalyticsCollectionsLogic.values.hasNoAnalyticsCollections).toBe(false); expect(AnalyticsCollectionsLogic.values).toEqual({ ...DEFAULT_VALUES, @@ -77,7 +81,7 @@ describe('analyticsCollectionsLogic', () => { }); it('calls flashAPIErrors on apiError', () => { - AnalyticsCollectionsLogic.actions.apiError({} as HttpError); + FetchAnalyticsCollectionsAPILogic.actions.apiError({} as HttpError); expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1); expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledWith({}); }); @@ -92,7 +96,7 @@ describe('analyticsCollectionsLogic', () => { describe('selectors', () => { describe('analyticsCollections', () => { it('updates when apiSuccess listener triggered', () => { - AnalyticsCollectionsLogic.actions.apiSuccess([]); + FetchAnalyticsCollectionsAPILogic.actions.apiSuccess([]); expect(AnalyticsCollectionsLogic.values).toEqual({ ...DEFAULT_VALUES, diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collections_logic.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collections_logic.ts index 5736680893b2b..aa12b92b0f177 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collections_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collections_logic.ts @@ -10,15 +10,12 @@ import { kea, MakeLogicType } from 'kea'; import { AnalyticsCollection } from '../../../../../common/types/analytics'; import { Status } from '../../../../../common/types/api'; import { Actions } from '../../../shared/api_logic/create_api_logic'; -import { flashAPIErrors, clearFlashMessages } from '../../../shared/flash_messages'; import { FetchAnalyticsCollectionsAPILogic, FetchAnalyticsCollectionsApiLogicResponse, } from '../../api/index/fetch_analytics_collections_api_logic'; export interface AnalyticsCollectionsActions { - apiError: Actions<{}, FetchAnalyticsCollectionsApiLogicResponse>['apiError']; - apiSuccess: Actions<{}, FetchAnalyticsCollectionsApiLogicResponse>['apiSuccess']; fetchAnalyticsCollections(): void; makeRequest: Actions<{}, FetchAnalyticsCollectionsApiLogicResponse>['makeRequest']; } @@ -37,15 +34,13 @@ export const AnalyticsCollectionsLogic = kea< fetchAnalyticsCollections: () => {}, }, connect: { - actions: [FetchAnalyticsCollectionsAPILogic, ['makeRequest', 'apiSuccess', 'apiError']], + actions: [FetchAnalyticsCollectionsAPILogic, ['makeRequest']], values: [FetchAnalyticsCollectionsAPILogic, ['data', 'status']], }, listeners: ({ actions }) => ({ - apiError: (e) => flashAPIErrors(e), fetchAnalyticsCollections: () => { actions.makeRequest({}); }, - makeRequest: () => clearFlashMessages(), }), path: ['enterprise_search', 'analytics', 'collections'], selectors: ({ selectors }) => ({ diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_overview.tsx index 0fd3518240fbb..39ab22a675c42 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_overview.tsx @@ -44,7 +44,7 @@ export const AnalyticsOverview: React.FC = () => { } ), pageTitle: i18n.translate('xpack.enterpriseSearch.analytics.collections.pageTitle', { - defaultMessage: 'Behaviorial Analytics', + defaultMessage: 'Behavioral Analytics', }), }} > diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/cancel_syncs_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/cancel_syncs_api_logic.ts index 297e26f2c05ec..53324ceb9f635 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/cancel_syncs_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/cancel_syncs_api_logic.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; + import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; @@ -17,4 +19,9 @@ export const cancelSyncs = async ({ connectorId }: CancelSyncsApiArgs) => { return await HttpLogic.values.http.post(route); }; -export const CancelSyncsApiLogic = createApiLogic(['cancel_syncs_api_logic'], cancelSyncs); +export const CancelSyncsApiLogic = createApiLogic(['cancel_syncs_api_logic'], cancelSyncs, { + showSuccessFlashFn: () => + i18n.translate('xpack.enterpriseSearch.content.searchIndex.cancelSyncs.successMessage', { + defaultMessage: 'Successfully canceled syncs', + }), +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/start_sync_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/start_sync_api_logic.ts index 4a97edfa528a8..20e51228114a5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/start_sync_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/start_sync_api_logic.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; + import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; import { CrawlRequestOverrides } from '../../components/search_index/crawler/crawler_logic'; @@ -23,4 +25,9 @@ export const startSync = async ({ connectorId, nextSyncConfig }: StartSyncArgs) }); }; -export const StartSyncApiLogic = createApiLogic(['start_sync_api_logic'], startSync); +export const StartSyncApiLogic = createApiLogic(['start_sync_api_logic'], startSync, { + showSuccessFlashFn: () => + i18n.translate('xpack.enterpriseSearch.content.searchIndex.index.syncSuccess.message', { + defaultMessage: 'Successfully scheduled a sync, waiting for a connector to pick it up', + }), +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_configuration_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_configuration_api_logic.ts index 2b3b86b296ea1..79294d60b5af0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_configuration_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_configuration_api_logic.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; + import { ConnectorConfiguration } from '../../../../../common/types/connectors'; import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; @@ -35,5 +37,12 @@ export const postConnectorConfiguration = async ({ export const ConnectorConfigurationApiLogic = createApiLogic( ['content', 'configuration_connector_api_logic'], - postConnectorConfiguration + postConnectorConfiguration, + { + showSuccessFlashFn: () => + i18n.translate( + 'xpack.enterpriseSearch.content.indices.configurationConnector.configuration.successToast.title', + { defaultMessage: 'Configuration updated' } + ), + } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_filtering_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_filtering_api_logic.ts index 3f1a668203615..023d06b8f957b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_filtering_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_filtering_api_logic.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; + import { FilteringRule, FilteringRules } from '../../../../../common/types/connectors'; import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; @@ -34,5 +36,12 @@ export const putConnectorFiltering = async ({ export const ConnectorFilteringApiLogic = createApiLogic( ['content', 'connector_filtering_api_logic'], - putConnectorFiltering + putConnectorFiltering, + { + showSuccessFlashFn: () => + i18n.translate( + 'xpack.enterpriseSearch.content.index.connector.filtering.successToastRules.title', + { defaultMessage: 'Sync rules updated' } + ), + } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_filtering_draft_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_filtering_draft_api_logic.ts index aa7406aee253f..f380af36e849e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_filtering_draft_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_filtering_draft_api_logic.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; + import { FilteringRule, FilteringRules } from '../../../../../common/types/connectors'; import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; @@ -34,5 +36,12 @@ export const putConnectorFilteringDraft = async ({ export const ConnectorFilteringDraftApiLogic = createApiLogic( ['content', 'connector_filtering_draft_api_logic'], - putConnectorFilteringDraft + putConnectorFilteringDraft, + { + showSuccessFlashFn: () => + i18n.translate( + 'xpack.enterpriseSearch.content.index.connector.syncRules.successToastDraft.title', + { defaultMessage: 'Draft rules saved' } + ), + } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_name_and_description_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_name_and_description_api_logic.ts index 639bd56208546..88d2c19a59eb0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_name_and_description_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_name_and_description_api_logic.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; + import { Connector } from '../../../../../common/types/connectors'; import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; @@ -36,5 +38,12 @@ export const putConnectorNameAndDescription = async ({ export const ConnectorNameAndDescriptionApiLogic = createApiLogic( ['content', 'connector_name_and_description_api_logic'], - putConnectorNameAndDescription + putConnectorNameAndDescription, + { + showSuccessFlashFn: () => + i18n.translate( + 'xpack.enterpriseSearch.content.indices.configurationConnector.nameAndDescription.successToast.title', + { defaultMessage: 'Connector name and description updated' } + ), + } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_scheduling_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_scheduling_api_logic.ts index eebbd2b2bedf4..2c68b5994e398 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_scheduling_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_scheduling_api_logic.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; + import { ConnectorScheduling } from '../../../../../common/types/connectors'; import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; @@ -28,5 +30,12 @@ export const updateConnectorScheduling = async ({ export const UpdateConnectorSchedulingApiLogic = createApiLogic( ['content', 'update_connector_scheduling_api_logic'], - updateConnectorScheduling + updateConnectorScheduling, + { + showSuccessFlashFn: () => + i18n.translate( + 'xpack.enterpriseSearch.content.indices.configurationConnector.scheduling.successToast.title', + { defaultMessage: 'Scheduling successfully updated' } + ), + } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_default_pipeline_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_default_pipeline_api_logic.ts index 612403a1f0472..81cfeadf8e39a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_default_pipeline_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_default_pipeline_api_logic.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; + import { IngestPipelineParams } from '../../../../../common/types/connectors'; import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; @@ -25,5 +27,11 @@ export const updateDefaultPipeline = async ( export const UpdateDefaultPipelineApiLogic = createApiLogic( ['content', 'update_default_pipeline_api_logic'], - updateDefaultPipeline + updateDefaultPipeline, + { + showSuccessFlashFn: () => + i18n.translate('xpack.enterpriseSearch.content.indices.defaultPipelines.successToast.title', { + defaultMessage: 'Default pipeline successfully updated', + }), + } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_pipeline_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_pipeline_api_logic.ts index b3f3b2f673622..496b50fce7444 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_pipeline_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_pipeline_api_logic.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; + import { IngestPipelineParams } from '../../../../../common/types/connectors'; import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; @@ -33,5 +35,11 @@ export const updatePipeline = async ({ export const UpdatePipelineApiLogic = createApiLogic( ['content', 'update_pipeline_api_logic'], - updatePipeline + updatePipeline, + { + showSuccessFlashFn: () => + i18n.translate('xpack.enterpriseSearch.content.indices.pipelines.successToast.title', { + defaultMessage: 'Pipelines updated', + }), + } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/delete_crawler_domain_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/delete_crawler_domain_api_logic.ts index 8857ef95a32fa..28d03f44a7c0a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/delete_crawler_domain_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/delete_crawler_domain_api_logic.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; + import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; @@ -34,5 +36,14 @@ export const deleteCrawlerDomain = async ({ export const DeleteCrawlerDomainApiLogic = createApiLogic( ['delete_crawler_domain'], - deleteCrawlerDomain + deleteCrawlerDomain, + { + showSuccessFlashFn: ({ domain }) => + i18n.translate('xpack.enterpriseSearch.crawler.domainsTable.action.delete.successMessage', { + defaultMessage: "Successfully deleted domain '{domainUrl}'", + values: { + domainUrl: domain.url, + }, + }), + } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/engines/fetch_engines_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/engines/fetch_engines_api_logic.ts new file mode 100644 index 0000000000000..5c2e57be2a39d --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/engines/fetch_engines_api_logic.ts @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; + +import { EngineListDetails, Meta } from '../../components/engines/types'; + +export interface EnginesListAPIResponse { + results: EngineListDetails[]; + meta: Meta; + searchQuery?: string; +} +export interface EnginesListAPIArguments { + meta: Meta; + searchQuery?: string; +} + +const metaValue: Meta = { + from: 1, + size: 3, + total: 5, +}; +// These are mocked values. To be changed as per the latest requirement when Backend API is ready +export const mockedEngines: EnginesListAPIResponse[] = [ + { + meta: metaValue, + results: [ + { + name: 'engine-name-1', + indices: ['index-18', 'index-23'], + last_updated: '21 March 2021', + document_count: 18, + }, + { + name: 'engine-name-2', + indices: ['index-180', 'index-230', 'index-8', 'index-2'], + last_updated: '10 Jul 2018', + document_count: 10, + }, + + { + name: 'engine-name-3', + indices: ['index-2', 'index-3'], + last_updated: '21 December 2022', + document_count: 8, + }, + ], + }, +]; +export const fetchEngines = async () => { + // TODO replace with http call when backend is ready + return mockedEngines[0]; +}; + +export const FetchEnginesAPILogic = createApiLogic(['content', 'engines_api_logic'], fetchEngines); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/create_custom_pipeline_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/create_custom_pipeline_api_logic.ts index 9b3f8e9bd5c03..7d9a7ede6ad98 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/create_custom_pipeline_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/create_custom_pipeline_api_logic.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; + import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; @@ -26,5 +28,11 @@ export const createCustomPipeline = async ({ export const CreateCustomPipelineApiLogic = createApiLogic( ['content', 'create_custom_pipeline_api_logic'], - createCustomPipeline + createCustomPipeline, + { + showSuccessFlashFn: () => + i18n.translate('xpack.enterpriseSearch.content.indices.pipelines.successToastCustom.title', { + defaultMessage: 'Custom pipeline created', + }), + } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/delete_index_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/delete_index_api_logic.ts index ff92e4ecef6bc..391e3e102383a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/delete_index_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/delete_index_api_logic.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; + import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; @@ -12,10 +14,25 @@ export interface DeleteIndexApiLogicArgs { indexName: string; } -export const deleteIndex = async ({ indexName }: DeleteIndexApiLogicArgs): Promise => { +export interface DeleteIndexApiLogicValues { + indexName: string; +} + +export const deleteIndex = async ({ + indexName, +}: DeleteIndexApiLogicArgs): Promise => { const route = `/internal/enterprise_search/indices/${indexName}`; await HttpLogic.values.http.delete(route); - return; + return { indexName }; }; -export const DeleteIndexApiLogic = createApiLogic(['delete_index_api_logic'], deleteIndex); +export const DeleteIndexApiLogic = createApiLogic(['delete_index_api_logic'], deleteIndex, { + showSuccessFlashFn: ({ indexName }) => + i18n.translate('xpack.enterpriseSearch.content.indices.deleteIndex.successToast.title', { + defaultMessage: + 'Your index {indexName} and any associated ingestion configurations were successfully deleted', + values: { + indexName, + }, + }), +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/fetch_index_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/fetch_index_api_logic.ts index 9473e9041da3b..9ba818bc6c57a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/fetch_index_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/fetch_index_api_logic.ts @@ -23,4 +23,7 @@ export const fetchIndex = async ({ return await HttpLogic.values.http.get(route); }; -export const FetchIndexApiLogic = createApiLogic(['fetch_index_api_logic'], fetchIndex); +export const FetchIndexApiLogic = createApiLogic(['fetch_index_api_logic'], fetchIndex, { + clearFlashMessagesOnMakeRequest: false, + showErrorFlash: false, +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/ml_model_stats_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/ml_model_stats_logic.ts index d80c1836a9597..7c0d1020cd265 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/ml_model_stats_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/ml_model_stats_logic.ts @@ -22,7 +22,11 @@ export const getMLModelsStats = async () => { export const MLModelsStatsApiLogic = createApiLogic( ['ml_models_stats_api_logic'], - getMLModelsStats + getMLModelsStats, + { + clearFlashMessagesOnMakeRequest: false, + showErrorFlash: false, + } ); export type MLModelsStatsApiLogicActions = Actions; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/ml_models_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/ml_models_logic.ts index 63095f3fbaa2d..fe610ed0b710a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/ml_models_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/ml_models_logic.ts @@ -19,6 +19,9 @@ export const getMLModels = async (size: GetMlModelsArgs = 1000) => { }); }; -export const MLModelsApiLogic = createApiLogic(['ml_models_api_logic'], getMLModels); +export const MLModelsApiLogic = createApiLogic(['ml_models_api_logic'], getMLModels, { + clearFlashMessagesOnMakeRequest: false, + showErrorFlash: false, +}); export type MLModelsApiLogicActions = Actions; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/crawler_domain_detail_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/crawler_domain_detail_logic.ts index 0b00622492c9b..e36f62333a588 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/crawler_domain_detail_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/crawler_domain_detail_logic.ts @@ -135,9 +135,6 @@ export const CrawlerDomainDetailLogic = kea< }) ); }, - deleteApiError: (error) => { - flashAPIErrors(error); - }, fetchDomainData: async ({ domainId }) => { const { http } = HttpLogic.values; const { indexName } = IndexNameLogic.values; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/components/tables/engines_table.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/components/tables/engines_table.tsx new file mode 100644 index 0000000000000..a66ff164e7b8f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/components/tables/engines_table.tsx @@ -0,0 +1,113 @@ +/* + * 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 { CriteriaWithPagination, EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; +import { FormattedNumber } from '@kbn/i18n-react'; + +import { DELETE_BUTTON_LABEL, MANAGE_BUTTON_LABEL } from '../../../../../shared/constants'; + +import { convertMetaToPagination, EngineListDetails, Meta } from '../../types'; + +// add health status +interface EnginesListTableProps { + enginesList: EngineListDetails[]; + loading: boolean; + meta: Meta; + isLoading?: boolean; + onChange: (criteria: CriteriaWithPagination) => void; +} +export const EnginesListTable: React.FC = ({ + enginesList, + meta, + isLoading, + onChange, +}) => { + const columns: Array> = [ + { + field: 'name', + name: i18n.translate('xpack.enterpriseSearch.content.enginesList.table.column.name', { + defaultMessage: 'Engine Name', + }), + width: '30%', + truncateText: true, + mobileOptions: { + header: true, + enlarge: true, + width: '100%', + }, + }, + { + field: 'document_count', + name: i18n.translate('xpack.enterpriseSearch.content.enginesList.table.column.documents', { + defaultMessage: 'Documents', + }), + dataType: 'number', + render: (number: number) => , + }, + { + field: 'last_updated', + name: i18n.translate('xpack.enterpriseSearch.content.enginesList.table.column.lastUpdated', { + defaultMessage: 'Last updated', + }), + dataType: 'string', + }, + { + field: 'indices.length', + datatype: 'number', + name: i18n.translate('xpack.enterpriseSearch.content.enginesList.table.column.indices', { + defaultMessage: 'Indices', + }), + }, + + { + name: i18n.translate('xpack.enterpriseSearch.content.enginesList.table.column.actions', { + defaultMessage: 'Actions', + }), + actions: [ + { + name: MANAGE_BUTTON_LABEL, + description: i18n.translate( + 'xpack.enterpriseSearch.content.enginesList.table.column.action.manage.buttonDescription', + { + defaultMessage: 'Manage this engine', + } + ), + type: 'icon', + icon: 'eye', + onClick: () => {}, + }, + { + name: DELETE_BUTTON_LABEL, + description: i18n.translate( + 'xpack.enterpriseSearch.content.enginesList.table.column.action.delete.buttonDescription', + { + defaultMessage: 'Delete this engine', + } + ), + type: 'icon', + icon: 'trash', + color: 'danger', + onClick: () => {}, + }, + ], + }, + ]; + + return ( + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/engine_list_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/engine_list_logic.test.ts new file mode 100644 index 0000000000000..efd4ae2a622de --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/engine_list_logic.test.ts @@ -0,0 +1,153 @@ +/* + * 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 { LogicMounter, mockFlashMessageHelpers } from '../../../__mocks__/kea_logic'; + +import { nextTick } from '@kbn/test-jest-helpers'; + +import { HttpError, Status } from '../../../../../common/types/api'; + +import { FetchEnginesAPILogic } from '../../api/engines/fetch_engines_api_logic'; + +import { EnginesListLogic } from './engines_list_logic'; +import { DEFAULT_META, EngineListDetails } from './types'; + +const DEFAULT_VALUES = { + data: undefined, + results: [], + meta: DEFAULT_META, + parameters: { meta: DEFAULT_META }, + status: Status.IDLE, +}; + +// sample engines list + +const results: EngineListDetails[] = [ + { + name: 'engine-name-1', + indices: ['index-18', 'index-23'], + last_updated: '21 March 2021', + document_count: 18, + }, + { + name: 'engine-name-2', + indices: ['index-180', 'index-230', 'index-8', 'index-2'], + last_updated: '10 Jul 2018', + document_count: 10, + }, + + { + name: 'engine-name-3', + indices: ['index-2', 'index-3'], + last_updated: '21 December 2022', + document_count: 8, + }, +]; + +describe('EnginesListLogic', () => { + const { mount: apiLogicMount } = new LogicMounter(FetchEnginesAPILogic); + const { mount } = new LogicMounter(EnginesListLogic); + + beforeEach(() => { + jest.clearAllMocks(); + jest.useRealTimers(); + apiLogicMount(); + mount(); + }); + it('has expected default values', () => { + expect(EnginesListLogic.values).toEqual(DEFAULT_VALUES); + }); + describe('actions', () => { + describe('onPaginate', () => { + it('updates meta with newPageIndex', () => { + expect(EnginesListLogic.values).toEqual(DEFAULT_VALUES); + // This test does not work for now, test below code when Kibana GET API for pagination is ready + // EnginesListLogic.actions.onPaginate(2); + // expect(EnginesListLogic.values).toEqual({ + // ...DEFAULT_VALUES, + // meta: { + // ...DEFAULT_META, + // from: 2, + // }, + // }); + }); + }); + }); + describe('reducers', () => { + describe('meta', () => { + it('updates when apiSuccess', () => { + const newPageMeta = { + from: 2, + size: 3, + total: 6, + }; + expect(EnginesListLogic.values).toEqual(DEFAULT_VALUES); + EnginesListLogic.actions.apiSuccess({ + meta: newPageMeta, + results, + searchQuery: 'k', + }); + expect(EnginesListLogic.values).toEqual({ + ...DEFAULT_VALUES, + data: { + results, + meta: newPageMeta, + searchQuery: 'k', + }, + meta: newPageMeta, + parameters: { + meta: newPageMeta, + searchQuery: 'k', + }, + results, + status: Status.SUCCESS, + }); + }); + }); + }); + describe('listeners', () => { + it('call flashAPIErrors on apiError', () => { + EnginesListLogic.actions.apiError({} as HttpError); + expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1); + expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledWith({}); + }); + + it('call makeRequest on fetchEngines', async () => { + jest.useFakeTimers({ legacyFakeTimers: true }); + EnginesListLogic.actions.makeRequest = jest.fn(); + EnginesListLogic.actions.fetchEngines({ meta: DEFAULT_META }); + await nextTick(); + expect(EnginesListLogic.actions.makeRequest).toHaveBeenCalledWith({ + meta: DEFAULT_META, + }); + }); + }); + describe('selectors', () => { + describe('enginesList', () => { + it('updates when apiSuccess', () => { + expect(EnginesListLogic.values).toEqual(DEFAULT_VALUES); + EnginesListLogic.actions.apiSuccess({ + results, + meta: DEFAULT_META, + }); + expect(EnginesListLogic.values).toEqual({ + ...DEFAULT_VALUES, + data: { + results, + meta: DEFAULT_META, + }, + meta: DEFAULT_META, + parameters: { + meta: DEFAULT_META, + }, + results, + status: Status.SUCCESS, + }); + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/engines_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/engines_list.test.tsx new file mode 100644 index 0000000000000..20ee8ac80bd49 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/engines_list.test.tsx @@ -0,0 +1,44 @@ +/* + * 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 { setMockActions, setMockValues } from '../../../__mocks__/kea_logic'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { mockedEngines } from '../../api/engines/fetch_engines_api_logic'; + +import { EnginesListTable } from './components/tables/engines_table'; +import { EnginesList } from './engines_list'; +import { DEFAULT_META } from './types'; + +const mockValues = { + enginesList: mockedEngines, + meta: DEFAULT_META, +}; +const mockActions = { + fetchEngines: jest.fn(), + onPaginate: jest.fn(), +}; + +describe('EnginesList', () => { + beforeEach(() => { + jest.clearAllMocks(); + global.localStorage.clear(); + }); + describe('Empty state', () => {}); + + it('renders with Engines data ', async () => { + setMockValues(mockValues); + setMockActions(mockActions); + + const wrapper = shallow(); + + expect(wrapper.find(EnginesListTable)).toHaveLength(1); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/engines_list.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/engines_list.tsx index 7292dad6db745..702d623c44dc1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/engines_list.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/engines_list.tsx @@ -5,13 +5,35 @@ * 2.0. */ -import React from 'react'; +import React, { useEffect, useState } from 'react'; + +import { useActions, useValues } from 'kea'; + +import { EuiButton, EuiFieldSearch, EuiLink, EuiSpacer, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage, FormattedNumber } from '@kbn/i18n-react'; + +import { DataPanel } from '../../../shared/data_panel/data_panel'; +import { handlePageChange } from '../../../shared/table_pagination'; import { EnterpriseSearchContentPageTemplate } from '../layout/page_template'; -export const EnginesList = () => { +import { EnginesListTable } from './components/tables/engines_table'; +import { EnginesListLogic } from './engines_list_logic'; + +export const EnginesList: React.FC = () => { + const { fetchEngines, onPaginate } = useActions(EnginesListLogic); + const { meta, results } = useValues(EnginesListLogic); + const [searchQuery, setSearchValue] = useState(''); + + useEffect(() => { + fetchEngines({ + meta, + searchQuery, + }); + }, [meta, searchQuery]); + return ( { }), ]} pageHeader={{ - pageTitle: i18n.translate('xpack.enterpriseSearch.content.engines.headerTitle', { + pageTitle: i18n.translate('xpack.enterpriseSearch.content.engines.title', { defaultMessage: 'Engines', }), + rightSideItems: [ + + {i18n.translate('xpack.enterpriseSearch.content.engines.createEngineButtonLabel', { + defaultMessage: 'Create engine', + })} + , + ], }} pageViewTelemetry="Engines" isLoading={false} > + + {i18n.translate('xpack.enterpriseSearch.content.engines.description', { + defaultMessage: + 'Engines allow you to query indexed data with a complete set of relevance, analytics and personalization tools. To learn more about how engines work in Enterprise search ', + })} + + + {i18n.translate('xpack.enterpriseSearch.content.engines.documentation', { + defaultMessage: 'explore our Engines documentation', + })} + + + +
+ { + setSearchValue(event.currentTarget.value); + }} + /> +
+ + + {i18n.translate('xpack.enterpriseSearch.content.engines.searchPlaceholder.description', { + defaultMessage: 'Locate an engine via name or indices', + })} + + + + + + +
+ ), + size: ( + + + + ), + total: , + }} + /> + + + {i18n.translate('xpack.enterpriseSearch.content.engines.title', { + defaultMessage: 'Engines', + })} + + } + > + + + +
); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/engines_list_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/engines_list_logic.ts new file mode 100644 index 0000000000000..bccb560f79ac8 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/engines_list_logic.ts @@ -0,0 +1,76 @@ +/* + * 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 { kea, MakeLogicType } from 'kea'; + +import { Actions } from '../../../shared/api_logic/create_api_logic'; + +import { + EnginesListAPIArguments, + EnginesListAPIResponse, + FetchEnginesAPILogic, +} from '../../api/engines/fetch_engines_api_logic'; + +import { DEFAULT_META, EngineListDetails, Meta, updateMetaPageIndex } from './types'; + +type EnginesListActions = Pick< + Actions, + 'apiError' | 'apiSuccess' | 'makeRequest' +> & { + fetchEngines({ meta, searchQuery }: { meta: Meta; searchQuery?: string }): { + meta: Meta; + searchQuery?: string; + }; + onPaginate(pageNumber: number): { pageNumber: number }; +}; +interface EngineListValues { + data: typeof FetchEnginesAPILogic.values.data; + meta: Meta; + parameters: { meta: Meta; searchQuery?: string }; // Added this variable to store to the search Query value as well + results: EngineListDetails[]; // stores engine list value from data + status: typeof FetchEnginesAPILogic.values.status; +} + +export const EnginesListLogic = kea>({ + actions: { + fetchEngines: ({ meta, searchQuery }) => ({ + meta, + searchQuery, + }), + + onPaginate: (pageNumber) => ({ pageNumber }), + }, + connect: { + actions: [FetchEnginesAPILogic, ['makeRequest', 'apiSuccess', 'apiError']], + values: [FetchEnginesAPILogic, ['data', 'status']], + }, + listeners: ({ actions }) => ({ + fetchEngines: async (input) => { + actions.makeRequest(input); + }, + }), + path: ['enterprise_search', 'content', 'engine_list_logic'], + reducers: ({}) => ({ + parameters: [ + { meta: DEFAULT_META }, + { + apiSuccess: (_, { meta, searchQuery }) => ({ + meta, + searchQuery, + }), + onPaginate: (state, { pageNumber }) => ({ + ...state, + meta: updateMetaPageIndex(state.meta, pageNumber), + }), + }, + ], + }), + selectors: ({ selectors }) => ({ + meta: [() => [selectors.parameters], (parameters) => parameters.meta], + results: [() => [selectors.data], (data) => data?.results ?? []], + }), +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/types.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/types.ts new file mode 100644 index 0000000000000..d21e3c92c8329 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/types.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. + */ + +export interface Meta { + from: number; + size: number; + total: number; +} + +export interface EngineListDetails { + name: string; + indices: string[]; + last_updated: string; + document_count: number; +} +export const DEFAULT_META = { + from: 1, + size: 3, + total: 0, +}; + +export const convertMetaToPagination = (meta: Meta) => ({ + pageIndex: meta.from - 1, + pageSize: meta.size, + totalItemCount: meta.total, +}); +export const updateMetaPageIndex = (oldState: Meta, newPageIndex: number) => { + return { ...oldState, from: newPageIndex }; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_api/method_api_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_api/method_api_logic.test.ts index f5f185e420b05..2e4c5949be426 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_api/method_api_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_api/method_api_logic.test.ts @@ -5,19 +5,12 @@ * 2.0. */ -import { - LogicMounter, - mockFlashMessageHelpers, - mockKibanaValues, -} from '../../../../__mocks__/kea_logic'; - -import { HttpError } from '../../../../../../common/types/api'; +import { LogicMounter, mockKibanaValues } from '../../../../__mocks__/kea_logic'; import { MethodApiLogic } from './method_api_logic'; describe('MethodApiLogic', () => { const { mount } = new LogicMounter(MethodApiLogic); - const { clearFlashMessages, flashAPIErrors } = mockFlashMessageHelpers; const { navigateToUrl } = mockKibanaValues; beforeEach(() => { @@ -33,23 +26,5 @@ describe('MethodApiLogic', () => { expect(navigateToUrl).toHaveBeenCalledWith('/search_indices/my-index/overview'); }); }); - - describe('makeRequest', () => { - it('clears any displayed errors', () => { - MethodApiLogic.actions.makeRequest({ indexName: 'my-index', language: 'Universal' }); - - expect(clearFlashMessages).toHaveBeenCalled(); - }); - }); - - describe('apiError', () => { - it('displays the error to the user', () => { - const error = {} as HttpError; - - MethodApiLogic.actions.apiError(error); - - expect(flashAPIErrors).toHaveBeenCalledWith(error); - }); - }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_api/method_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_api/method_api_logic.ts index 65d1563458319..3608395cf5f34 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_api/method_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_api/method_api_logic.ts @@ -10,8 +10,6 @@ import { kea, MakeLogicType } from 'kea'; import { Actions } from '../../../../shared/api_logic/create_api_logic'; import { generateEncodedPath } from '../../../../shared/encode_path_params'; -import { clearFlashMessages, flashAPIErrors } from '../../../../shared/flash_messages'; - import { KibanaLogic } from '../../../../shared/kibana'; import { CreateApiIndexApiLogic, @@ -23,17 +21,14 @@ import { SearchIndexTabId } from '../../search_index/search_index'; type MethodApiActions = Pick< Actions, - 'apiError' | 'apiSuccess' | 'makeRequest' + 'apiSuccess' | 'makeRequest' >; export const MethodApiLogic = kea>({ connect: { - actions: [CreateApiIndexApiLogic, ['apiError', 'apiSuccess', 'makeRequest']], + actions: [CreateApiIndexApiLogic, ['apiSuccess', 'makeRequest']], }, listeners: { - apiError: (error) => { - flashAPIErrors(error); - }, apiSuccess: ({ indexName }) => { KibanaLogic.values.navigateToUrl( generateEncodedPath(SEARCH_INDEX_TAB_PATH, { @@ -42,7 +37,6 @@ export const MethodApiLogic = kea>({ }) ); }, - makeRequest: () => clearFlashMessages(), }, path: ['enterprise_search', 'method_api'], }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_connector/add_connector_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_connector/add_connector_logic.ts index dd9a33320d649..bfef21d4bbba5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_connector/add_connector_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_connector/add_connector_logic.ts @@ -12,7 +12,6 @@ import { ErrorCode } from '../../../../../../common/types/error_codes'; import { generateEncodedPath } from '../../../../app_search/utils/encode_path_params'; import { Actions } from '../../../../shared/api_logic/create_api_logic'; -import { flashAPIErrors } from '../../../../shared/flash_messages'; import { KibanaLogic } from '../../../../shared/kibana'; import { AddConnectorApiLogic, @@ -41,7 +40,6 @@ export const AddConnectorLogic = kea flashAPIErrors(error), apiSuccess: async ({ indexName }, breakpoint) => { // Give Elasticsearch the chance to propagate the index so we don't end up in an error state after navigating await breakpoint(1000); @@ -53,7 +51,7 @@ export const AddConnectorLogic = kea { const { mount } = new LogicMounter(MethodCrawlerLogic); + const { mount: apiLogicMount } = new LogicMounter(CreateCrawlerIndexApiLogic); const { clearFlashMessages, flashAPIErrors } = mockFlashMessageHelpers; const { navigateToUrl } = mockKibanaValues; beforeEach(() => { jest.clearAllMocks(); + apiLogicMount(); mount(); }); describe('listeners', () => { describe('apiSuccess', () => { it('navigates user to index detail view', () => { - MethodCrawlerLogic.actions.apiSuccess({ created: 'my-index' }); + CreateCrawlerIndexApiLogic.actions.apiSuccess({ created: 'my-index' }); expect(navigateToUrl).toHaveBeenCalledWith('/search_indices/my-index/domain_management'); }); @@ -36,7 +40,10 @@ describe('MethodCrawlerLogic', () => { describe('makeRequest', () => { it('clears any displayed errors', () => { - MethodCrawlerLogic.actions.makeRequest({ indexName: 'my-index', language: 'Universal' }); + CreateCrawlerIndexApiLogic.actions.makeRequest({ + indexName: 'my-index', + language: 'Universal', + }); expect(clearFlashMessages).toHaveBeenCalled(); }); @@ -46,7 +53,7 @@ describe('MethodCrawlerLogic', () => { it('displays the error to the user', () => { const error = {} as HttpError; - MethodCrawlerLogic.actions.apiError(error); + CreateCrawlerIndexApiLogic.actions.apiError(error); expect(flashAPIErrors).toHaveBeenCalledWith(error); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_crawler/method_crawler_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_crawler/method_crawler_logic.ts index 57649ea710eef..cbd53a07b4e0b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_crawler/method_crawler_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_crawler/method_crawler_logic.ts @@ -10,8 +10,6 @@ import { kea, MakeLogicType } from 'kea'; import { Actions } from '../../../../shared/api_logic/create_api_logic'; import { generateEncodedPath } from '../../../../shared/encode_path_params'; -import { clearFlashMessages, flashAPIErrors } from '../../../../shared/flash_messages'; - import { KibanaLogic } from '../../../../shared/kibana'; import { CreateCrawlerIndexApiLogic, @@ -28,12 +26,9 @@ type MethodCrawlerActions = Pick< export const MethodCrawlerLogic = kea>({ connect: { - actions: [CreateCrawlerIndexApiLogic, ['apiError', 'apiSuccess', 'makeRequest']], + actions: [CreateCrawlerIndexApiLogic, ['apiError', 'apiSuccess']], }, listeners: { - apiError: (error) => { - flashAPIErrors(error); - }, apiSuccess: ({ created }) => { KibanaLogic.values.navigateToUrl( generateEncodedPath(SEARCH_INDEX_TAB_PATH, { @@ -42,7 +37,6 @@ export const MethodCrawlerLogic = kea>({ }) ); }, - makeRequest: () => clearFlashMessages(), }, - path: ['enterprise_search', 'method_crawler'], + path: ['enterprise_search', 'content', 'method_crawler'], }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/generate_api_key_modal.logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/generate_api_key_modal.logic.test.ts index 596ec459bc992..4dbfc574777ad 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/generate_api_key_modal.logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/generate_api_key_modal.logic.test.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { LogicMounter, mockFlashMessageHelpers } from '../../../../../__mocks__/kea_logic'; +import { LogicMounter } from '../../../../../__mocks__/kea_logic'; -import { HttpError, Status } from '../../../../../../../common/types/api'; +import { Status } from '../../../../../../../common/types/api'; import { GenerateApiKeyLogic } from '../../../../api/generate_api_key/generate_api_key_logic'; import { GenerateApiKeyModalLogic } from './generate_api_key_modal.logic'; @@ -63,19 +63,6 @@ describe('IndicesLogic', () => { }); }); - describe('listeners', () => { - it('calls clearFlashMessages on new makeRequest', () => { - GenerateApiKeyModalLogic.actions.makeRequest({ indexName: 'test', keyName: 'test' }); - expect(mockFlashMessageHelpers.clearFlashMessages).toHaveBeenCalledTimes(1); - }); - - it('calls flashAPIErrors on apiError', () => { - GenerateApiKeyModalLogic.actions.apiError({} as HttpError); - expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1); - expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledWith({}); - }); - }); - describe('selectors', () => { describe('apiKey', () => { it('updates when apiSuccess listener triggered', () => { @@ -110,7 +97,7 @@ describe('IndicesLogic', () => { describe('isLoading', () => { it('should update with API status', () => { expect(GenerateApiKeyModalLogic.values).toEqual(DEFAULT_VALUES); - GenerateApiKeyModalLogic.actions.makeRequest({ indexName: 'test', keyName: 'test' }); + GenerateApiKeyLogic.actions.makeRequest({ indexName: 'test', keyName: 'test' }); expect(GenerateApiKeyModalLogic.values).toEqual({ ...DEFAULT_VALUES, diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/generate_api_key_modal.logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/generate_api_key_modal.logic.ts index 654a984a171ca..022dee11d63c9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/generate_api_key_modal.logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/generate_api_key_modal.logic.ts @@ -7,15 +7,11 @@ import { kea, MakeLogicType } from 'kea'; -import { HttpError, Status } from '../../../../../../../common/types/api'; - -import { flashAPIErrors, clearFlashMessages } from '../../../../../shared/flash_messages'; +import { Status } from '../../../../../../../common/types/api'; import { GenerateApiKeyLogic } from '../../../../api/generate_api_key/generate_api_key_logic'; interface GenerateApiKeyModalActions { - apiError(error: HttpError): HttpError; - makeRequest: typeof GenerateApiKeyLogic.actions.makeRequest; setKeyName(keyName: string): { keyName: string }; } @@ -35,13 +31,8 @@ export const GenerateApiKeyModalLogic = kea< setKeyName: (keyName) => ({ keyName }), }, connect: { - actions: [GenerateApiKeyLogic, ['makeRequest', 'apiError']], values: [GenerateApiKeyLogic, ['data', 'status']], }, - listeners: () => ({ - apiError: (e) => flashAPIErrors(e), - makeRequest: () => clearFlashMessages(), - }), path: ['enterprise_search', 'search_index', 'generate_api_key_modal'], reducers: () => ({ keyName: [ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/modal.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/modal.tsx index 9dbe7fb5e5aa4..18514ef93d9d9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/modal.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/generate_api_key_modal/modal.tsx @@ -34,6 +34,7 @@ import { i18n } from '@kbn/i18n'; import { docLinks } from '../../../../../shared/doc_links'; +import { GenerateApiKeyLogic } from '../../../../api/generate_api_key/generate_api_key_logic'; import { IndexViewLogic } from '../../index_view_logic'; import { GenerateApiKeyModalLogic } from './generate_api_key_modal.logic'; @@ -46,7 +47,8 @@ interface GenerateApiKeyModalProps { export const GenerateApiKeyModal: React.FC = ({ indexName, onClose }) => { const { keyName, apiKey, isLoading, isSuccess } = useValues(GenerateApiKeyModalLogic); const { ingestionMethod } = useValues(IndexViewLogic); - const { setKeyName, makeRequest } = useActions(GenerateApiKeyModalLogic); + const { setKeyName } = useActions(GenerateApiKeyModalLogic); + const { makeRequest } = useActions(GenerateApiKeyLogic); return ( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/cancel_syncs_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/cancel_syncs_logic.test.ts index a63dac6806cc8..36ee9b44ac9d9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/cancel_syncs_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/cancel_syncs_logic.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { LogicMounter, mockFlashMessageHelpers } from '../../../../__mocks__/kea_logic'; +import { LogicMounter } from '../../../../__mocks__/kea_logic'; import { indices } from '../../../__mocks__/search_indices.mock'; @@ -18,7 +18,6 @@ describe('CancelSyncsLogic', () => { const { mount } = new LogicMounter(CancelSyncsLogic); const { mount: IndexViewLogicMount } = new LogicMounter(IndexViewLogic); const { mount: FetchIndexApiLogicMount } = new LogicMounter(FetchIndexApiLogic); - const { clearFlashMessages, flashAPIErrors, flashSuccessToast } = mockFlashMessageHelpers; const DEFAULT_VALUES = { connectorId: null, isConnectorIndex: false, @@ -48,25 +47,5 @@ describe('CancelSyncsLogic', () => { expect(CancelSyncsLogic.actions.makeCancelSyncsRequest).toHaveBeenCalled(); }); }); - describe('makeRequest', () => { - it('should call clearFlashMessages', () => { - CancelSyncsLogic.actions.makeCancelSyncsRequest({ - connectorId: 'id', - }); - expect(clearFlashMessages).toHaveBeenCalled(); - }); - }); - describe('apiError', () => { - it('should call flashAPIError', () => { - CancelSyncsLogic.actions.cancelSyncsApiError('error' as any); - expect(flashAPIErrors).toHaveBeenCalledWith('error'); - }); - }); - describe('apiSuccess', () => { - it('should call flashAPIError', () => { - CancelSyncsLogic.actions.cancelSyncsApiSuccess('success' as any); - expect(flashSuccessToast).toHaveBeenCalledWith('Successfully canceled syncs'); - }); - }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/cancel_syncs_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/cancel_syncs_logic.ts index 73fa34d69c83d..43ae9d81a7336 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/cancel_syncs_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/cancel_syncs_logic.ts @@ -7,14 +7,7 @@ import { kea, MakeLogicType } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { Actions } from '../../../../shared/api_logic/create_api_logic'; -import { - clearFlashMessages, - flashAPIErrors, - flashSuccessToast, -} from '../../../../shared/flash_messages'; import { CancelSyncsApiArgs, @@ -58,17 +51,6 @@ export const CancelSyncsLogic = kea flashAPIErrors(e), - cancelSyncsApiSuccess: () => { - flashSuccessToast( - i18n.translate('xpack.enterpriseSearch.content.searchIndex.cancelSyncs.successMessage', { - defaultMessage: 'Successfully canceled syncs', - }) - ); - }, - makeCancelSyncsRequest: () => { - clearFlashMessages(); - }, }), } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.test.ts index 54b31d832af7f..632d60fac3cad 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { LogicMounter, mockFlashMessageHelpers } from '../../../../__mocks__/kea_logic'; +import { LogicMounter } from '../../../../__mocks__/kea_logic'; import { connectorIndex } from '../../../__mocks__/view_index.mock'; import { ConnectorStatus } from '../../../../../../common/types/connectors'; @@ -33,7 +33,6 @@ describe('ConnectorConfigurationLogic', () => { const { mount: mountIndexNameLogic } = new LogicMounter(IndexNameLogic); const { mount: mountFetchIndexApiWrapperLogic } = new LogicMounter(CachedFetchIndexApiLogic); const { mount: mountIndexViewLogic } = new LogicMounter(IndexViewLogic); - const { clearFlashMessages, flashAPIErrors, flashSuccessToast } = mockFlashMessageHelpers; beforeEach(() => { jest.clearAllMocks(); @@ -70,31 +69,6 @@ describe('ConnectorConfigurationLogic', () => { configView: [{ key: 'foo', label: 'thirdBar', value: 'fourthBar' }], }); }); - describe('makeRequest', () => { - it('should call clearFlashMessages', () => { - ConnectorConfigurationLogic.actions.makeRequest({ - configuration: {}, - connectorId: 'id', - indexName: 'name', - }); - expect(clearFlashMessages).toHaveBeenCalled(); - }); - }); - describe('apiError', () => { - it('should call flashAPIError', () => { - ConnectorConfigurationLogic.actions.apiError('error' as any); - expect(flashAPIErrors).toHaveBeenCalledWith('error'); - }); - }); - describe('apiSuccess', () => { - it('should call flashAPIError', () => { - ConnectorConfigurationLogic.actions.apiSuccess({ - configuration: {}, - indexName: 'name', - }); - expect(flashSuccessToast).toHaveBeenCalledWith('Configuration successfully updated'); - }); - }); describe('setLocalConfigEntry', () => { it('should set local config entry and sort keys', () => { ConnectorConfigurationLogic.actions.setConfigState({ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts index b2c7d7091ad76..c939b37fac8ad 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts @@ -7,15 +7,8 @@ import { kea, MakeLogicType } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { ConnectorConfiguration, ConnectorStatus } from '../../../../../../common/types/connectors'; import { Actions } from '../../../../shared/api_logic/create_api_logic'; -import { - clearFlashMessages, - flashAPIErrors, - flashSuccessToast, -} from '../../../../shared/flash_messages'; import { ConnectorConfigurationApiLogic, @@ -31,7 +24,7 @@ import { isConnectorIndex } from '../../../utils/indices'; type ConnectorConfigurationActions = Pick< Actions, - 'apiError' | 'apiSuccess' | 'makeRequest' + 'apiSuccess' | 'makeRequest' > & { fetchIndexApiSuccess: CachedFetchIndexApiLogicActions['apiSuccess']; saveConfig: () => void; @@ -78,7 +71,7 @@ export const ConnectorConfigurationLogic = kea< connect: { actions: [ ConnectorConfigurationApiLogic, - ['apiError', 'apiSuccess', 'makeRequest'], + ['apiSuccess'], CachedFetchIndexApiLogic, ['apiSuccess as fetchIndexApiSuccess'], ], @@ -101,14 +94,7 @@ export const ConnectorConfigurationLogic = kea< }, }), listeners: ({ actions, values }) => ({ - apiError: (error) => flashAPIErrors(error), apiSuccess: ({ indexName }) => { - flashSuccessToast( - i18n.translate( - 'xpack.enterpriseSearch.content.indices.configurationConnector.configuration.successToast.title', - { defaultMessage: 'Configuration successfully updated' } - ) - ); CachedFetchIndexApiLogic.actions.makeRequest({ indexName }); }, fetchIndexApiSuccess: (index) => { @@ -127,7 +113,6 @@ export const ConnectorConfigurationLogic = kea< actions.setIsEditing(true); } }, - makeRequest: () => clearFlashMessages(), saveConfig: () => { if (isConnectorIndex(values.index)) { actions.makeRequest({ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_logic.ts index 934b7c11e180f..563951fddf3eb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_logic.ts @@ -7,15 +7,8 @@ import { kea, MakeLogicType } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { Connector } from '../../../../../../../common/types/connectors'; import { Actions } from '../../../../../shared/api_logic/create_api_logic'; -import { - flashAPIErrors, - flashSuccessToast, - clearFlashMessages, -} from '../../../../../shared/flash_messages'; import { ConnectorNameAndDescriptionApiLogic, PutConnectorNameAndDescriptionArgs, @@ -32,7 +25,7 @@ type NameAndDescription = Partial>; type ConnectorNameAndDescriptionActions = Pick< Actions, - 'apiError' | 'apiSuccess' | 'makeRequest' + 'apiSuccess' | 'makeRequest' > & { fetchIndexApiSuccess: CachedFetchIndexApiLogicActions['apiSuccess']; saveNameAndDescription: () => void; @@ -77,22 +70,11 @@ export const ConnectorNameAndDescriptionLogic = kea< ), }), listeners: ({ actions, values }) => ({ - apiError: (error) => flashAPIErrors(error), - apiSuccess: ({ indexName }) => { - flashSuccessToast( - i18n.translate( - 'xpack.enterpriseSearch.content.indices.configurationConnector.configuration.successToast.title', - { defaultMessage: 'Configuration successfully updated' } - ) - ); - CachedFetchIndexApiLogic.actions.makeRequest({ indexName }); - }, fetchIndexApiSuccess: (index) => { if (!values.isEditing && isConnectorIndex(index)) { actions.setNameAndDescription(index.connector); } }, - makeRequest: () => clearFlashMessages(), saveNameAndDescription: () => { if (isConnectorIndex(values.index) || isCrawlerIndex(values.index)) { actions.makeRequest({ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling_logic.test.ts index b355273a71012..e2897a053a5b4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling_logic.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { LogicMounter, mockFlashMessageHelpers } from '../../../../__mocks__/kea_logic'; +import { LogicMounter } from '../../../../__mocks__/kea_logic'; import { UpdateConnectorSchedulingApiLogic } from '../../../api/connector/update_connector_scheduling_api_logic'; @@ -13,7 +13,6 @@ import { ConnectorSchedulingLogic } from './connector_scheduling_logic'; describe('ConnectorSchedulingLogic', () => { const { mount } = new LogicMounter(ConnectorSchedulingLogic); - const { clearFlashMessages, flashAPIErrors, flashSuccessToast } = mockFlashMessageHelpers; const DEFAULT_VALUES = { hasChanges: false, }; @@ -48,31 +47,4 @@ describe('ConnectorSchedulingLogic', () => { }); }); }); - - describe('actions', () => { - describe('makeRequest', () => { - it('should call clearFlashMessages', () => { - ConnectorSchedulingLogic.actions.makeRequest({ - connectorId: 'id', - scheduling: { - enabled: true, - interval: 'interval', - }, - }); - expect(clearFlashMessages).toHaveBeenCalled(); - }); - }); - describe('apiError', () => { - it('should call flashAPIError', () => { - ConnectorSchedulingLogic.actions.apiError('error' as any); - expect(flashAPIErrors).toHaveBeenCalledWith('error'); - }); - }); - describe('apiSuccess', () => { - it('should call flashAPIError', () => { - ConnectorSchedulingLogic.actions.apiSuccess('success' as any); - expect(flashSuccessToast).toHaveBeenCalledWith('Scheduling successfully updated'); - }); - }); - }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling_logic.ts index a9b99a734d704..73a624351cbb8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling_logic.ts @@ -7,15 +7,8 @@ import { kea, MakeLogicType } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { ConnectorScheduling } from '../../../../../../common/types/connectors'; import { Actions } from '../../../../shared/api_logic/create_api_logic'; -import { - clearFlashMessages, - flashAPIErrors, - flashSuccessToast, -} from '../../../../shared/flash_messages'; import { UpdateConnectorSchedulingApiLogic, @@ -24,7 +17,7 @@ import { type ConnectorSchedulingActions = Pick< Actions, - 'apiError' | 'apiSuccess' | 'makeRequest' + 'apiSuccess' > & { setHasChanges: (hasChanges: boolean) => { hasChanges: boolean } }; interface ConnectorSchedulingValues { @@ -38,18 +31,7 @@ export const ConnectorSchedulingLogic = kea< setHasChanges: (hasChanges) => ({ hasChanges }), }, connect: { - actions: [UpdateConnectorSchedulingApiLogic, ['apiError', 'apiSuccess', 'makeRequest']], - }, - listeners: { - apiError: (error) => flashAPIErrors(error), - apiSuccess: () => - flashSuccessToast( - i18n.translate( - 'xpack.enterpriseSearch.content.indices.configurationConnector.scheduling.successToast.title', - { defaultMessage: 'Scheduling successfully updated' } - ) - ), - makeRequest: () => clearFlashMessages(), + actions: [UpdateConnectorSchedulingApiLogic, ['apiSuccess']], }, reducers: { hasChanges: [ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/select_connector/select_connector_logic.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/select_connector/select_connector_logic.tsx index 48af3e24fa8b9..fec06e823a4db 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/select_connector/select_connector_logic.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/select_connector/select_connector_logic.tsx @@ -9,7 +9,6 @@ import { kea, MakeLogicType } from 'kea'; import { Actions } from '../../../../../shared/api_logic/create_api_logic'; import { generateEncodedPath } from '../../../../../shared/encode_path_params'; -import { clearFlashMessages, flashAPIErrors } from '../../../../../shared/flash_messages'; import { KibanaLogic } from '../../../../../shared/kibana'; import { @@ -28,7 +27,7 @@ import { NativeConnector } from '../types'; type SelectConnectorActions = Pick< Actions, - 'apiError' | 'apiSuccess' | 'makeRequest' + 'apiSuccess' | 'makeRequest' > & { saveNativeConnector(): void; setSelectedConnector(nativeConnector: NativeConnector): { @@ -66,11 +65,9 @@ export const SelectConnectorLogic = kea< }, }), listeners: ({ actions, values }) => ({ - apiError: (error) => flashAPIErrors(error), apiSuccess: () => { CachedFetchIndexApiLogic.actions.makeRequest({ indexName: values.index.name }); }, - makeRequest: () => clearFlashMessages(), saveNativeConnector: () => { if (!isConnectorIndex(values.index) || values.selectedNativeConnector === null) { KibanaLogic.values.navigateToUrl( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/sync_rules/connector_filtering_logic.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/sync_rules/connector_filtering_logic.tsx index c430794063a76..13db854fa79e9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/sync_rules/connector_filtering_logic.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/sync_rules/connector_filtering_logic.tsx @@ -9,8 +9,6 @@ import { kea, MakeLogicType } from 'kea'; import { isEqual } from 'lodash'; -import { i18n } from '@kbn/i18n'; - import { Status } from '../../../../../../../common/types/api'; import { @@ -22,11 +20,7 @@ import { FilteringValidationState, } from '../../../../../../../common/types/connectors'; import { Actions } from '../../../../../shared/api_logic/create_api_logic'; -import { - flashAPIErrors, - flashSuccessToast, - clearFlashMessages, -} from '../../../../../shared/flash_messages'; +import { clearFlashMessages } from '../../../../../shared/flash_messages'; import { ConnectorFilteringApiLogic, PutConnectorFilteringArgs, @@ -46,7 +40,7 @@ import { isConnectorIndex } from '../../../../utils/indices'; type ConnectorFilteringActions = Pick< Actions, - 'apiError' | 'apiSuccess' | 'makeRequest' + 'apiSuccess' | 'makeRequest' > & { addFilteringRule(filteringRule: FilteringRule): FilteringRule; applyDraft: () => void; @@ -134,7 +128,7 @@ export const ConnectorFilteringLogic = kea< connect: { actions: [ ConnectorFilteringApiLogic, - ['apiError', 'apiSuccess', 'makeRequest'], + ['apiSuccess', 'makeRequest'], ConnectorFilteringDraftApiLogic, [ 'apiError as draftApiError', @@ -153,15 +147,6 @@ export const ConnectorFilteringLogic = kea< ), }), listeners: ({ actions, values }) => ({ - apiError: (error) => flashAPIErrors(error), - apiSuccess: () => { - flashSuccessToast( - i18n.translate( - 'xpack.enterpriseSearch.content.index.connector.filtering.successToastRules.title', - { defaultMessage: 'Sync rules updated' } - ) - ); - }, applyDraft: () => { if (isConnectorIndex(values.index)) { actions.makeRequest({ @@ -171,16 +156,6 @@ export const ConnectorFilteringLogic = kea< }); } }, - draftApiError: (error) => flashAPIErrors(error), - draftApiSuccess: () => { - flashSuccessToast( - i18n.translate( - 'xpack.enterpriseSearch.content.index.connector.syncRules.successToastDraft.title', - { defaultMessage: 'Draft rules saved' } - ) - ); - }, - draftMakeRequest: () => clearFlashMessages(), fetchIndexApiSuccess: (index) => { if ( !values.isEditing && diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_logic.ts index 3d8954d2210e6..7d25ad679d00c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_logic.ts @@ -86,9 +86,6 @@ export const CrawlerLogic = kea>({ values: [GetCrawlerApiLogic, ['status', 'data'], CachedFetchIndexApiLogic, ['indexData']], }, listeners: ({ actions, values }) => ({ - apiError: (error) => { - flashAPIErrors(error); - }, fetchCrawlerData: () => { const { indexName } = IndexNameLogic.values; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/delete_domain_modal_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/delete_domain_modal_logic.ts index 96294170d6b77..9c69da8decbb5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/delete_domain_modal_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/delete_domain_modal_logic.ts @@ -13,11 +13,8 @@ import { kea, MakeLogicType } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { Status } from '../../../../../../../common/types/api'; import { Actions } from '../../../../../shared/api_logic/create_api_logic'; -import { flashAPIErrors, flashSuccessToast } from '../../../../../shared/flash_messages'; import { DeleteCrawlerDomainApiLogic, DeleteCrawlerDomainResponse, @@ -74,18 +71,7 @@ export const DeleteDomainModalLogic = kea< ], }, listeners: ({ values }) => ({ - apiError: (error) => { - flashAPIErrors(error); - }, - apiSuccess: ({ domain }) => { - flashSuccessToast( - i18n.translate('xpack.enterpriseSearch.crawler.domainsTable.action.delete.successMessage', { - defaultMessage: "Successfully deleted domain '{domainUrl}'", - values: { - domainUrl: domain.url, - }, - }) - ); + apiSuccess: () => { CrawlerLogic.actions.fetchCrawlerData(); }, deleteDomain: () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/domain_management_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/domain_management_logic.ts index 8131ceb250757..e023b865ca987 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/domain_management_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/domain_management_logic.ts @@ -14,9 +14,8 @@ import { kea, MakeLogicType } from 'kea'; import { Meta } from '../../../../../../../common/types'; -import { HttpError, Status } from '../../../../../../../common/types/api'; +import { Status } from '../../../../../../../common/types/api'; import { DEFAULT_META } from '../../../../../shared/constants'; -import { flashAPIErrors } from '../../../../../shared/flash_messages'; import { updateMetaPageIndex } from '../../../../../shared/table_pagination'; import { DeleteCrawlerDomainApiLogic } from '../../../../api/crawler/delete_crawler_domain_api_logic'; import { GetCrawlerDomainsApiLogic } from '../../../../api/crawler/get_crawler_domains_api_logic'; @@ -33,10 +32,8 @@ interface DomainManagementValues { } interface DomainManagementActions { - deleteApiError(error: HttpError): HttpError; deleteDomain(domain: CrawlerDomain): { domain: CrawlerDomain }; deleteSuccess(): void; - getApiError(error: HttpError): HttpError; getApiSuccess(data: CrawlerDomainsWithMeta): CrawlerDomainsWithMeta; getDomains(meta: Meta): { meta: Meta }; onPaginate(newPageIndex: number): { newPageIndex: number }; @@ -48,9 +45,9 @@ export const DomainManagementLogic = kea< connect: { actions: [ GetCrawlerDomainsApiLogic, - ['apiError as getApiError', 'apiSuccess as getApiSuccess'], + ['apiSuccess as getApiSuccess'], DeleteCrawlerDomainApiLogic, - ['apiError as deleteApiError', 'apiSuccess as deleteApiSuccess'], + ['apiSuccess as deleteApiSuccess'], ], values: [ GetCrawlerDomainsApiLogic, @@ -68,9 +65,6 @@ export const DomainManagementLogic = kea< }), }, listeners: ({ values, actions }) => ({ - deleteApiError: (error) => { - flashAPIErrors(error); - }, deleteApiSuccess: () => { actions.getDomains(values.meta); }, @@ -78,9 +72,6 @@ export const DomainManagementLogic = kea< const { indexName } = IndexNameLogic.values; DeleteCrawlerDomainApiLogic.actions.makeRequest({ domain, indexName }); }, - getApiError: (error) => { - flashAPIErrors(error); - }, getDomains: ({ meta }) => { const { indexName } = IndexNameLogic.values; GetCrawlerDomainsApiLogic.actions.makeRequest({ indexName, meta }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/documents_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/documents_logic.test.ts index 1f255a049d26e..28037f346c1ad 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/documents_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/documents_logic.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { LogicMounter, mockFlashMessageHelpers } from '../../../__mocks__/kea_logic'; +import { LogicMounter } from '../../../__mocks__/kea_logic'; import { nextTick } from '@kbn/test-jest-helpers'; @@ -101,22 +101,6 @@ describe('DocumentsLogic', () => { jest.useRealTimers(); }); }); - it('calls flashAPIErrors on apiError', () => { - DocumentsLogic.actions.apiError({} as HttpError); - expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1); - }); - it('calls flashAPIErrors on mappingsApiError', () => { - DocumentsLogic.actions.mappingsApiError({} as HttpError); - expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1); - }); - it('clears flash messages on new makeRequest', () => { - DocumentsLogic.actions.makeRequest({ - indexName: 'index', - pagination: convertMetaToPagination(INDEX_DOCUMENTS_META_DEFAULT), - query: '', - }); - expect(mockFlashMessageHelpers.clearFlashMessages).toHaveBeenCalledTimes(1); - }); }); describe('selectors', () => { describe('isLoading', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/documents_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/documents_logic.ts index 439e8652ffc3c..093c4f5f399cc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/documents_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/documents_logic.ts @@ -16,9 +16,8 @@ import { import { ENTERPRISE_SEARCH_DOCUMENTS_DEFAULT_DOC_COUNT } from '../../../../../common/constants'; import { Meta } from '../../../../../common/types'; -import { HttpError, Status } from '../../../../../common/types/api'; +import { Status } from '../../../../../common/types/api'; -import { flashAPIErrors, clearFlashMessages } from '../../../shared/flash_messages'; import { updateMetaPageIndex } from '../../../shared/table_pagination'; import { MappingsApiLogic } from '../../api/mappings/mappings_logic'; @@ -42,11 +41,9 @@ export const DEFAULT_PAGINATION = { }; interface DocumentsLogicActions { - apiError(error: HttpError): HttpError; apiReset: typeof SearchDocumentsApiLogic.actions.apiReset; makeMappingRequest: typeof MappingsApiLogic.actions.makeRequest; makeRequest: typeof SearchDocumentsApiLogic.actions.makeRequest; - mappingsApiError(error: HttpError): HttpError; onPaginate(newPageIndex: number): { newPageIndex: number }; setDocsPerPage(docsPerPage: number): { docsPerPage: number }; setSearchQuery(query: string): { query: string }; @@ -81,9 +78,9 @@ export const DocumentsLogic = kea ({ - apiError: (e) => flashAPIErrors(e), - makeRequest: () => clearFlashMessages(), - mappingsApiError: (e) => flashAPIErrors(e), onPaginate: () => { actions.makeRequest({ docsPerPage: values.docsPerPage, diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_view_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_view_logic.test.ts index f4f28ace3ae9a..3ff4355636f89 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_view_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_view_logic.test.ts @@ -14,7 +14,7 @@ import { apiIndex, connectorIndex, crawlerIndex } from '../../__mocks__/view_ind import { nextTick } from '@kbn/test-jest-helpers'; -import { HttpError, Status } from '../../../../../common/types/api'; +import { Status } from '../../../../../common/types/api'; import { SyncStatus } from '../../../../../common/types/connectors'; import { StartSyncApiLogic } from '../../api/connector/start_sync_api_logic'; @@ -229,16 +229,6 @@ describe('IndexViewLogic', () => { }); describe('listeners', () => { - it('calls clearFlashMessages on makeStartSyncRequest', () => { - IndexViewLogic.actions.makeStartSyncRequest({ connectorId: 'connectorId' }); - expect(mockFlashMessageHelpers.clearFlashMessages).toHaveBeenCalledTimes(1); - }); - - it('calls flashAPIErrors on apiError', () => { - IndexViewLogic.actions.startSyncApiError({} as HttpError); - expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1); - expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledWith({}); - }); it('calls makeFetchIndexRequest on fetchIndex', () => { IndexViewLogic.actions.makeFetchIndexRequest = jest.fn(); IndexNameLogic.actions.setIndexName('indexName'); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_view_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_view_logic.ts index 07f6f70aae37b..2d3651a598fc1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_view_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_view_logic.ts @@ -18,11 +18,7 @@ import { } from '../../../../../common/types/connectors'; import { ElasticsearchIndexWithIngestion } from '../../../../../common/types/indices'; import { Actions } from '../../../shared/api_logic/create_api_logic'; -import { - flashAPIErrors, - clearFlashMessages, - flashSuccessToast, -} from '../../../shared/flash_messages'; +import { flashSuccessToast } from '../../../shared/flash_messages'; import { StartSyncApiLogic, StartSyncArgs } from '../../api/connector/start_sync_api_logic'; import { @@ -60,8 +56,6 @@ export interface IndexViewActions { resetRecheckIndexLoading: () => void; startFetchIndexPoll: CachedFetchIndexApiLogicActions['startPolling']; startSync(): void; - startSyncApiError: StartSyncApiActions['apiError']; - startSyncApiSuccess: StartSyncApiActions['apiSuccess']; stopFetchIndexPoll(): CachedFetchIndexApiLogicActions['stopPolling']; stopFetchIndexPoll(): void; } @@ -114,11 +108,7 @@ export const IndexViewLogic = kea clearFlashMessages(), recheckIndex: () => actions.fetchIndex(), setIndexName: ({ indexName }) => { actions.startFetchIndexPoll(indexName); @@ -166,14 +155,6 @@ export const IndexViewLogic = kea flashAPIErrors(e), - startSyncApiSuccess: () => { - flashSuccessToast( - i18n.translate('xpack.enterpriseSearch.content.searchIndex.index.syncSuccess.message', { - defaultMessage: 'Successfully scheduled a sync, waiting for a connector to pick it up', - }) - ); - }, }), path: ['enterprise_search', 'content', 'index_view_logic'], reducers: { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.logic.ts index 4d3a8ec40834b..34584d394b93a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.logic.ts @@ -8,7 +8,6 @@ import { kea, MakeLogicType } from 'kea'; import { Status } from '../../../../../common/types/api'; -import { flashAPIErrors } from '../../../shared/flash_messages'; import { KibanaLogic } from '../../../shared/kibana'; import { GenerateApiKeyLogic } from '../../api/generate_api_key/generate_api_key_logic'; @@ -58,8 +57,7 @@ export const OverviewLogic = kea ({ - apiError: async (error, breakpoint) => { - flashAPIErrors(error); + apiError: async (_, breakpoint) => { // show error for a second before navigating away await breakpoint(1000); KibanaLogic.values.navigateToUrl(SEARCH_INDICES_PATH); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors.tsx index 0b380e003f48d..554c7d1162d0d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors.tsx @@ -16,14 +16,16 @@ import { i18n } from '@kbn/i18n'; import { MlInferenceError } from '../../../../../../common/types/pipelines'; import { DataPanel } from '../../../../shared/data_panel/data_panel'; +import { FetchMlInferenceErrorsApiLogic } from '../../../api/pipelines/fetch_ml_inference_pipeline_errors'; + import { InferenceErrorsLogic } from './inference_errors_logic'; export const InferenceErrors: React.FC = () => { const { indexName, isLoading, inferenceErrors } = useValues(InferenceErrorsLogic); - const { fetchIndexInferenceErrorLogs } = useActions(InferenceErrorsLogic); + const { makeRequest } = useActions(FetchMlInferenceErrorsApiLogic); useEffect(() => { - fetchIndexInferenceErrorLogs({ indexName }); + makeRequest({ indexName }); }, [indexName]); const errorsColumns: Array> = [ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors_logic.test.ts index a9d07657b94ab..9b4414b4ec1ba 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors_logic.test.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { LogicMounter, mockFlashMessageHelpers } from '../../../../__mocks__/kea_logic'; +import { LogicMounter } from '../../../../__mocks__/kea_logic'; import { Status } from '../../../../../../common/types/api'; import { FetchMlInferenceErrorsApiLogic } from '../../../api/pipelines/fetch_ml_inference_pipeline_errors'; @@ -24,7 +24,6 @@ describe('InferenceErrorsLogic', () => { const { mount: mountFetchInferenceErrorsApiLogic } = new LogicMounter( FetchMlInferenceErrorsApiLogic ); - const { clearFlashMessages, flashAPIErrors } = mockFlashMessageHelpers; beforeEach(() => { jest.clearAllMocks(); mountFetchInferenceErrorsApiLogic(); @@ -36,14 +35,6 @@ describe('InferenceErrorsLogic', () => { }); describe('actions', () => { - it('should clear flash errors when fetching data', () => { - FetchMlInferenceErrorsApiLogic.actions.makeRequest({ indexName: 'test' }); - expect(clearFlashMessages).toHaveBeenCalledTimes(1); - }); - it('should flash errors fetching errors', () => { - FetchMlInferenceErrorsApiLogic.actions.apiError('error' as any); - expect(flashAPIErrors).toHaveBeenCalledWith('error'); - }); it('should load fetched errors', () => { const inferenceErrorsData = { errors: [ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors_logic.ts index 520af1bbd6c39..9bc466597d92d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors_logic.ts @@ -9,26 +9,12 @@ import { kea, MakeLogicType } from 'kea'; import { Status } from '../../../../../../common/types/api'; import { MlInferenceError } from '../../../../../../common/types/pipelines'; -import { Actions } from '../../../../shared/api_logic/create_api_logic'; -import { clearFlashMessages, flashAPIErrors } from '../../../../shared/flash_messages'; import { - FetchMlInferenceErrorsApiLogicArgs, FetchMlInferenceErrorsApiLogicResponse, FetchMlInferenceErrorsApiLogic, } from '../../../api/pipelines/fetch_ml_inference_pipeline_errors'; import { IndexNameLogic } from '../index_name_logic'; -interface InferenceErrorsActions { - fetchIndexInferenceErrorLogs: Actions< - FetchMlInferenceErrorsApiLogicArgs, - FetchMlInferenceErrorsApiLogicResponse - >['makeRequest']; - fetchIndexInferenceErrorLogsError: Actions< - FetchMlInferenceErrorsApiLogicArgs, - FetchMlInferenceErrorsApiLogicResponse - >['apiError']; -} - interface InferenceErrorsValues { fetchIndexInferenceHistoryStatus: Status; indexName: string; @@ -37,17 +23,8 @@ interface InferenceErrorsValues { isLoading: boolean; } -export const InferenceErrorsLogic = kea< - MakeLogicType ->({ +export const InferenceErrorsLogic = kea>({ connect: { - actions: [ - FetchMlInferenceErrorsApiLogic, - [ - 'makeRequest as fetchIndexInferenceErrorLogs', - 'apiError as fetchIndexInferenceErrorLogsError', - ], - ], values: [ IndexNameLogic, ['indexName'], @@ -55,10 +32,6 @@ export const InferenceErrorsLogic = kea< ['data as inferenceErrorsData', 'status as fetchIndexInferenceHistoryStatus'], ], }, - listeners: () => ({ - fetchIndexInferenceErrorLogs: () => clearFlashMessages(), - fetchIndexInferenceErrorLogsError: (error) => flashAPIErrors(error), - }), path: ['enterprise_search', 'content', 'pipelines_inference_errors'], selectors: ({ selectors }) => ({ inferenceErrors: [ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_history_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_history_logic.ts index e1ec8feb77f09..2d2e4021f2feb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_history_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_history_logic.ts @@ -10,7 +10,6 @@ import { kea, MakeLogicType } from 'kea'; import { Status } from '../../../../../../common/types/api'; import { MlInferenceHistoryItem } from '../../../../../../common/types/pipelines'; import { Actions } from '../../../../shared/api_logic/create_api_logic'; -import { clearFlashMessages, flashAPIErrors } from '../../../../shared/flash_messages'; import { FetchMlInferencePipelineHistoryApiLogicArgs, FetchMlInferencePipelineHistoryApiLogicResponse, @@ -48,10 +47,6 @@ export const InferenceHistoryLogic = kea< ['data as inferenceHistoryData', 'status as fetchIndexInferenceHistoryStatus'], ], }, - listeners: () => ({ - fetchIndexInferenceHistory: () => clearFlashMessages(), - fetchIndexInferenceHistoryError: (error) => flashAPIErrors(error), - }), path: ['enterprise_search', 'content', 'pipelines_inference_history'], selectors: ({ selectors }) => ({ inferenceHistory: [ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.test.ts index 8d74cae4ba998..970119cd58b4f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.test.ts @@ -135,7 +135,7 @@ describe('PipelinesLogic', () => { describe('apiSuccess', () => { it('should call flashSuccessToast', () => { PipelinesLogic.actions.apiSuccess({ connectorId: 'a', pipeline: newPipeline }); - expect(flashSuccessToast).toHaveBeenCalledWith('Pipelines successfully updated'); + expect(flashSuccessToast).toHaveBeenCalledWith('Pipelines updated'); }); }); describe('createCustomPipelineError', () => { @@ -151,7 +151,7 @@ describe('PipelinesLogic', () => { PipelinesLogic.actions.fetchCustomPipeline = jest.fn(); PipelinesLogic.actions.fetchIndexApiSuccess(connectorIndex); PipelinesLogic.actions.createCustomPipelineSuccess({ created: ['a', 'b'] }); - expect(flashSuccessToast).toHaveBeenCalledWith('Custom pipeline successfully created'); + expect(flashSuccessToast).toHaveBeenCalledWith('Custom pipeline created'); expect(PipelinesLogic.actions.setPipelineState).toHaveBeenCalledWith({ ...PipelinesLogic.values.pipelineState, name: 'a', diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.ts index 487f89f57c22a..134155f88a64c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.ts @@ -8,6 +8,7 @@ import { kea, MakeLogicType } from 'kea'; import { IngestPipeline } from '@elastic/elasticsearch/lib/api/types'; + import { i18n } from '@kbn/i18n'; import { DEFAULT_PIPELINE_VALUES } from '../../../../../../common/constants'; @@ -17,11 +18,7 @@ import { IngestPipelineParams } from '../../../../../../common/types/connectors' import { ElasticsearchIndexWithIngestion } from '../../../../../../common/types/indices'; import { InferencePipeline } from '../../../../../../common/types/pipelines'; import { Actions } from '../../../../shared/api_logic/create_api_logic'; -import { - clearFlashMessages, - flashAPIErrors, - flashSuccessToast, -} from '../../../../shared/flash_messages'; +import { flashSuccessToast } from '../../../../shared/flash_messages'; import { FetchDefaultPipelineApiLogic, @@ -227,7 +224,6 @@ export const PipelinesLogic = kea ({ - apiError: (error) => flashAPIErrors(error), apiSuccess: ({ pipeline }) => { if (isConnectorIndex(values.index) || isCrawlerIndex(values.index)) { if (values.index.connector) { @@ -238,11 +234,6 @@ export const PipelinesLogic = kea { // Re-fetch processors to ensure we display newly added ml processor @@ -256,16 +247,7 @@ export const PipelinesLogic = kea flashAPIErrors(error), createCustomPipelineSuccess: ({ created }) => { - flashSuccessToast( - i18n.translate( - 'xpack.enterpriseSearch.content.indices.pipelines.successToastCustom.title', - { - defaultMessage: 'Custom pipeline successfully created', - } - ) - ); actions.setPipelineState({ ...values.pipelineState, name: created[0] }); actions.savePipeline(); actions.fetchCustomPipeline({ indexName: values.index.name }); @@ -276,7 +258,6 @@ export const PipelinesLogic = kea flashAPIErrors(error), deleteMlPipelineSuccess: (value) => { if (value.deleted) { flashSuccessToast( @@ -296,7 +277,6 @@ export const PipelinesLogic = kea flashAPIErrors(error), detachMlPipelineSuccess: (response) => { if (response.updated) { flashSuccessToast( @@ -326,7 +306,6 @@ export const PipelinesLogic = kea clearFlashMessages(), openModal: () => { const pipeline = isCrawlerIndex(values.index) || isConnectorIndex(values.index) diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs/sync_jobs_view_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs/sync_jobs_view_logic.test.ts index 544d48110941a..28af9f3d1a72d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs/sync_jobs_view_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs/sync_jobs_view_logic.test.ts @@ -188,11 +188,9 @@ describe('SyncJobsViewLogic', () => { expect(mockFlashMessageHelpers.clearFlashMessages).toHaveBeenCalledTimes(1); }); - it('calls flashAPIErrors on apiError', async () => { + it('updates state on apiError', async () => { SyncJobsViewLogic.actions.fetchSyncJobsError({} as HttpError); await nextTick(); - expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1); - expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledWith({}); expect(SyncJobsViewLogic.values).toEqual({ ...DEFAULT_VALUES, syncJobsLoading: false, diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs/sync_jobs_view_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs/sync_jobs_view_logic.ts index 91852dbaaec72..e8feb159dbcd0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs/sync_jobs_view_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs/sync_jobs_view_logic.ts @@ -14,7 +14,6 @@ import { Status } from '../../../../../../common/types/api'; import { ConnectorSyncJob } from '../../../../../../common/types/connectors'; import { Paginate } from '../../../../../../common/types/pagination'; import { Actions } from '../../../../shared/api_logic/create_api_logic'; -import { clearFlashMessages, flashAPIErrors } from '../../../../shared/flash_messages'; import { FetchSyncJobsApiLogic, FetchSyncJobsArgs, @@ -61,10 +60,6 @@ export const SyncJobsViewLogic = kea ({ - fetchSyncJobs: () => clearFlashMessages(), - fetchSyncJobsError: (e) => flashAPIErrors(e), - }), path: ['enterprise_search', 'content', 'sync_jobs_view_logic'], selectors: ({ selectors }) => ({ syncJobs: [ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.test.ts index e7405c45bf4a6..acf1eaa9f8331 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.test.ts @@ -266,7 +266,7 @@ describe('IndicesLogic', () => { isDeleteLoading: true, }); }); - it('should update isDeleteLoading to to false on apiError', () => { + it('should update isDeleteLoading to false on apiError', () => { IndicesLogic.actions.deleteIndex({ indexName: 'to-delete' }); IndicesLogic.actions.deleteError({} as HttpError); @@ -276,9 +276,9 @@ describe('IndicesLogic', () => { isDeleteLoading: false, }); }); - it('should update isDeleteLoading to to false on apiSuccess', () => { + it('should update isDeleteLoading to false on apiSuccess', () => { IndicesLogic.actions.deleteIndex({ indexName: 'to-delete' }); - IndicesLogic.actions.deleteSuccess(); + IndicesLogic.actions.deleteSuccess({ indexName: 'to-delete' }); expect(IndicesLogic.values).toEqual({ ...DEFAULT_VALUES, @@ -294,20 +294,10 @@ describe('IndicesLogic', () => { IndicesLogic.actions.makeRequest({ meta: DEFAULT_META, returnHiddenIndices: false }); expect(mockFlashMessageHelpers.clearFlashMessages).toHaveBeenCalledTimes(1); }); - it('calls flashAPIErrors on apiError', () => { - IndicesLogic.actions.apiError({} as HttpError); - expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1); - expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledWith({}); - }); - it('calls flashAPIErrors on deleteError', () => { - IndicesLogic.actions.deleteError({} as HttpError); - expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1); - expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledWith({}); - }); it('calls flashSuccessToast, closeDeleteModal and fetchIndices on deleteSuccess', () => { IndicesLogic.actions.fetchIndices = jest.fn(); IndicesLogic.actions.closeDeleteModal = jest.fn(); - IndicesLogic.actions.deleteSuccess(); + IndicesLogic.actions.deleteSuccess({ indexName: 'index-name' }); expect(mockFlashMessageHelpers.flashSuccessToast).toHaveBeenCalledTimes(1); expect(IndicesLogic.actions.fetchIndices).toHaveBeenCalledWith( IndicesLogic.values.searchParams diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.ts index a771a29a3c0d9..282566637e103 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.ts @@ -7,22 +7,16 @@ import { kea, MakeLogicType } from 'kea'; -import { i18n } from '@kbn/i18n'; - import { Meta } from '../../../../../common/types'; import { HttpError, Status } from '../../../../../common/types/api'; import { ElasticsearchIndexWithIngestion } from '../../../../../common/types/indices'; import { Actions } from '../../../shared/api_logic/create_api_logic'; import { DEFAULT_META } from '../../../shared/constants'; -import { - flashAPIErrors, - clearFlashMessages, - flashSuccessToast, -} from '../../../shared/flash_messages'; import { updateMetaPageIndex } from '../../../shared/table_pagination'; import { DeleteIndexApiLogic, DeleteIndexApiLogicArgs, + DeleteIndexApiLogicValues, } from '../../api/index/delete_index_api_logic'; import { FetchIndicesAPILogic } from '../../api/index/fetch_indices_api_logic'; import { ElasticsearchViewIndex, IngestionMethod } from '../../types'; @@ -50,9 +44,9 @@ export interface IndicesActions { searchQuery?: string; }; closeDeleteModal(): void; - deleteError: Actions['apiError']; - deleteIndex: Actions['makeRequest']; - deleteSuccess: Actions['apiSuccess']; + deleteError: Actions['apiError']; + deleteIndex: Actions['makeRequest']; + deleteSuccess: Actions['apiSuccess']; fetchIndices({ meta, returnHiddenIndices, @@ -111,18 +105,7 @@ export const IndicesLogic = kea>({ ], }, listeners: ({ actions, values }) => ({ - apiError: (e) => flashAPIErrors(e), - deleteError: (e) => flashAPIErrors(e), deleteSuccess: () => { - flashSuccessToast( - i18n.translate('xpack.enterpriseSearch.content.indices.deleteIndex.successToast.title', { - defaultMessage: - 'Your index {indexName} and any associated ingestion configurations were successfully deleted', - values: { - indexName: values.deleteModalIndexName, - }, - }) - ); actions.closeDeleteModal(); actions.fetchIndices(values.searchParams); }, @@ -130,7 +113,6 @@ export const IndicesLogic = kea>({ await breakpoint(150); actions.makeRequest(input); }, - makeRequest: () => clearFlashMessages(), }), path: ['enterprise_search', 'content', 'indices_logic'], reducers: () => ({ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings_logic.ts index 11c63043e989a..84c03f821442b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings_logic.ts @@ -9,18 +9,11 @@ import { kea, MakeLogicType } from 'kea'; import { isDeepEqual } from 'react-use/lib/util'; -import { i18n } from '@kbn/i18n'; - import { DEFAULT_PIPELINE_VALUES } from '../../../../../common/constants'; import { Status } from '../../../../../common/types/api'; import { IngestPipelineParams } from '../../../../../common/types/connectors'; import { Actions } from '../../../shared/api_logic/create_api_logic'; -import { - clearFlashMessages, - flashAPIErrors, - flashSuccessToast, -} from '../../../shared/flash_messages'; import { FetchDefaultPipelineApiLogic, @@ -81,22 +74,12 @@ export const SettingsLogic = kea ({ - apiError: (error) => flashAPIErrors(error), apiSuccess: (pipeline) => { - flashSuccessToast( - i18n.translate( - 'xpack.enterpriseSearch.content.indices.defaultPipelines.successToast.title', - { - defaultMessage: 'Default pipeline successfully updated', - } - ) - ); actions.fetchDefaultPipelineSuccess(pipeline); }, fetchDefaultPipelineSuccess: (pipeline) => { actions.setPipeline(pipeline); }, - makeRequest: () => clearFlashMessages(), }), path: ['enterprise_search', 'content', 'settings'], reducers: () => ({ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/routes.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/routes.ts index 82a2af053773a..edd3aa3d42edb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/routes.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/routes.ts @@ -23,5 +23,6 @@ export const SEARCH_INDEX_CRAWLER_DOMAIN_DETAIL_PATH = `${SEARCH_INDEX_PATH}/cra export const SEARCH_INDEX_SELECT_CONNECTOR_PATH = `${SEARCH_INDEX_PATH}/select_connector`; export const ENGINES_PATH = `${ROOT_PATH}engines`; +export const ENGINE_CREATION_PATH = `${ENGINES_PATH}/new`; export const ML_MANAGE_TRAINED_MODELS_PATH = '/app/ml/trained_models'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/api_logic/create_api_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/api_logic/create_api_logic.test.ts index 7349f036c255d..ced4a7c5004b5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/api_logic/create_api_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/api_logic/create_api_logic.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { LogicMounter } from '../../__mocks__/kea_logic'; +import { LogicMounter, mockFlashMessageHelpers } from '../../__mocks__/kea_logic'; import { nextTick } from '@kbn/test-jest-helpers'; @@ -26,6 +26,7 @@ describe('CreateApiLogic', () => { const apiCallMock = jest.fn(); const logic = createApiLogic(['path'], apiCallMock); const { mount } = new LogicMounter(logic); + const { clearFlashMessages, flashSuccessToast, flashAPIErrors } = mockFlashMessageHelpers; beforeEach(() => { jest.clearAllMocks(); @@ -45,6 +46,7 @@ describe('CreateApiLogic', () => { apiStatus: { status: Status.LOADING }, status: Status.LOADING, }); + expect(clearFlashMessages).toHaveBeenCalled(); }); it('should set persist data in between new requests', () => { @@ -57,6 +59,16 @@ describe('CreateApiLogic', () => { status: Status.LOADING, }); }); + + it('should not call clearFlashMessages if clearFlashMessages param is false', () => { + const messageLogic = createApiLogic(['message_path'], apiCallMock, { + clearFlashMessagesOnMakeRequest: false, + }); + const { mount: messageMount } = messageLogic; + messageMount(); + messageLogic.actions.makeRequest({}); + expect(clearFlashMessages).not.toHaveBeenCalled(); + }); }); describe('apiSuccess', () => { it('should set status to SUCCESS and load data', () => { @@ -70,6 +82,16 @@ describe('CreateApiLogic', () => { data: { success: 'data' }, status: Status.SUCCESS, }); + expect(flashSuccessToast).not.toHaveBeenCalled(); + }); + it('should call flashSuccessToast if success function provided', () => { + const messageLogic = createApiLogic(['message_path'], apiCallMock, { + showSuccessFlashFn: () => 'test message', + }); + const { mount: messageMount } = messageLogic; + messageMount(); + messageLogic.actions.apiSuccess({}); + expect(flashSuccessToast).toHaveBeenCalledWith('test message'); }); }); describe('apiError', () => { @@ -86,6 +108,16 @@ describe('CreateApiLogic', () => { error: 'error', status: Status.ERROR, }); + expect(flashAPIErrors).toHaveBeenCalledWith('error'); + }); + it('should not call flashApiErrors if showErrorFlash param is set to false', () => { + const messageLogic = createApiLogic(['message_path'], apiCallMock, { + showErrorFlash: false, + }); + const { mount: messageMount } = messageLogic; + messageMount(); + messageLogic.actions.apiError('error' as any as HttpError); + expect(flashAPIErrors).not.toHaveBeenCalledWith('error'); }); }); describe('apiReset', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/api_logic/create_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/api_logic/create_api_logic.ts index b8f6aac6f8624..f8a3eb7a823d8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/api_logic/create_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/api_logic/create_api_logic.ts @@ -8,6 +8,7 @@ import { kea, MakeLogicType } from 'kea'; import { ApiStatus, Status, HttpError } from '../../../../common/types/api'; +import { clearFlashMessages, flashAPIErrors, flashSuccessToast } from '../flash_messages'; export interface Values { apiStatus: ApiStatus; @@ -23,11 +24,25 @@ export interface Actions { makeRequest(args: Args): Args; } +export interface CreateApiOptions { + clearFlashMessagesOnMakeRequest: boolean; + showErrorFlash: boolean; + showSuccessFlashFn?: (result: Result) => string; +} + +const DEFAULT_CREATE_API_OPTIONS = { + clearFlashMessagesOnMakeRequest: true, + showErrorFlash: true, +}; + export const createApiLogic = ( path: string[], - apiFunction: (args: Args) => Promise -) => - kea, Actions>>({ + apiFunction: (args: Args) => Promise, + incomingOptions: Partial> = {} +) => { + const options = { ...DEFAULT_CREATE_API_OPTIONS, ...incomingOptions }; + + return kea, Actions>>({ actions: { apiError: (error) => error, apiReset: true, @@ -35,7 +50,20 @@ export const createApiLogic = ( makeRequest: (args) => args, }, listeners: ({ actions }) => ({ + apiError: (error) => { + if (options.showErrorFlash) { + flashAPIErrors(error); + } + }, + apiSuccess: (result) => { + if (options.showSuccessFlashFn) { + flashSuccessToast(options.showSuccessFlashFn(result)); + } + }, makeRequest: async (args) => { + if (options.clearFlashMessagesOnMakeRequest) { + clearFlashMessages(); + } try { const result = await apiFunction(args); actions.apiSuccess(result); @@ -75,3 +103,4 @@ export const createApiLogic = ( status: [() => [selectors.apiStatus], (apiStatus: ApiStatus) => apiStatus.status], }), }); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_custom_source/add_custom_source_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_custom_source/add_custom_source_logic.ts index 0f81e78d98868..1aa292c1efc3f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_custom_source/add_custom_source_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_custom_source/add_custom_source_logic.ts @@ -8,7 +8,6 @@ import { kea, MakeLogicType } from 'kea'; import { HttpError, Status } from '../../../../../../../../common/types/api'; -import { clearFlashMessages, flashAPIErrors } from '../../../../../../shared/flash_messages'; import { CustomSource } from '../../../../../types'; import { AddCustomSourceApiLogic } from './add_custom_source_api_logic'; @@ -92,8 +91,6 @@ export const AddCustomSourceLogic = kea< const { baseServiceType } = props; actions.makeRequest({ name: customSourceNameValue, baseServiceType }); }, - makeRequest: () => clearFlashMessages(), - apiError: (error) => flashAPIErrors(error), apiSuccess: ({ source }) => { actions.setNewCustomSource(source); }, diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts index e9f22cae5b94b..14c3532efee91 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts @@ -35,7 +35,6 @@ describe('addConnector lib function', () => { create: jest.fn(), exists: jest.fn(), getMapping: jest.fn(), - refresh: jest.fn(), }, }, asInternalUser: {}, @@ -160,6 +159,7 @@ describe('addConnector lib function', () => { sync_now: false, }, index: CONNECTORS_INDEX, + refresh: true, }); expect(mockClient.asCurrentUser.indices.create).toHaveBeenCalledWith({ index: 'index_name', @@ -343,6 +343,7 @@ describe('addConnector lib function', () => { sync_now: false, }, index: CONNECTORS_INDEX, + refresh: true, }); expect(mockClient.asCurrentUser.indices.create).toHaveBeenCalledWith({ index: 'index_name', @@ -448,6 +449,7 @@ describe('addConnector lib function', () => { sync_now: false, }, index: CONNECTORS_INDEX, + refresh: true, }); expect(mockClient.asCurrentUser.indices.create).toHaveBeenCalledWith({ index: 'search-index_name', diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts index f0ff60a075439..e697cf57522f8 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts @@ -59,9 +59,9 @@ const createConnector = async ( const result = await client.asCurrentUser.index({ document, index: CONNECTORS_INDEX, + refresh: true, }); await createIndex(client, document.index_name, language, false); - await client.asCurrentUser.indices.refresh({ index: CONNECTORS_INDEX }); return { id: result._id, index_name: document.index_name }; }; diff --git a/x-pack/plugins/enterprise_search/server/lib/fetch_search_results.test.ts b/x-pack/plugins/enterprise_search/server/lib/fetch_search_results.test.ts index 2e3b7a202f153..1f7f1eec9cdff 100644 --- a/x-pack/plugins/enterprise_search/server/lib/fetch_search_results.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/fetch_search_results.test.ts @@ -87,7 +87,28 @@ describe('fetchSearchResults lib function', () => { expect(mockClient.asCurrentUser.search).toHaveBeenCalledWith({ from: DEFAULT_FROM_VALUE, index: indexName, - q: JSON.stringify(query), + q: query, + size: ENTERPRISE_SEARCH_DOCUMENTS_DEFAULT_DOC_COUNT, + }); + }); + + it('should escape quotes in queries and return results with hits', async () => { + mockClient.asCurrentUser.search.mockImplementation( + () => regularSearchResultsResponse as SearchResponseBody + ); + + await expect( + fetchSearchResults( + mockClient as unknown as IScopedClusterClient, + indexName, + '"yellow banana"' + ) + ).resolves.toEqual(regularSearchResultsResponse); + + expect(mockClient.asCurrentUser.search).toHaveBeenCalledWith({ + from: DEFAULT_FROM_VALUE, + index: indexName, + q: '\\"yellow banana\\"', size: ENTERPRISE_SEARCH_DOCUMENTS_DEFAULT_DOC_COUNT, }); }); @@ -120,7 +141,7 @@ describe('fetchSearchResults lib function', () => { expect(mockClient.asCurrentUser.search).toHaveBeenCalledWith({ from: DEFAULT_FROM_VALUE, index: indexName, - q: JSON.stringify(query), + q: query, size: ENTERPRISE_SEARCH_DOCUMENTS_DEFAULT_DOC_COUNT, }); }); diff --git a/x-pack/plugins/enterprise_search/server/lib/fetch_search_results.ts b/x-pack/plugins/enterprise_search/server/lib/fetch_search_results.ts index b7c3bf81e0ca5..a1b8da77f887d 100644 --- a/x-pack/plugins/enterprise_search/server/lib/fetch_search_results.ts +++ b/x-pack/plugins/enterprise_search/server/lib/fetch_search_results.ts @@ -21,7 +21,7 @@ export const fetchSearchResults = async ( from, index: indexName, size, - ...(!!query ? { q: JSON.stringify(query) } : {}), + ...(!!query ? { q: query.replace(/"/g, '\\"') } : {}), }); return results; }; diff --git a/x-pack/plugins/enterprise_search/server/plugin.ts b/x-pack/plugins/enterprise_search/server/plugin.ts index 408413398aa29..c3ba5c95476e6 100644 --- a/x-pack/plugins/enterprise_search/server/plugin.ts +++ b/x-pack/plugins/enterprise_search/server/plugin.ts @@ -258,7 +258,7 @@ export class EnterpriseSearchPlugin implements Plugin { indexName: 'logs-elastic_analytics.events-*', type: 'index_name', }, - name: 'Enterprise Search Behaviorial Analytics Logs', + name: 'Enterprise Search Behavioral Analytics Logs', }); /** diff --git a/x-pack/plugins/file_upload/public/importer/geo/geojson_importer/geojson_importer.test.js b/x-pack/plugins/file_upload/public/importer/geo/geojson_importer/geojson_importer.test.js index d05212223ef3d..7b621c4ccbcad 100644 --- a/x-pack/plugins/file_upload/public/importer/geo/geojson_importer/geojson_importer.test.js +++ b/x-pack/plugins/file_upload/public/importer/geo/geojson_importer/geojson_importer.test.js @@ -278,4 +278,74 @@ describe('previewFile', () => { expect(results.features).toEqual([]); expect(results.invalidFeatures.length).toBe(2); }); + + describe('crs', () => { + test('should read features with supported CRS', async () => { + const file = new File( + [ + JSON.stringify({ + ...FEATURE_COLLECTION, + crs: { + type: 'name', + properties: { + name: 'urn:ogc:def:crs:OGC:1.3:CRS84', + }, + }, + }), + ], + 'testfile.json', + { type: 'text/json' } + ); + + const importer = new GeoJsonImporter(file); + const results = await importer.previewFile(); + + expect(results).toEqual({ + previewCoverage: 100, + hasPoints: true, + hasShapes: false, + features: FEATURE_COLLECTION.features, + invalidFeatures: [], + }); + }); + + test('should reject "link" CRS', async () => { + const file = new File( + [ + JSON.stringify({ + ...FEATURE_COLLECTION, + crs: { + type: 'link', + }, + }), + ], + 'testfile.json', + { type: 'text/json' } + ); + + const importer = new GeoJsonImporter(file); + await expect(importer.previewFile()).rejects.toThrow(); + }); + + test('should reject unsupported CRS', async () => { + const file = new File( + [ + JSON.stringify({ + ...FEATURE_COLLECTION, + crs: { + type: 'name', + properties: { + name: 'urn:ogc:def:crs:EPSG::25833', + }, + }, + }), + ], + 'testfile.json', + { type: 'text/json' } + ); + + const importer = new GeoJsonImporter(file); + await expect(importer.previewFile()).rejects.toThrow(); + }); + }); }); diff --git a/x-pack/plugins/file_upload/public/importer/geo/geojson_importer/geojson_importer.ts b/x-pack/plugins/file_upload/public/importer/geo/geojson_importer/geojson_importer.ts index cc2f387e5bff4..e0405d1e998b8 100644 --- a/x-pack/plugins/file_upload/public/importer/geo/geojson_importer/geojson_importer.ts +++ b/x-pack/plugins/file_upload/public/importer/geo/geojson_importer/geojson_importer.ts @@ -13,6 +13,8 @@ import { AbstractGeoFileImporter } from '../abstract_geo_file_importer'; export const GEOJSON_FILE_TYPES = ['.json', '.geojson']; +const SUPPORTED_CRS_LIST = ['EPSG:4326', 'urn:ogc:def:crs:OGC:1.3:CRS84']; + interface LoaderBatch { bytesUsed?: number; batchType?: string; @@ -51,6 +53,28 @@ export class GeoJsonImporter extends AbstractGeoFileImporter { const { value: batch, done } = await this._iterator.next(); + // geojson only supports WGS 84 datum, with longitude and latitude units of decimal degrees. + // https://datatracker.ietf.org/doc/html/rfc7946#section-4 + // Deprecated geojson specification supported crs + // https://geojson.org/geojson-spec.html#named-crs + // This importer only supports WGS 84 datum + if (typeof batch?.container?.crs === 'object') { + const crs = batch.container.crs as { type?: string; properties?: { name?: string } }; + if ( + crs?.type === 'link' || + (crs?.type === 'name' && !SUPPORTED_CRS_LIST.includes(crs?.properties?.name ?? '')) + ) { + throw new Error( + i18n.translate('xpack.fileUpload.geojsonImporter.unsupportedCrs', { + defaultMessage: 'Unsupported coordinate reference system, expecting {supportedCrsList}', + values: { + supportedCrsList: SUPPORTED_CRS_LIST.join(', '), + }, + }) + ); + } + } + if (!this._getIsActive() || done) { results.hasNext = false; return results; diff --git a/x-pack/plugins/fleet/common/authz.test.ts b/x-pack/plugins/fleet/common/authz.test.ts index cadb90651b01c..9602fabdce7c1 100644 --- a/x-pack/plugins/fleet/common/authz.test.ts +++ b/x-pack/plugins/fleet/common/authz.test.ts @@ -15,11 +15,8 @@ import { ENDPOINT_PRIVILEGES } from './constants'; const SECURITY_SOLUTION_ID = DEFAULT_APP_CATEGORIES.security.id; -function generateActions( - privileges: typeof ENDPOINT_PRIVILEGES, - overrides: Record = {} -) { - return privileges.reduce((acc, privilege) => { +function generateActions(privileges: T, overrides: Record = {}) { + return Object.keys(privileges).reduce((acc, privilege) => { const executePackageAction = overrides[privilege] || false; return { diff --git a/x-pack/plugins/fleet/common/authz.ts b/x-pack/plugins/fleet/common/authz.ts index 72812576e13b3..fa30f2b8f7f33 100644 --- a/x-pack/plugins/fleet/common/authz.ts +++ b/x-pack/plugins/fleet/common/authz.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; import type { Capabilities } from '@kbn/core-capabilities-common'; import { ENDPOINT_PRIVILEGES } from './constants'; @@ -95,14 +94,17 @@ export function calculatePackagePrivilegesFromCapabilities( return {}; } - const endpointActions = ENDPOINT_PRIVILEGES.reduce((acc, privilege) => { - return { - ...acc, - [privilege]: { - executePackageAction: capabilities.siem[privilege] || false, - }, - }; - }, {}); + const endpointActions = Object.entries(ENDPOINT_PRIVILEGES).reduce( + (acc, [privilege, { privilegeName }]) => { + return { + ...acc, + [privilege]: { + executePackageAction: capabilities.siem[privilegeName] || false, + }, + }; + }, + {} + ); return { endpoint: { @@ -117,10 +119,11 @@ function getAuthorizationFromPrivileges( privilege: string; authorized: boolean; }>, + prefix: string, searchPrivilege: string ): boolean { const privilege = kibanaPrivileges.find((p) => - p.privilege.endsWith(`${DEFAULT_APP_CATEGORIES.security.id}-${searchPrivilege}`) + p.privilege.endsWith(`${prefix}${searchPrivilege}`) ); return privilege?.authorized || false; } @@ -138,15 +141,22 @@ export function calculatePackagePrivilegesFromKibanaPrivileges( return {}; } - const endpointActions = ENDPOINT_PRIVILEGES.reduce((acc, privilege: string) => { - const kibanaPrivilege = getAuthorizationFromPrivileges(kibanaPrivileges, privilege); - return { - ...acc, - [privilege]: { - executePackageAction: kibanaPrivilege, - }, - }; - }, {}); + const endpointActions = Object.entries(ENDPOINT_PRIVILEGES).reduce( + (acc, [privilege, { appId, privilegeSplit, privilegeName }]) => { + const kibanaPrivilege = getAuthorizationFromPrivileges( + kibanaPrivileges, + `${appId}${privilegeSplit}`, + privilegeName + ); + return { + ...acc, + [privilege]: { + executePackageAction: kibanaPrivilege, + }, + }; + }, + {} + ); return { endpoint: { diff --git a/x-pack/plugins/fleet/common/constants/authz.ts b/x-pack/plugins/fleet/common/constants/authz.ts index d7a0ca4ade2eb..fa2a2c0b44e93 100644 --- a/x-pack/plugins/fleet/common/constants/authz.ts +++ b/x-pack/plugins/fleet/common/constants/authz.ts @@ -5,22 +5,137 @@ * 2.0. */ -export const ENDPOINT_PRIVILEGES = [ - 'writeEndpointList', - 'readEndpointList', - 'writeTrustedApplications', - 'readTrustedApplications', - 'writeHostIsolationExceptions', - 'readHostIsolationExceptions', - 'writeBlocklist', - 'readBlocklist', - 'writeEventFilters', - 'readEventFilters', - 'writePolicyManagement', - 'readPolicyManagement', - 'writeActionsLogManagement', - 'readActionsLogManagement', - 'writeHostIsolation', - 'writeProcessOperations', - 'writeFileOperations', -] as const; +import { deepFreeze } from '@kbn/std'; +import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; + +const SECURITY_SOLUTION_APP_ID = 'siem'; + +interface PrivilegeMapObject { + appId: string; + privilegeSplit: string; + privilegeType: 'ui' | 'api'; + privilegeName: string; +} + +/** + * defines endpoint package privileges + * the key is the name of the packagePrivilege (ie. 'readSecuritySolution') + * the value object is for mapping kibana privileges and capabilities + * see x-pack/plugins/fleet/server/services/security/security.ts for example of how object values are used + */ +export const ENDPOINT_PRIVILEGES: Record = deepFreeze({ + readSecuritySolution: { + appId: SECURITY_SOLUTION_APP_ID, + privilegeSplit: '/', + privilegeType: 'ui', + privilegeName: 'show', + }, + writeSecuritySolution: { + appId: SECURITY_SOLUTION_APP_ID, + privilegeSplit: '/', + privilegeType: 'ui', + privilegeName: 'crud', + }, + writeEndpointList: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'writeEndpointList', + }, + readEndpointList: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'readEndpointList', + }, + writeTrustedApplications: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'writeTrustedApplications', + }, + readTrustedApplications: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'readTrustedApplications', + }, + writeHostIsolationExceptions: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'writeHostIsolationExceptions', + }, + readHostIsolationExceptions: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'readHostIsolationExceptions', + }, + writeBlocklist: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'writeBlocklist', + }, + readBlocklist: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'readBlocklist', + }, + writeEventFilters: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'writeEventFilters', + }, + readEventFilters: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'readEventFilters', + }, + writePolicyManagement: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'writePolicyManagement', + }, + readPolicyManagement: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'readPolicyManagement', + }, + writeActionsLogManagement: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'writeActionsLogManagement', + }, + readActionsLogManagement: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'readActionsLogManagement', + }, + writeHostIsolation: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'writeHostIsolation', + }, + writeProcessOperations: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'writeProcessOperations', + }, + writeFileOperations: { + appId: DEFAULT_APP_CATEGORIES.security.id, + privilegeSplit: '-', + privilegeType: 'api', + privilegeName: 'writeFileOperations', + }, +}); diff --git a/x-pack/plugins/fleet/common/experimental_features.ts b/x-pack/plugins/fleet/common/experimental_features.ts index e7379ba1e2a4b..b64a1192f3930 100644 --- a/x-pack/plugins/fleet/common/experimental_features.ts +++ b/x-pack/plugins/fleet/common/experimental_features.ts @@ -16,6 +16,7 @@ export const allowedExperimentalValues = Object.freeze({ packageVerification: true, showDevtoolsRequest: true, diagnosticFileUploadEnabled: false, + experimentalDataStreamSettings: false, }); type ExperimentalConfigKeys = Array; diff --git a/x-pack/plugins/fleet/common/index.ts b/x-pack/plugins/fleet/common/index.ts index 5b3765bf9e40b..b347b5b29dd81 100644 --- a/x-pack/plugins/fleet/common/index.ts +++ b/x-pack/plugins/fleet/common/index.ts @@ -147,6 +147,7 @@ export type { KibanaAssetReference, KibanaSavedObjectType, EsAssetReference, + AssetsGroupedByServiceByType, KibanaAssetTypeToParts, KibanaAssetParts, KibanaAssetType, diff --git a/x-pack/plugins/fleet/common/mocks.ts b/x-pack/plugins/fleet/common/mocks.ts index d5aca8398abd8..526110e133137 100644 --- a/x-pack/plugins/fleet/common/mocks.ts +++ b/x-pack/plugins/fleet/common/mocks.ts @@ -62,7 +62,7 @@ export const deletePackagePolicyMock = (): DeletePackagePoliciesResponse => { * Creates mock `authz` object */ export const createFleetAuthzMock = (): FleetAuthz => { - const endpointActions = ENDPOINT_PRIVILEGES.reduce((acc, privilege) => { + const endpointActions = Object.keys(ENDPOINT_PRIVILEGES).reduce((acc, privilege) => { return { ...acc, [privilege]: { diff --git a/x-pack/plugins/fleet/cypress/e2e/a11y/home_page.cy.ts b/x-pack/plugins/fleet/cypress/e2e/a11y/home_page.cy.ts index 9b3803679a0de..18369a048b464 100644 --- a/x-pack/plugins/fleet/cypress/e2e/a11y/home_page.cy.ts +++ b/x-pack/plugins/fleet/cypress/e2e/a11y/home_page.cy.ts @@ -33,15 +33,15 @@ import { setFleetServerHost } from '../../tasks/fleet_server'; describe('Home page', () => { before(() => { setFleetServerHost('https://fleetserver:8220'); - navigateTo(FLEET); - cy.getBySel(LANDING_PAGE_ADD_FLEET_SERVER_BUTTON).click(); }); describe('Agents', () => { - before(() => { + beforeEach(() => { + navigateTo(FLEET); + cy.getBySel(LANDING_PAGE_ADD_FLEET_SERVER_BUTTON).click(); cy.getBySel(AGENT_FLYOUT.QUICK_START_TAB_BUTTON, { timeout: 15000 }).should('be.visible'); - setFleetServerHost('https://fleetserver:8220'); }); + const fleetServerHost = 'https://localhost:8220'; describe('Quick Start', () => { @@ -63,7 +63,10 @@ describe('Home page', () => { }); describe('Advanced', () => { - before(() => { + beforeEach(() => { + navigateTo(FLEET); + cy.getBySel(LANDING_PAGE_ADD_FLEET_SERVER_BUTTON).click(); + cy.getBySel(AGENT_FLYOUT.QUICK_START_TAB_BUTTON, { timeout: 15000 }).should('be.visible'); cy.getBySel(AGENT_FLYOUT.ADVANCED_TAB_BUTTON).click(); }); it('Select policy for fleet', () => { @@ -88,7 +91,7 @@ describe('Home page', () => { }); describe('Agent Policies', () => { - before(() => { + beforeEach(() => { navigateTo(FLEET); cy.getBySel(AGENT_POLICIES_TAB).click(); cy.getBySel(AGENT_POLICIES_CREATE_AGENT_POLICY_FLYOUT.CREATE_BUTTON, { @@ -111,6 +114,11 @@ describe('Home page', () => { checkA11y({ skipFailures: false }); }); it('Agent Table After Adding Another Agent', () => { + cy.getBySel(AGENT_POLICIES_CREATE_AGENT_POLICY_FLYOUT.CREATE_BUTTON).click(); + cy.getBySel(AGENT_POLICIES_CREATE_AGENT_POLICY_FLYOUT.TITLE, { timeout: 15000 }).should( + 'be.visible' + ); + cy.getBySel(AGENT_POLICY_CREATE_AGENT_POLICY_NAME_FIELD).type('testName'); cy.getBySel(AGENT_POLICY_FLYOUT_CREATE_BUTTON).click(); cy.getBySel(AGENT_POLICY_NAME_LINK, { timeout: 15000 }).should('be.visible'); checkA11y({ skipFailures: true }); @@ -118,7 +126,7 @@ describe('Home page', () => { }); describe('Enrollment Tokens', () => { - before(() => { + beforeEach(() => { navigateTo(FLEET); cy.getBySel(ENROLLMENT_TOKENS_TAB).click(); }); @@ -137,7 +145,7 @@ describe('Home page', () => { describe('Data Streams', () => { before(() => { - cy.getBySel('confirmModalCancelButton').click(); + navigateTo(FLEET); cy.getBySel(DATA_STREAMS_TAB, { timeout: 15000 }).should('be.visible'); cy.getBySel(DATA_STREAMS_TAB).click(); }); diff --git a/x-pack/plugins/fleet/cypress/e2e/enrollment_token.cy.ts b/x-pack/plugins/fleet/cypress/e2e/enrollment_token.cy.ts index 88c94815eee0d..862e49e6c2119 100644 --- a/x-pack/plugins/fleet/cypress/e2e/enrollment_token.cy.ts +++ b/x-pack/plugins/fleet/cypress/e2e/enrollment_token.cy.ts @@ -49,6 +49,12 @@ describe('Enrollment token page', () => { cy.get('.euiPanel').contains('Are you sure you want to revoke'); cy.get('.euiButton').contains('Revoke enrollment token').click({ force: true }); - cy.getBySel(ENROLLMENT_TOKENS.TABLE_REVOKE_BTN).first().should('not.exist'); + cy.getBySel(ENROLLMENT_TOKENS.LIST_TABLE).within(() => { + cy.get('.euiTableRow') + .first() + .within(() => { + cy.getBySel(ENROLLMENT_TOKENS.TABLE_REVOKE_BTN).should('not.exist'); + }); + }); }); }); diff --git a/x-pack/plugins/fleet/dev_docs/data_model.md b/x-pack/plugins/fleet/dev_docs/data_model.md index a36cda76fffb6..1e74afe3115b9 100644 --- a/x-pack/plugins/fleet/dev_docs/data_model.md +++ b/x-pack/plugins/fleet/dev_docs/data_model.md @@ -29,6 +29,8 @@ In prior alpha versions of Fleet, this data was also stored in Saved Objects bec communicating directly with Kibana for policy updates. Once Fleet Server was introduced, that data was migrated to these Elasticsearch indices to be readable by Fleet Server. +_Note: All of these system indices are plain indices, and not data streams._ + ### `.fleet-agents` index Each document in this index tracks an individual Elastic Agent's enrollment in the Fleet, which policy it is current @@ -38,6 +40,8 @@ All of the code that interacts with this index is currently located in [`x-pack/plugins/fleet/server/services/agents/crud.ts`](../server/services/agents/crud.ts) and the schema of these documents is maintained by the `FleetServerAgent` TypeScript interface. +- Cleanup model: N/A + ### `.fleet-actions` index Each document in this index represents an action that was initiated by a user and needs to be processed by Fleet Server @@ -47,18 +51,35 @@ list. The total schema for actions is represented by the `FleetServerAgentAction` type. +- Cleanup model: Fleet Server considers actions expired after 30 days, and will remove them via an hourly process +- [Source](https://github.com/elastic/fleet-server/blob/9af3b2176b42a0de34c5583b5430558c03792dd0/internal/pkg/gc/schedules.go#L29-L33) + ### `.fleet-actions-results` +- Cleanup model: N/A + ### `.fleet-servers` +- Cleanup model: N/A + ### `.fleet-artifacts` -### `.fleet-entrollment-api-keys` +- Cleanup model: N/A + +### `.fleet-enrollment-api-keys` + +- Cleanup model: Deleteable via Fleet UI/API, deleted when an agent policy is deleted +- [Source](https://github.com/elastic/kibana/blob/7a35748cb43f2c73623ffda6fa02b91c3cb4c689/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts#L102) ### `.fleet-policies` +- Cleanup model: Deleted when a corresponding agent policy is deleted in the Fleet UI or API +- [Source](https://github.com/elastic/kibana/blob/976b1b2331371f4a1325f6947d38d1f4de7a7254/x-pack/plugins/fleet/server/services/agent_policy.ts#L699-L701) + ### `.fleet-policies-leader` +- Cleanup model: N/A + ## Saved Object types The Fleet plugin leverages several Saved Object types to track metadata on install packages, agent policies, and more. diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx index 4bfdff96a9d50..2191b151414ba 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx @@ -21,7 +21,7 @@ import { } from '@elastic/eui'; import { useRouteMatch } from 'react-router-dom'; -import { useGetDataStreams } from '../../../../../../../../hooks'; +import { useConfig, useGetDataStreams } from '../../../../../../../../hooks'; import { mapPackageReleaseToIntegrationCardRelease } from '../../../../../../../../services/package_prerelease'; import type { ExperimentalDataStreamFeature } from '../../../../../../../../../common/types/models/epm'; @@ -71,6 +71,10 @@ export const PackagePolicyInputStreamConfig = memo( inputStreamValidationResults, forceShowErrors, }) => { + const config = useConfig(); + const isExperimentalDataStreamSettingsEnabled = + config.enableExperimental?.includes('experimentalDataStreamSettings') ?? false; + const { params: { packagePolicyId }, } = useRouteMatch<{ packagePolicyId?: string }>(); @@ -305,13 +309,15 @@ export const PackagePolicyInputStreamConfig = memo( )} {/* Experimental index/datastream settings e.g. synthetic source */} - + {isExperimentalDataStreamSettingsEnabled && ( + + )} ) : null} diff --git a/x-pack/plugins/fleet/server/routes/agent/handlers.ts b/x-pack/plugins/fleet/server/routes/agent/handlers.ts index 2177fcdc252f6..71e21378e6f5f 100644 --- a/x-pack/plugins/fleet/server/routes/agent/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/agent/handlers.ts @@ -205,9 +205,10 @@ export const getAgentTagsHandler: RequestHandler< > = async (context, request, response) => { const coreContext = await context.core; const esClient = coreContext.elasticsearch.client.asInternalUser; + const soClient = coreContext.savedObjects.client; try { - const tags = await AgentService.getAgentTags(esClient, { + const tags = await AgentService.getAgentTags(soClient, esClient, { showInactive: request.query.showInactive, kuery: request.query.kuery, }); diff --git a/x-pack/plugins/fleet/server/routes/epm/handlers.ts b/x-pack/plugins/fleet/server/routes/epm/handlers.ts index b4b189d3ad2bb..702b70bee117b 100644 --- a/x-pack/plugins/fleet/server/routes/epm/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/epm/handlers.ts @@ -53,7 +53,7 @@ import { } from '../../services/epm/packages'; import type { BulkInstallResponse } from '../../services/epm/packages'; import { defaultFleetErrorHandler, fleetErrorToResponseOptions, FleetError } from '../../errors'; -import { licenseService } from '../../services'; +import { checkAllowedPackages, licenseService } from '../../services'; import { getArchiveEntry } from '../../services/epm/archive/cache'; import { getAsset } from '../../services/epm/archive/storage'; import { getPackageUsageStats } from '../../services/epm/packages/get'; @@ -91,6 +91,7 @@ export const getListHandler: FleetRequestHandler< savedObjectsClient, ...request.query, }); + const body: GetPackagesResponse = { items: res, response: res, @@ -209,7 +210,11 @@ export const getInfoHandler: FleetRequestHandler< > = async (context, request, response) => { try { const savedObjectsClient = (await context.fleet).internalSoClient; + const { limitedToPackages } = await context.fleet; const { pkgName, pkgVersion } = request.params; + + checkAllowedPackages([pkgName], limitedToPackages); + const { ignoreUnverified = false, full = false, prerelease } = request.query; if (pkgVersion && !semverValid(pkgVersion)) { throw new FleetError('Package version is not a valid semver'); diff --git a/x-pack/plugins/fleet/server/routes/epm/index.ts b/x-pack/plugins/fleet/server/routes/epm/index.ts index 383f9c3116d8d..fecf49471c97d 100644 --- a/x-pack/plugins/fleet/server/routes/epm/index.ts +++ b/x-pack/plugins/fleet/server/routes/epm/index.ts @@ -7,7 +7,13 @@ import type { IKibanaResponse } from '@kbn/core/server'; -import type { FleetAuthzRouter } from '../../services/security'; +import type { FleetAuthz } from '../../../common'; + +import { + calculateRouteAuthz, + type FleetAuthzRouter, + getRouteRequiredAuthz, +} from '../../services/security'; import type { DeletePackageResponse, @@ -111,9 +117,9 @@ export const registerRoutes = (router: FleetAuthzRouter) => { { path: EPM_API_ROUTES.INFO_PATTERN, validate: GetInfoRequestSchema, - fleetAuthz: { - integrations: { readPackageInfo: true }, - }, + fleetAuthz: (fleetAuthz: FleetAuthz): boolean => + calculateRouteAuthz(fleetAuthz, getRouteRequiredAuthz('get', EPM_API_ROUTES.INFO_PATTERN)) + .granted, }, getInfoHandler ); @@ -186,9 +192,11 @@ export const registerRoutes = (router: FleetAuthzRouter) => { { path: EPM_API_ROUTES.INFO_PATTERN_DEPRECATED, validate: GetInfoRequestSchemaDeprecated, - fleetAuthz: { - integrations: { readPackageInfo: true }, - }, + fleetAuthz: (fleetAuthz: FleetAuthz): boolean => + calculateRouteAuthz( + fleetAuthz, + getRouteRequiredAuthz('get', EPM_API_ROUTES.INFO_PATTERN_DEPRECATED) + ).granted, }, async (context, request, response) => { const newRequest = { ...request, params: splitPkgKey(request.params.pkgkey) } as any; diff --git a/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts b/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts index 045f32cbf6c6e..ca29e7c0d079b 100644 --- a/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts @@ -15,7 +15,12 @@ import { groupBy, keyBy } from 'lodash'; import { populatePackagePolicyAssignedAgentsCount } from '../../services/package_policies/populate_package_policy_assigned_agents_count'; -import { agentPolicyService, appContextService, packagePolicyService } from '../../services'; +import { + agentPolicyService, + appContextService, + checkAllowedPackages, + packagePolicyService, +} from '../../services'; import type { GetPackagePoliciesRequestSchema, GetOnePackagePolicyRequestSchema, @@ -45,44 +50,6 @@ import { simplifiedPackagePolicytoNewPackagePolicy } from '../../../common/servi import type { SimplifiedPackagePolicy } from '../../../common/services/simplified_package_policy_helper'; -const getAllowedPackageNamesMessage = (allowedPackageNames: string[]): string => { - return `Allowed package.name's: ${allowedPackageNames.join(', ')}`; -}; - -/** - * Validates that Package Policy data only includes `package.name`'s that are in the list of - * `allowedPackageNames`. If an error is encountered, then a message is return, otherwise, undefined. - * - * @param data - * @param allowedPackageNames - */ -const validatePackagePolicyDataIsScopedToAllowedPackageNames = ( - data: PackagePolicy[], - allowedPackageNames: string[] | undefined -): string | undefined => { - if (!data.length || typeof allowedPackageNames === 'undefined') { - return; - } - - if (!allowedPackageNames.length) { - return 'Authorization denied due to lack of integration package privileges'; - } - - // Because List type of APIs have an un-bounded `perPage` query param, we only validate the - // data up to the first package.name that we find is not authorized. - for (const packagePolicy of data) { - if (!packagePolicy.package) { - return `Authorization denied. ${getAllowedPackageNamesMessage(allowedPackageNames)}`; - } - - if (!allowedPackageNames.includes(packagePolicy.package.name)) { - return `Authorization denied to [package.name=${ - packagePolicy.package.name - }]. ${getAllowedPackageNamesMessage(allowedPackageNames)}`; - } - } -}; - export const getPackagePoliciesHandler: FleetRequestHandler< undefined, TypeOf @@ -98,18 +65,7 @@ export const getPackagePoliciesHandler: FleetRequestHandler< request.query ); - // specific to package-level RBAC - const validationResult = validatePackagePolicyDataIsScopedToAllowedPackageNames( - items, - limitedToPackages - ); - if (validationResult) { - return response.forbidden({ - body: { - message: validationResult, - }, - }); - } + checkAllowedPackages(items, limitedToPackages, 'package.name'); if (request.query.withAgentCount) { await populatePackagePolicyAssignedAgentsCount(esClient, items); @@ -146,17 +102,7 @@ export const bulkGetPackagePoliciesHandler: FleetRequestHandler< const body: BulkGetPackagePoliciesResponse = { items: items ?? [] }; - const validationResult = validatePackagePolicyDataIsScopedToAllowedPackageNames( - body.items, - limitedToPackages - ); - if (validationResult) { - return response.forbidden({ - body: { - message: validationResult, - }, - }); - } + checkAllowedPackages(body.items, limitedToPackages, 'package.name'); return response.ok({ body, @@ -186,17 +132,7 @@ export const getOnePackagePolicyHandler: FleetRequestHandler< const packagePolicy = await packagePolicyService.get(soClient, packagePolicyId); if (packagePolicy) { - const validationResult = validatePackagePolicyDataIsScopedToAllowedPackageNames( - [packagePolicy], - limitedToPackages - ); - if (validationResult) { - return response.forbidden({ - body: { - message: validationResult, - }, - }); - } + checkAllowedPackages([packagePolicy], limitedToPackages, 'package.name'); return response.ok({ body: { diff --git a/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.test.ts b/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.test.ts index ab1f9617a8917..249b74db13256 100644 --- a/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.test.ts @@ -24,7 +24,11 @@ describe('buildStatusRuntimeField', () => { "source": " long lastCheckinMillis = doc['last_checkin'].size() > 0 ? doc['last_checkin'].value.toInstant().toEpochMilli() - : -1; + : ( + doc['enrolled_at'].size() > 0 + ? doc['enrolled_at'].value.toInstant().toEpochMilli() + : -1 + ); if (doc['active'].size() > 0 && doc['active'].value == false) { emit('unenrolled'); } else if (lastCheckinMillis > 0 && doc['policy_id'].size() > 0 && false) { @@ -76,7 +80,11 @@ describe('buildStatusRuntimeField', () => { "source": " long lastCheckinMillis = doc['my.prefix.last_checkin'].size() > 0 ? doc['my.prefix.last_checkin'].value.toInstant().toEpochMilli() - : -1; + : ( + doc['my.prefix.enrolled_at'].size() > 0 + ? doc['my.prefix.enrolled_at'].value.toInstant().toEpochMilli() + : -1 + ); if (doc['my.prefix.active'].size() > 0 && doc['my.prefix.active'].value == false) { emit('unenrolled'); } else if (lastCheckinMillis > 0 && doc['my.prefix.policy_id'].size() > 0 && false) { @@ -133,7 +141,11 @@ describe('buildStatusRuntimeField', () => { "source": " long lastCheckinMillis = doc['last_checkin'].size() > 0 ? doc['last_checkin'].value.toInstant().toEpochMilli() - : -1; + : ( + doc['enrolled_at'].size() > 0 + ? doc['enrolled_at'].value.toInstant().toEpochMilli() + : -1 + ); if (doc['active'].size() > 0 && doc['active'].value == false) { emit('unenrolled'); } else if (lastCheckinMillis > 0 && doc['policy_id'].size() > 0 && (doc['policy_id'].value == 'policy-1') && lastCheckinMillis < 1234567590123L) { @@ -190,7 +202,11 @@ describe('buildStatusRuntimeField', () => { "source": " long lastCheckinMillis = doc['last_checkin'].size() > 0 ? doc['last_checkin'].value.toInstant().toEpochMilli() - : -1; + : ( + doc['enrolled_at'].size() > 0 + ? doc['enrolled_at'].value.toInstant().toEpochMilli() + : -1 + ); if (doc['active'].size() > 0 && doc['active'].value == false) { emit('unenrolled'); } else if (lastCheckinMillis > 0 && doc['policy_id'].size() > 0 && (doc['policy_id'].value == 'policy-1' || doc['policy_id'].value == 'policy-2') && lastCheckinMillis < 1234567590123L) { @@ -251,7 +267,11 @@ describe('buildStatusRuntimeField', () => { "source": " long lastCheckinMillis = doc['last_checkin'].size() > 0 ? doc['last_checkin'].value.toInstant().toEpochMilli() - : -1; + : ( + doc['enrolled_at'].size() > 0 + ? doc['enrolled_at'].value.toInstant().toEpochMilli() + : -1 + ); if (doc['active'].size() > 0 && doc['active'].value == false) { emit('unenrolled'); } else if (lastCheckinMillis > 0 && doc['policy_id'].size() > 0 && (doc['policy_id'].value == 'policy-1' || doc['policy_id'].value == 'policy-2') && lastCheckinMillis < 1234567590123L || (doc['policy_id'].value == 'policy-3') && lastCheckinMillis < 1234567490123L) { diff --git a/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.ts b/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.ts index 3250c632d0200..cebf3a440e511 100644 --- a/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.ts +++ b/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.ts @@ -45,7 +45,11 @@ function _buildSource(inactivityTimeouts: InactivityTimeouts, pathPrefix?: strin return ` long lastCheckinMillis = ${field('last_checkin')}.size() > 0 ? ${field('last_checkin')}.value.toInstant().toEpochMilli() - : -1; + : ( + ${field('enrolled_at')}.size() > 0 + ? ${field('enrolled_at')}.value.toInstant().toEpochMilli() + : -1 + ); if (${field('active')}.size() > 0 && ${field('active')}.value == false) { emit('unenrolled'); } else if (${_buildInactiveClause(now, inactivityTimeouts, field)}) { diff --git a/x-pack/plugins/fleet/server/services/agents/crud.test.ts b/x-pack/plugins/fleet/server/services/agents/crud.test.ts index 2a0b341201202..623ca8d0039bc 100644 --- a/x-pack/plugins/fleet/server/services/agents/crud.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/crud.test.ts @@ -54,17 +54,23 @@ describe('Agents CRUD test', () => { }, }); - const result = await getAgentTags(esClientMock, { showInactive: false }); + const result = await getAgentTags(soClientMock, esClientMock, { showInactive: false }); expect(result).toEqual(['tag1', 'tag2']); - expect(searchMock).toHaveBeenCalledWith({ - aggs: { tags: { terms: { field: 'tags', size: 10000 } } }, - body: { - query: expect.any(Object), - }, - index: '.fleet-agents', - size: 0, - }); + expect(searchMock).toHaveBeenCalledWith( + expect.objectContaining({ + aggs: { tags: { terms: { field: 'tags', size: 10000 } } }, + body: { + query: expect.any(Object), + }, + index: '.fleet-agents', + size: 0, + fields: ['status'], + runtime_mappings: { + status: expect.anything(), + }, + }) + ); }); it('should return empty list if no agent tags', async () => { @@ -74,7 +80,7 @@ describe('Agents CRUD test', () => { }, }); - const result = await getAgentTags(esClientMock, { showInactive: false }); + const result = await getAgentTags(soClientMock, esClientMock, { showInactive: false }); expect(result).toEqual([]); }); @@ -82,7 +88,7 @@ describe('Agents CRUD test', () => { it('should return empty list if no agent index', async () => { searchMock.mockRejectedValueOnce(new errors.ResponseError({ statusCode: 404 } as any)); - const result = await getAgentTags(esClientMock, { showInactive: false }); + const result = await getAgentTags(soClientMock, esClientMock, { showInactive: false }); expect(result).toEqual([]); }); @@ -94,30 +100,36 @@ describe('Agents CRUD test', () => { }, }); - await getAgentTags(esClientMock, { + await getAgentTags(soClientMock, esClientMock, { showInactive: true, kuery: 'fleet-agents.policy_id: 123', }); - expect(searchMock).toHaveBeenCalledWith({ - aggs: { tags: { terms: { field: 'tags', size: 10000 } } }, - body: { - query: { - bool: { - minimum_should_match: 1, - should: [ - { - match: { - policy_id: '123', + expect(searchMock).toHaveBeenCalledWith( + expect.objectContaining({ + aggs: { tags: { terms: { field: 'tags', size: 10000 } } }, + body: { + query: { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + policy_id: '123', + }, }, - }, - ], + ], + }, }, }, - }, - index: '.fleet-agents', - size: 0, - }); + index: '.fleet-agents', + size: 0, + fields: ['status'], + runtime_mappings: { + status: expect.anything(), + }, + }) + ); }); }); diff --git a/x-pack/plugins/fleet/server/services/agents/crud.ts b/x-pack/plugins/fleet/server/services/agents/crud.ts index 3e5c45c10b0f6..412603df68c81 100644 --- a/x-pack/plugins/fleet/server/services/agents/crud.ts +++ b/x-pack/plugins/fleet/server/services/agents/crud.ts @@ -119,6 +119,7 @@ export async function closePointInTime(esClient: ElasticsearchClient, pitId: str } export async function getAgentTags( + soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, options: ListWithKuery & { showInactive: boolean; @@ -137,11 +138,14 @@ export async function getAgentTags( const kueryNode = _joinFilters(filters); const body = kueryNode ? { query: toElasticsearchQuery(kueryNode) } : {}; + const runtimeFields = await buildAgentStatusRuntimeField(soClient); try { const result = await esClient.search<{}, { tags: { buckets: Array<{ key: string }> } }>({ index: AGENTS_INDEX, size: 0, body, + fields: Object.keys(runtimeFields), + runtime_mappings: runtimeFields, aggs: { tags: { terms: { field: 'tags', size: SO_SEARCH_LIMIT }, diff --git a/x-pack/plugins/fleet/server/services/agents/update_agent_tags_action_runner.ts b/x-pack/plugins/fleet/server/services/agents/update_agent_tags_action_runner.ts index b0876a4c27d81..8abab53e66272 100644 --- a/x-pack/plugins/fleet/server/services/agents/update_agent_tags_action_runner.ts +++ b/x-pack/plugins/fleet/server/services/agents/update_agent_tags_action_runner.ts @@ -111,7 +111,12 @@ export async function updateTagsBatch( } else if (options.tagsToRemove.length === 1 && options.tagsToAdd.length === 0) { extraFilters.push(`tags:${options.tagsToRemove[0]}`); } - query = getElasticsearchQuery(options.kuery, false, false, hostedIds, extraFilters); + const DEFAULT_STATUS_FILTER = + 'status:online or (status:error or status:degraded) or (status:updating or status:unenrolling or status:enrolling) or status:offline'; + // removing default staus filters, as it is a runtime field and doesn't work with updateByQuery + // this is a quick fix for bulk update tags with default filters + const kuery = options.kuery === DEFAULT_STATUS_FILTER ? '' : options.kuery; + query = getElasticsearchQuery(kuery, false, false, hostedIds, extraFilters); } else { query = { terms: { diff --git a/x-pack/plugins/fleet/server/services/artifacts/artifacts.test.ts b/x-pack/plugins/fleet/server/services/artifacts/artifacts.test.ts index 2c9d93ee47f32..30a59f51e3232 100644 --- a/x-pack/plugins/fleet/server/services/artifacts/artifacts.test.ts +++ b/x-pack/plugins/fleet/server/services/artifacts/artifacts.test.ts @@ -23,6 +23,7 @@ import { setEsClientMethodResponseToError, } from './mocks'; import { + bulkCreateArtifacts, createArtifact, deleteArtifact, encodeArtifactContent, @@ -114,6 +115,68 @@ describe('When using the artifacts services', () => { }); }); + describe('and calling `bulkCreateArtifacts()`', () => { + let newArtifact: NewArtifact; + + beforeEach(() => { + const { id, created, ...artifact } = generateArtifactMock(); + newArtifact = artifact; + }); + + it('should create and return artifacts', async () => { + const { artifacts } = await bulkCreateArtifacts(esClientMock, [newArtifact]); + const artifact = artifacts![0]; + + expect(esClientMock.bulk).toHaveBeenCalledWith({ + index: FLEET_SERVER_ARTIFACTS_INDEX, + refresh: false, + body: [ + { + create: { + _id: `${artifact.packageName}:${artifact.identifier}-${artifact.decodedSha256}`, + }, + }, + { + ...newArtifactToElasticsearchProperties(newArtifact), + created: expect.any(String), + }, + ], + }); + + expect(artifact).toEqual({ + ...newArtifact, + id: expect.any(String), + created: expect.any(String), + }); + }); + + it('should ignore 409 errors from elasticsearch', async () => { + esClientMock.bulk.mockResolvedValue({ + errors: true, + items: [{ create: { status: 409 } as any }], + } as any); + const { artifacts, errors: responseErrors } = await bulkCreateArtifacts(esClientMock, [ + newArtifact, + ]); + + expect(responseErrors).toBeUndefined(); + expect(artifacts?.length).toEqual(1); + }); + + it('should return error if one is encountered', async () => { + esClientMock.bulk.mockResolvedValue({ + errors: true, + items: [{ create: { status: 400, error: { reason: 'error' } } as any }], + } as any); + const { artifacts, errors: responseErrors } = await bulkCreateArtifacts(esClientMock, [ + newArtifact, + ]); + + expect(responseErrors).toEqual([new Error('error')]); + expect(artifacts).toBeUndefined(); + }); + }); + describe('and calling `deleteArtifact()`', () => { it('should delete the artifact', async () => { deleteArtifact(esClientMock, '123'); diff --git a/x-pack/plugins/fleet/server/services/artifacts/artifacts.ts b/x-pack/plugins/fleet/server/services/artifacts/artifacts.ts index edaec33191937..63eace294dd77 100644 --- a/x-pack/plugins/fleet/server/services/artifacts/artifacts.ts +++ b/x-pack/plugins/fleet/server/services/artifacts/artifacts.ts @@ -20,6 +20,8 @@ import { ArtifactsElasticsearchError } from '../../errors'; import { isElasticsearchVersionConflictError } from '../../errors/utils'; +import { withPackageSpan } from '../epm/packages/utils'; + import { isElasticsearchItemNotFoundError } from './utils'; import type { Artifact, @@ -82,6 +84,58 @@ export const createArtifact = async ( return esSearchHitToArtifact({ _id: id, _source: newArtifactData }); }; +export const bulkCreateArtifacts = async ( + esClient: ElasticsearchClient, + artifacts: NewArtifact[], + refresh = false +): Promise<{ artifacts?: Artifact[]; errors?: Error[] }> => { + const { ids, newArtifactsData } = artifacts.reduce<{ + ids: string[]; + newArtifactsData: ArtifactElasticsearchProperties[]; + }>( + (acc, artifact) => { + acc.ids.push(uniqueIdFromArtifact(artifact)); + acc.newArtifactsData.push(newArtifactToElasticsearchProperties(artifact)); + return acc; + }, + { ids: [], newArtifactsData: [] } + ); + + const body = ids.flatMap((id, index) => [ + { + create: { + _id: id, + }, + }, + newArtifactsData[index], + ]); + + const res = await withPackageSpan('Bulk create fleet artifacts', () => + esClient.bulk({ + index: FLEET_SERVER_ARTIFACTS_INDEX, + body, + refresh, + }) + ); + if (res.errors) { + const nonConflictErrors = res.items.reduce((acc, item) => { + if (item.create?.status !== 409) { + acc.push(new Error(item.create?.error?.reason)); + } + return acc; + }, []); + if (nonConflictErrors.length > 0) { + return { errors: nonConflictErrors }; + } + } + + return { + artifacts: ids.map((id, index) => + esSearchHitToArtifact({ _id: id, _source: newArtifactsData[index] }) + ), + }; +}; + export const deleteArtifact = async (esClient: ElasticsearchClient, id: string): Promise => { try { await esClient.delete({ diff --git a/x-pack/plugins/fleet/server/services/artifacts/client.test.ts b/x-pack/plugins/fleet/server/services/artifacts/client.test.ts index f2acdc59e10de..f5c882eee9fbe 100644 --- a/x-pack/plugins/fleet/server/services/artifacts/client.test.ts +++ b/x-pack/plugins/fleet/server/services/artifacts/client.test.ts @@ -80,6 +80,56 @@ describe('When using the Fleet Artifacts Client', () => { }); }); + describe('and calling `bulkCreateArtifacts()`', () => { + it('should create a new artifact', async () => { + expect( + await artifactClient.bulkCreateArtifacts([ + { + content: '{ "key": "value" }', + identifier: 'some-identifier', + type: 'type A', + }, + { + content: '{ "key": "value2" }', + identifier: 'some-identifier2', + type: 'type B', + }, + ]) + ).toEqual({ + artifacts: [ + { + ...generateArtifactMock(), + body: 'eJyrVlDKTq1UslJQKkvMKU1VUqgFADNPBYE=', + created: expect.any(String), + decodedSha256: '05d13b11501327cc43f9a29165f1b4cab5c65783d86227536fcf798e6fa45586', + decodedSize: 18, + encodedSha256: '373d059bac3b51b05af96128cdaf013abd0c59d3d50579589937068059690a68', + encodedSize: 26, + id: expect.any(String), + identifier: 'some-identifier', + relative_url: + '/api/fleet/artifacts/some-identifier/05d13b11501327cc43f9a29165f1b4cab5c65783d86227536fcf798e6fa45586', + type: 'type A', + }, + { + ...generateArtifactMock(), + body: 'eJyrVlDKTq1UslJQKkvMKU01UlKoBQA42QWz', + created: expect.any(String), + decodedSha256: '98fdb0001b0ddb7acb15136579aab7074cf2b6df9db009568e04294bd97e7dd3', + decodedSize: 19, + encodedSha256: '220b82f2f2013cd5137966d0f9c81ace9156319e8f420bbad0f05fc0f61eec5d', + encodedSize: 27, + id: expect.any(String), + identifier: 'some-identifier2', + relative_url: + '/api/fleet/artifacts/some-identifier2/98fdb0001b0ddb7acb15136579aab7074cf2b6df9db009568e04294bd97e7dd3', + type: 'type B', + }, + ], + }); + }); + }); + describe('and calling `deleteArtifact()`', () => { it('should delete the artifact', async () => { setEsClientGetMock(); diff --git a/x-pack/plugins/fleet/server/services/artifacts/client.ts b/x-pack/plugins/fleet/server/services/artifacts/client.ts index 081038447c8f9..3cf28e4847d0d 100644 --- a/x-pack/plugins/fleet/server/services/artifacts/client.ts +++ b/x-pack/plugins/fleet/server/services/artifacts/client.ts @@ -27,6 +27,7 @@ import { generateArtifactContentHash, getArtifact, listArtifacts, + bulkCreateArtifacts, } from './artifacts'; /** @@ -76,6 +77,32 @@ export class FleetArtifactsClient implements ArtifactsClientInterface { return createArtifact(this.esClient, newArtifactData); } + async bulkCreateArtifacts( + optionsList: ArtifactsClientCreateOptions[] + ): Promise<{ artifacts?: Artifact[]; errors?: Error[] }> { + const newArtifactsData = []; + + for (const options of optionsList) { + const { content, type = '', identifier = this.packageName } = options; + + const encodedMetaData = await this.encodeContent(content); + const newArtifactData: NewArtifact = { + type, + identifier, + packageName: this.packageName, + encryptionAlgorithm: 'none', + relative_url: relativeDownloadUrlFromArtifact({ + identifier, + decodedSha256: encodedMetaData.decodedSha256, + }), + ...encodedMetaData, + }; + newArtifactsData.push(newArtifactData); + } + + return bulkCreateArtifacts(this.esClient, newArtifactsData); + } + async deleteArtifact(id: string) { // get the artifact first, which will also ensure its validated const artifact = await this.getArtifact(id); diff --git a/x-pack/plugins/fleet/server/services/artifacts/mocks.ts b/x-pack/plugins/fleet/server/services/artifacts/mocks.ts index f20c72ab0f78b..1ded8743297f9 100644 --- a/x-pack/plugins/fleet/server/services/artifacts/mocks.ts +++ b/x-pack/plugins/fleet/server/services/artifacts/mocks.ts @@ -24,6 +24,7 @@ export const createArtifactsClientMock = (): jest.Mocked; + bulkCreateArtifacts( + optionsList: ArtifactsClientCreateOptions[] + ): Promise<{ artifacts?: Artifact[]; errors?: Error[] }>; + deleteArtifact(id: string): Promise; listArtifacts(options?: ListArtifactsProps): Promise>; diff --git a/x-pack/plugins/fleet/server/services/check_allowed_packages.test.ts b/x-pack/plugins/fleet/server/services/check_allowed_packages.test.ts new file mode 100644 index 0000000000000..d475a4af61854 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/check_allowed_packages.test.ts @@ -0,0 +1,56 @@ +/* + * 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 { FleetUnauthorizedError } from '../errors'; + +import { checkAllowedPackages } from './check_allowed_packages'; + +describe('#checkAllowedPackages', () => { + it('does not throw if no packages', () => { + expect(() => checkAllowedPackages([], [])).not.toThrowError(FleetUnauthorizedError); + }); + + it('does not throw if allowedPackages is undefined', () => { + expect(() => checkAllowedPackages([])).not.toThrowError(FleetUnauthorizedError); + }); + + it('throws if allowedPackages is empty array', () => { + expect(() => checkAllowedPackages([{ name: 'packageA' }], [], 'name')).toThrowError( + new FleetUnauthorizedError( + 'Authorization denied due to lack of integration package privileges' + ) + ); + }); + + it('does not throw if all packages allowed', () => { + const packages = ['packageA', 'packageB', 'packageC']; + const allowedPackages = ['packageA', 'packageB', 'packageC']; + expect(() => checkAllowedPackages(packages, allowedPackages)).not.toThrowError( + FleetUnauthorizedError + ); + }); + + it('throws if contains unresolved package', () => { + const packages = [{ name: 'packageA' }, { name: 'packageB' }, { name: undefined }]; + const allowedPackages = ['packageA', 'packageB', 'packageC']; + expect(() => checkAllowedPackages(packages, allowedPackages, 'name')).toThrowError( + new FleetUnauthorizedError( + 'Authorization denied. Allowed package(s): packageA, packageB, packageC.' + ) + ); + }); + + it('throws if contains restricted packages', () => { + const packages = [{ name: 'packageA' }, { name: 'packageB' }, { name: 'packageC' }]; + const allowedPackages = ['packageA', 'packageB']; + expect(() => checkAllowedPackages(packages, allowedPackages, 'name')).toThrowError( + new FleetUnauthorizedError( + 'Authorization denied to package: packageC. Allowed package(s): packageA, packageB' + ) + ); + }); +}); diff --git a/x-pack/plugins/fleet/server/services/check_allowed_packages.ts b/x-pack/plugins/fleet/server/services/check_allowed_packages.ts new file mode 100644 index 0000000000000..fffd8d0bdcb91 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/check_allowed_packages.ts @@ -0,0 +1,48 @@ +/* + * 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 { get } from 'lodash'; + +import { FleetUnauthorizedError } from '../errors'; + +export function checkAllowedPackages( + packages: T[], + allowedPackages?: string[], + keyPath: string = '' +) { + // allowedPackages is undefined when user has privileges from fleet + if (!packages.length || !allowedPackages) { + return; + } + + if (!allowedPackages.length) { + throw new FleetUnauthorizedError( + 'Authorization denied due to lack of integration package privileges' + ); + } + + const allowedPackagedSet = new Set(allowedPackages); + const allowedPackagesStr = allowedPackages.join(', '); + + packages.some((pkg) => { + const pkgName = typeof pkg === 'string' ? pkg : get(pkg, keyPath, undefined); + if (!pkgName) { + throw new FleetUnauthorizedError( + `Authorization denied. Allowed package(s): ${allowedPackagesStr}.` + ); + } + + const isRestricted = !allowedPackagedSet.has(pkgName); + if (isRestricted) { + throw new FleetUnauthorizedError( + `Authorization denied to package: ${pkgName}. Allowed package(s): ${allowedPackagesStr}` + ); + } + + return false; + }); +} diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts index c293b38a6f46a..8ba41a5556f46 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts @@ -279,7 +279,7 @@ describe('EPM index template install', () => { }); expect(indexTemplate.indexTemplate.template.settings).toEqual({ - index: { mode: 'time_series', routing_path: ['test_dimension'] }, + index: { mode: 'time_series' }, }); }); }); diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts index 23c55db1d43f0..4455c719207b2 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts @@ -18,7 +18,6 @@ import type { } from '../../../../types'; import { appContextService } from '../../..'; import { getRegistryDataStreamAssetBaseName } from '../../../../../common/services'; -import { builRoutingPath } from '../../../package_policies'; import { FLEET_GLOBALS_COMPONENT_TEMPLATE_NAME, FLEET_AGENT_ID_VERIFY_COMPONENT_TEMPLATE_NAME, @@ -499,17 +498,10 @@ function getBaseTemplate({ const isIndexModeTimeSeries = registryElasticsearch?.index_mode === 'time_series'; - const mappingsProperties = mappings?.properties ?? {}; - - // All mapped fields of type keyword and time_series_dimension enabled will be included in the generated routing path - // Temporarily generating routing_path here until fixed in elasticsearch https://github.com/elastic/elasticsearch/issues/91592 - const routingPath = builRoutingPath(mappingsProperties); - let settingsIndex = {}; - if (isIndexModeTimeSeries && routingPath.length > 0) { + if (isIndexModeTimeSeries) { settingsIndex = { mode: 'time_series', - routing_path: routingPath, }; } diff --git a/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts index dd2a66a1526ab..4dbceb772cc20 100644 --- a/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts @@ -294,6 +294,7 @@ export async function installKibanaSavedObjects({ overwrite: true, readStream: createListStream(toBeSavedObjects), createNewCopies: false, + refresh: false, }) ); diff --git a/x-pack/plugins/fleet/server/services/index.ts b/x-pack/plugins/fleet/server/services/index.ts index 133d5cf88d71c..a5078471d934d 100644 --- a/x-pack/plugins/fleet/server/services/index.ts +++ b/x-pack/plugins/fleet/server/services/index.ts @@ -64,3 +64,5 @@ export type { PackageService, PackageClient } from './epm'; export { migrateSettingsToFleetServerHost } from './fleet_server_host'; export { FleetUsageSender } from './telemetry/fleet_usage_sender'; + +export { checkAllowedPackages } from './check_allowed_packages'; diff --git a/x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.test.ts b/x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.test.ts index 40d67b079655c..9d43a9fad7efd 100644 --- a/x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.test.ts +++ b/x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.test.ts @@ -10,10 +10,7 @@ import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks import type { NewPackagePolicy, PackagePolicy } from '../../types'; -import { - builRoutingPath, - handleExperimentalDatastreamFeatureOptIn, -} from './experimental_datastream_features'; +import { handleExperimentalDatastreamFeatureOptIn } from './experimental_datastream_features'; function getNewTestPackagePolicy({ isSyntheticSourceEnabled, @@ -187,7 +184,7 @@ describe('experimental_datastream_features', () => { body: expect.objectContaining({ template: expect.objectContaining({ settings: expect.objectContaining({ - index: { mode: 'time_series', routing_path: ['test_dimension'] }, + index: { mode: 'time_series' }, }), }), }), @@ -291,7 +288,7 @@ describe('experimental_datastream_features', () => { body: expect.objectContaining({ template: expect.objectContaining({ settings: expect.objectContaining({ - index: { mode: 'time_series', routing_path: ['test_dimension'] }, + index: { mode: 'time_series' }, }), }), }), @@ -300,64 +297,4 @@ describe('experimental_datastream_features', () => { }); }); }); - it('should build routing path', () => { - const mappingProperties = { - cloud: { - properties: { - availability_zone: { - ignore_above: 1024, - type: 'keyword', - }, - image: { - properties: { - id: { - ignore_above: 1024, - type: 'keyword', - }, - }, - }, - }, - }, - test_dimension: { - time_series_dimension: true, - type: 'keyword', - }, - '@timestamp': { - type: 'date', - }, - }; - const routingPath = builRoutingPath(mappingProperties as any); - expect(routingPath).toEqual(['test_dimension']); - }); - - it('should build routing path from nested properties', () => { - const mappingProperties = { - cloud: { - properties: { - availability_zone: { - ignore_above: 1024, - type: 'keyword', - }, - image: { - properties: { - id: { - ignore_above: 1024, - type: 'keyword', - time_series_dimension: true, - }, - }, - }, - }, - }, - test_dimension: { - time_series_dimension: true, - type: 'keyword', - }, - '@timestamp': { - type: 'date', - }, - }; - const routingPath = builRoutingPath(mappingProperties as any); - expect(routingPath).toEqual(['cloud.image.id', 'test_dimension']); - }); }); diff --git a/x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.ts b/x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.ts index 3a60733a57eb5..06a51a0b02eb4 100644 --- a/x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.ts +++ b/x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.ts @@ -5,10 +5,6 @@ * 2.0. */ -import type { - MappingProperty, - PropertyName, -} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; @@ -16,31 +12,6 @@ import type { NewPackagePolicy, PackagePolicy } from '../../types'; import { getInstallation } from '../epm/packages'; import { updateDatastreamExperimentalFeatures } from '../epm/packages/update'; -function mapFields(mappingProperties: Record) { - const mappings = Object.keys(mappingProperties).reduce((acc, curr) => { - const property = mappingProperties[curr] as any; - if (property.properties) { - const childMappings = mapFields(property.properties); - Object.keys(childMappings).forEach((key) => { - acc[curr + '.' + key] = childMappings[key]; - }); - } else { - acc[curr] = property; - } - return acc; - }, {} as any); - return mappings; -} - -export function builRoutingPath(properties: Record) { - const mappingsProperties = mapFields(properties); - return Object.keys(mappingsProperties).filter( - (mapping) => - mappingsProperties[mapping].type === 'keyword' && - mappingsProperties[mapping].time_series_dimension - ); -} - export async function handleExperimentalDatastreamFeatureOptIn({ soClient, esClient, @@ -106,14 +77,6 @@ export async function handleExperimentalDatastreamFeatureOptIn({ } if (isTSDBOptInChanged && featureMapEntry.features.tsdb) { - const mappingsProperties = componentTemplate.template?.mappings?.properties ?? {}; - - // All mapped fields of type keyword and time_series_dimension enabled will be included in the generated routing path - // Temporarily generating routing_path here until fixed in elasticsearch https://github.com/elastic/elasticsearch/issues/91592 - const routingPath = builRoutingPath(mappingsProperties); - - if (routingPath.length === 0) continue; - const indexTemplateRes = await esClient.indices.getIndexTemplate({ name: featureMapEntry.data_stream, }); @@ -127,7 +90,6 @@ export async function handleExperimentalDatastreamFeatureOptIn({ ...(indexTemplate.template?.settings ?? {}), index: { mode: 'time_series', - routing_path: routingPath, }, }, }, diff --git a/x-pack/plugins/fleet/server/services/security/fleet_router.test.ts b/x-pack/plugins/fleet/server/services/security/fleet_router.test.ts index 1f2b6c3fab22b..6af9c891b31fc 100644 --- a/x-pack/plugins/fleet/server/services/security/fleet_router.test.ts +++ b/x-pack/plugins/fleet/server/services/security/fleet_router.test.ts @@ -71,6 +71,8 @@ describe('FleetAuthzRouter', () => { const mockContext = createAppContextStartContractMock(); // @ts-expect-error type doesn't properly respect deeply mocked keys mockContext.securityStart.authz.actions.api.get.mockImplementation((priv) => `api:${priv}`); + // @ts-expect-error type doesn't properly respect deeply mocked keys + mockContext.securityStart.authz.actions.ui.get.mockImplementation((priv) => `ui:${priv}`); mockContext.securityStart.authc.getCurrentUser.mockReturnValue({ username: 'foo', diff --git a/x-pack/plugins/fleet/server/services/security/route_required_authz.ts b/x-pack/plugins/fleet/server/services/security/route_required_authz.ts index 107279f5f33e4..98effa4070c96 100644 --- a/x-pack/plugins/fleet/server/services/security/route_required_authz.ts +++ b/x-pack/plugins/fleet/server/services/security/route_required_authz.ts @@ -11,6 +11,8 @@ import type { RouteMethod } from '@kbn/core-http-server'; import { PACKAGE_POLICY_API_ROUTES, AGENT_API_ROUTES } from '../../../common'; +import { EPM_API_ROUTES } from '../../constants'; + import type { FleetRouteRequiredAuthz } from './types'; /** @@ -144,6 +146,40 @@ const ROUTE_AUTHZ_REQUIREMENTS = deepFreeze - security.authz.actions.api.get(`${DEFAULT_APP_CATEGORIES.security.id}-${privilege}`) + const endpointPrivileges = Object.entries(ENDPOINT_PRIVILEGES).map( + ([_, { appId, privilegeType, privilegeName }]) => { + if (privilegeType === 'ui') { + return security.authz.actions[privilegeType].get(`${appId}`, `${privilegeName}`); + } + return security.authz.actions[privilegeType].get(`${appId}-${privilegeName}`); + } ); const { privileges } = await checkPrivileges({ kibana: [ diff --git a/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts b/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts index 8e13ca99eb722..40c3c77f9418c 100644 --- a/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts +++ b/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts @@ -60,6 +60,18 @@ export const fleetUsagesSchema: RootSchema = { description: 'The total number of enrolled agents currently offline', }, }, + inactive: { + type: 'long', + _meta: { + description: 'The total number of enrolled agents currently inactive', + }, + }, + unenrolled: { + type: 'long', + _meta: { + description: 'The total number of unenrolled agents', + }, + }, total_all_statuses: { type: 'long', _meta: { @@ -113,6 +125,18 @@ export const fleetUsagesSchema: RootSchema = { description: 'The number of Fleet Server hosts configured in Fleet settings.', }, }, + inactive: { + type: 'long', + _meta: { + description: 'The total number of enrolled agents currently inactive', + }, + }, + unenrolled: { + type: 'long', + _meta: { + description: 'The total number of unenrolled agents', + }, + }, }, }, packages: { diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/unified_search_bar.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/unified_search_bar.tsx index a588537244d0f..cc9f6e7ef4102 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/unified_search_bar.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/unified_search_bar.tsx @@ -11,6 +11,7 @@ import type { Filter, Query, TimeRange } from '@kbn/es-query'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { SavedQuery } from '@kbn/data-plugin/public'; import { i18n } from '@kbn/i18n'; +import { EuiFlexGrid } from '@elastic/eui'; import deepEqual from 'fast-deep-equal'; import type { InfraClientStartDeps } from '../../../../types'; import { useUnifiedSearchContext } from '../hooks/use_unified_search'; @@ -72,7 +73,7 @@ export const UnifiedSearchBar = ({ dataView }: Props) => { }; return ( - <> + { filters={unifiedSearchFilters} onFilterChange={onPanelFiltersChange} /> - + ); }; diff --git a/x-pack/plugins/lens/public/datasources/form_based/datapanel.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/datapanel.test.tsx index 411b8cd094ab2..f774525518e49 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/datapanel.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/datapanel.test.tsx @@ -374,6 +374,7 @@ describe('FormBased Data Panel', () => { (UseExistingFieldsApi.useExistingFieldsReader as jest.Mock).mockClear(); (UseExistingFieldsApi.useExistingFieldsFetcher as jest.Mock).mockClear(); UseExistingFieldsApi.resetExistingFieldsCache(); + window.localStorage.removeItem('lens.unifiedFieldList.initiallyOpenSections'); }); it('should render a warning if there are no index patterns', async () => { diff --git a/x-pack/plugins/lens/public/datasources/form_based/datapanel.tsx b/x-pack/plugins/lens/public/datasources/form_based/datapanel.tsx index 01feaa4187627..374eb430dae9c 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/datapanel.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/datapanel.tsx @@ -428,6 +428,7 @@ export const InnerFormBasedDataPanel = function InnerFormBasedDataPanel({ {...fieldListGroupedProps} renderFieldItem={renderFieldItem} data-test-subj="lnsIndexPattern" + localStorageKeyPrefix="lens" /> diff --git a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/shared_components/label_input.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/shared_components/label_input.tsx index 9d8730d38216a..ded5298a93879 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/shared_components/label_input.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/shared_components/label_input.tsx @@ -27,7 +27,10 @@ export const LabelInput = ({ dataTestSubj?: string; compressed?: boolean; }) => { - const { inputValue, handleInputChange } = useDebouncedValue({ value, onChange }); + const { inputValue, handleInputChange } = useDebouncedValue( + { value, onChange }, + { allowFalsyValue: true } + ); const localKeyHold = useRef(false); return ( diff --git a/x-pack/plugins/lens/public/datasources/text_based/datapanel.tsx b/x-pack/plugins/lens/public/datasources/text_based/datapanel.tsx index b278284bad8e9..aad9bae11faf4 100644 --- a/x-pack/plugins/lens/public/datasources/text_based/datapanel.tsx +++ b/x-pack/plugins/lens/public/datasources/text_based/datapanel.tsx @@ -161,6 +161,7 @@ export function TextBasedDataPanel({ {...fieldListGroupedProps} renderFieldItem={renderFieldItem} data-test-subj="lnsTextBasedLanguages" + localStorageKeyPrefix="lens" /> diff --git a/x-pack/plugins/maps/common/mvt_request_body.test.ts b/x-pack/plugins/maps/common/mvt_request_body.test.ts index 4f06d21ff2507..fd67cdeed3e8b 100644 --- a/x-pack/plugins/maps/common/mvt_request_body.test.ts +++ b/x-pack/plugins/maps/common/mvt_request_body.test.ts @@ -5,73 +5,123 @@ * 2.0. */ -import { decodeMvtResponseBody, encodeMvtResponseBody } from './mvt_request_body'; +import { + decodeMvtResponseBody, + encodeMvtResponseBody, + getAggsTileRequest, + getHitsTileRequest, +} from './mvt_request_body'; +import { RENDER_AS } from './constants'; -test('Should encode shape into URI safe string and decode back to original shape', () => { - const searchRequest = { - docvalue_fields: [], - size: 10000, - _source: false, - script_fields: {}, - stored_fields: ['geopoint'], - runtime_mappings: { - 'day of week': { - type: 'keyword', - script: { - source: - "ZonedDateTime input = doc['ISSUE_DATE'].value;\nString output = input.format(DateTimeFormatter.ofPattern('e')) + ' ' + input.format(DateTimeFormatter.ofPattern('E'));\nemit(output);", +describe('decodeMvtResponseBody', () => { + test('Should encode shape into URI safe string and decode back to original shape', () => { + const searchRequest = { + docvalue_fields: [], + size: 10000, + _source: false, + script_fields: {}, + stored_fields: ['geopoint'], + runtime_mappings: { + 'day of week': { + type: 'keyword', + script: { + source: + "ZonedDateTime input = doc['ISSUE_DATE'].value;\nString output = input.format(DateTimeFormatter.ofPattern('e')) + ' ' + input.format(DateTimeFormatter.ofPattern('E'));\nemit(output);", + }, }, }, - }, - query: { - bool: { - must: [], - filter: [], - should: [], - must_not: [], + query: { + bool: { + must: [], + filter: [], + should: [], + must_not: [], + }, }, - }, - }; - const encodedSearchRequest = encodeMvtResponseBody(searchRequest); - expect(encodedSearchRequest).toBe( - `(_source%3A!f%2Cdocvalue_fields%3A!()%2Cquery%3A(bool%3A(filter%3A!()%2Cmust%3A!()%2Cmust_not%3A!()%2Cshould%3A!()))%2Cruntime_mappings%3A('day%20of%20week'%3A(script%3A(source%3A'ZonedDateTime%20input%20%3D%20doc%5B!'ISSUE_DATE!'%5D.value%3B%0AString%20output%20%3D%20input.format(DateTimeFormatter.ofPattern(!'e!'))%20%2B%20!'%20!'%20%2B%20input.format(DateTimeFormatter.ofPattern(!'E!'))%3B%0Aemit(output)%3B')%2Ctype%3Akeyword))%2Cscript_fields%3A()%2Csize%3A10000%2Cstored_fields%3A!(geopoint))` - ); - expect(decodeMvtResponseBody(encodedSearchRequest)).toEqual(searchRequest); -}); + }; + const encodedSearchRequest = encodeMvtResponseBody(searchRequest); + expect(encodedSearchRequest).toBe( + `(_source%3A!f%2Cdocvalue_fields%3A!()%2Cquery%3A(bool%3A(filter%3A!()%2Cmust%3A!()%2Cmust_not%3A!()%2Cshould%3A!()))%2Cruntime_mappings%3A('day%20of%20week'%3A(script%3A(source%3A'ZonedDateTime%20input%20%3D%20doc%5B!'ISSUE_DATE!'%5D.value%3B%0AString%20output%20%3D%20input.format(DateTimeFormatter.ofPattern(!'e!'))%20%2B%20!'%20!'%20%2B%20input.format(DateTimeFormatter.ofPattern(!'E!'))%3B%0Aemit(output)%3B')%2Ctype%3Akeyword))%2Cscript_fields%3A()%2Csize%3A10000%2Cstored_fields%3A!(geopoint))` + ); + expect(decodeMvtResponseBody(encodedSearchRequest)).toEqual(searchRequest); + }); -test(`Should handle '%' character`, () => { - const runtimeFieldScript = `if (doc['price'].size() != 0){ - String tmp=dissect('$%{price}').extract(doc["price"].value)?.price; + test(`Should handle '%' character`, () => { + const runtimeFieldScript = `if (doc['price'].size() != 0){ + String tmp=dissect('$%{price}').extract(doc["price"].value)?.price; - tmp = tmp.replace(',',''); + tmp = tmp.replace(',',''); - def pn = Double.parseDouble( tmp ); + def pn = Double.parseDouble( tmp ); - if (pn != null) emit(pn); -} -else { - emit(0) -}`; - const searchRequest = { - size: 10000, - _source: false, - runtime_mappings: { - price_as_number: { - type: 'keyword', - script: { - source: runtimeFieldScript, + if (pn != null) emit(pn); + } + else { + emit(0) + }`; + const searchRequest = { + size: 10000, + _source: false, + runtime_mappings: { + price_as_number: { + type: 'keyword', + script: { + source: runtimeFieldScript, + }, }, }, - }, - query: { - bool: { - must: [], - filter: [], - should: [], - must_not: [], + query: { + bool: { + must: [], + filter: [], + should: [], + must_not: [], + }, }, - }, - }; - const encodedSearchRequest = encodeMvtResponseBody(searchRequest); - expect(decodeMvtResponseBody(encodedSearchRequest)).toEqual(searchRequest); + }; + const encodedSearchRequest = encodeMvtResponseBody(searchRequest); + expect(decodeMvtResponseBody(encodedSearchRequest)).toEqual(searchRequest); + }); +}); + +describe('getAggsTileRequest', () => { + test(`Should URL encode path parameters`, () => { + const searchRequest = { + aggs: {}, + runtime_mappings: {}, + query: {}, + }; + const { path } = getAggsTileRequest({ + encodedRequestBody: encodeMvtResponseBody(searchRequest), + geometryFieldName: 'my location', + gridPrecision: 8, + hasLabels: true, + index: 'my index', + renderAs: RENDER_AS.POINT, + x: 0, + y: 0, + z: 0, + }); + expect(path).toEqual('/my%20index/_mvt/my%20location/0/0/0'); + }); +}); + +describe('getHitsTileRequest', () => { + test(`Should URL encode path parameters`, () => { + const searchRequest = { + size: 10000, + runtime_mappings: {}, + query: {}, + }; + const { path } = getHitsTileRequest({ + encodedRequestBody: encodeMvtResponseBody(searchRequest), + geometryFieldName: 'my location', + hasLabels: true, + index: 'my index', + x: 0, + y: 0, + z: 0, + }); + expect(path).toEqual('/my%20index/_mvt/my%20location/0/0/0'); + }); }); diff --git a/x-pack/plugins/maps/common/mvt_request_body.ts b/x-pack/plugins/maps/common/mvt_request_body.ts index dbf719d685c46..f876caefe0312 100644 --- a/x-pack/plugins/maps/common/mvt_request_body.ts +++ b/x-pack/plugins/maps/common/mvt_request_body.ts @@ -43,7 +43,9 @@ export function getAggsTileRequest({ }) { const requestBody = decodeMvtResponseBody(encodedRequestBody) as any; return { - path: `/${encodeURIComponent(index)}/_mvt/${geometryFieldName}/${z}/${x}/${y}`, + path: `/${encodeURIComponent(index)}/_mvt/${encodeURIComponent( + geometryFieldName + )}/${z}/${x}/${y}`, body: { size: 0, // no hits grid_precision: gridPrecision, @@ -53,7 +55,7 @@ export function getAggsTileRequest({ grid_agg: renderAs === RENDER_AS.HEX ? 'geohex' : 'geotile', grid_type: renderAs === RENDER_AS.GRID || renderAs === RENDER_AS.HEX ? 'grid' : 'centroid', aggs: requestBody.aggs, - fields: requestBody.fields, + fields: requestBody.fields ? requestBody.fields : [], runtime_mappings: requestBody.runtime_mappings, with_labels: hasLabels, }, @@ -79,7 +81,9 @@ export function getHitsTileRequest({ }) { const requestBody = decodeMvtResponseBody(encodedRequestBody) as any; return { - path: `/${encodeURIComponent(index)}/_mvt/${geometryFieldName}/${z}/${x}/${y}`, + path: `/${encodeURIComponent(index)}/_mvt/${encodeURIComponent( + geometryFieldName + )}/${z}/${x}/${y}`, body: { grid_precision: 0, // no aggs exact_bounds: true, diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/create_source_editor.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/create_source_editor.js index 872c7b71c9f92..aede56a726713 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/create_source_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/create_source_editor.js @@ -52,14 +52,9 @@ export class CreateSourceEditor extends Component { }; _onGeoFieldSelect = (geoFieldName) => { - const geoField = - this.state.indexPattern && geoFieldName - ? this.state.indexPattern.fields.getByName(geoFieldName) - : undefined; this.setState( { geoField: geoFieldName, - geoFieldType: geoField ? geoField.type : undefined, }, this.previewLayer ); @@ -115,11 +110,7 @@ export class CreateSourceEditor extends Component { } return ( - + ); } diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/render_as_select/render_as_select.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/render_as_select/render_as_select.tsx index e5baf65711d3f..ce95c4ef982b8 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/render_as_select/render_as_select.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/render_as_select/render_as_select.tsx @@ -8,14 +8,13 @@ import React from 'react'; import { EuiFormRow, EuiButtonGroup } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ES_GEO_FIELD_TYPE, RENDER_AS } from '../../../../../common/constants'; +import { RENDER_AS } from '../../../../../common/constants'; import { getIsCloud } from '../../../../kibana_services'; import { getIsGoldPlus } from '../../../../licensed_features'; import { CLUSTER_LABEL, GRID_LABEL, HEX_LABEL } from './i18n_constants'; import { ShowAsLabel } from './show_as_label'; interface Props { - geoFieldType?: ES_GEO_FIELD_TYPE; renderAs: RENDER_AS; onChange: (newValue: RENDER_AS) => void; isColumnCompressed?: boolean; @@ -34,12 +33,6 @@ export function RenderAsSelect(props: Props) { defaultMessage: '{hexLabel} is a subscription feature.', values: { hexLabel: HEX_LABEL }, }); - } else if (props.geoFieldType !== ES_GEO_FIELD_TYPE.GEO_POINT) { - isHexDisabled = true; - hexDisabledReason = i18n.translate('xpack.maps.hexbin.geoShape.disabledReason', { - defaultMessage: `{hexLabel} requires a 'geo_point' cluster field.`, - values: { hexLabel: HEX_LABEL }, - }); } const options = [ diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.tsx index 8b42bc2f162c5..52431b95f52c2 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.tsx @@ -13,13 +13,7 @@ import { EuiPanel, EuiSpacer, EuiComboBoxOptionOption, EuiTitle } from '@elastic import { DataViewField } from '@kbn/data-views-plugin/public'; import { indexPatterns } from '@kbn/data-plugin/public'; import { getDataViewNotFoundMessage } from '../../../../common/i18n_getters'; -import { - AGG_TYPE, - ES_GEO_FIELD_TYPE, - GRID_RESOLUTION, - LAYER_TYPE, - RENDER_AS, -} from '../../../../common/constants'; +import { AGG_TYPE, GRID_RESOLUTION, LAYER_TYPE, RENDER_AS } from '../../../../common/constants'; import { MetricsEditor } from '../../../components/metrics_editor'; import { getIndexPatternService } from '../../../kibana_services'; import { ResolutionEditor } from './resolution_editor'; @@ -41,7 +35,6 @@ interface Props { } interface State { - geoFieldType?: ES_GEO_FIELD_TYPE; metricsEditorKey: string; fields: DataViewField[]; loadError?: string; @@ -80,11 +73,8 @@ export class UpdateSourceEditor extends Component { return; } - const geoField = indexPattern.fields.getByName(this.props.geoFieldName); - this.setState({ fields: indexPattern.fields.filter((field) => !indexPatterns.isNestedField(field)), - geoFieldType: geoField ? (geoField.type as ES_GEO_FIELD_TYPE) : undefined, }); } @@ -188,7 +178,6 @@ export class UpdateSourceEditor extends Component { /> diff --git a/x-pack/plugins/maps/public/render_app.tsx b/x-pack/plugins/maps/public/render_app.tsx index 196332d5e873e..23244df45b9b5 100644 --- a/x-pack/plugins/maps/public/render_app.tsx +++ b/x-pack/plugins/maps/public/render_app.tsx @@ -12,11 +12,6 @@ import { i18n } from '@kbn/i18n'; import type { CoreStart, AppMountParameters } from '@kbn/core/public'; import { ExitFullScreenButtonKibanaProvider } from '@kbn/shared-ux-button-exit-full-screen'; import { KibanaThemeProvider, toMountPoint } from '@kbn/kibana-react-plugin/public'; -import { - createKbnUrlStateStorage, - withNotifyOnErrors, - IKbnUrlStateStorage, -} from '@kbn/kibana-utils-plugin/public'; import { FormattedRelative } from '@kbn/i18n-react'; import type { SavedObjectTaggingPluginStart } from '@kbn/saved-objects-tagging-plugin/public'; import { TableListViewKibanaProvider } from '@kbn/content-management-table-list'; @@ -24,7 +19,6 @@ import { getCoreChrome, getCoreI18n, getMapsCapabilities, - getToasts, getEmbeddableService, getDocLinks, getCore, @@ -35,7 +29,6 @@ import { APP_ID } from '../common/constants'; import { registerLayerWizards } from './classes/layers/wizards/load_layer_wizards'; export let goToSpecifiedPath: (path: string) => void; -export let kbnUrlStateStorage: IKbnUrlStateStorage; function setAppChrome() { if (!getMapsCapabilities().save) { @@ -81,11 +74,6 @@ export async function renderApp( } ) { goToSpecifiedPath = (path) => history.push(path); - kbnUrlStateStorage = createKbnUrlStateStorage({ - useHash: false, - history, - ...withNotifyOnErrors(getToasts()), - }); const stateTransfer = getEmbeddableService().getStateTransfer(); diff --git a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx index 9aed108b62ad4..fffb12130a05d 100644 --- a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx +++ b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx @@ -15,7 +15,18 @@ import { Subscription } from 'rxjs'; import { type Filter, FilterStateStore, type Query, type TimeRange } from '@kbn/es-query'; import type { DataViewSpec } from '@kbn/data-views-plugin/public'; import type { DataView } from '@kbn/data-plugin/common'; -import { SavedQuery, QueryStateChange, QueryState } from '@kbn/data-plugin/public'; +import { + GlobalQueryStateFromUrl, + QueryState, + QueryStateChange, + SavedQuery, + syncGlobalQueryStateWithUrl, +} from '@kbn/data-plugin/public'; +import { + createKbnUrlStateStorage, + withNotifyOnErrors, + IKbnUrlStateStorage, +} from '@kbn/kibana-utils-plugin/public'; import { getData, getExecutionContext, @@ -27,14 +38,7 @@ import { getTimeFilter, getToasts, } from '../../../kibana_services'; -import { - AppStateManager, - startAppStateSyncing, - getGlobalState, - updateGlobalState, - startGlobalStateSyncing, - MapsGlobalState, -} from '../url_state'; +import { AppStateManager, startAppStateSyncing } from '../url_state'; import { MapContainer } from '../../../connected_components/map_container'; import { getIndexPatternsFromIds } from '../../../index_pattern_util'; import { getTopNavConfig } from '../top_nav_config'; @@ -44,7 +48,6 @@ import { getMapEmbeddableDisplayName } from '../../../../common/i18n_getters'; import { getInitialQuery, getInitialRefreshConfig, - getInitialTimeFilters, SavedMap, unsavedChangesTitle, unsavedChangesWarning, @@ -100,6 +103,8 @@ export class MapApp extends React.Component { _appStateManager = new AppStateManager(); _prevIndexPatternIds: string[] | null = null; _isMounted: boolean = false; + _kbnUrlStateStorage: IKbnUrlStateStorage; + _initialTimeFromUrl: TimeRange | undefined; constructor(props: Props) { super(props); @@ -109,6 +114,11 @@ export class MapApp extends React.Component { isRefreshPaused: true, refreshInterval: 0, }; + this._kbnUrlStateStorage = createKbnUrlStateStorage({ + useHash: false, + history: props.history, + ...withNotifyOnErrors(getToasts()), + }); } componentDidMount() { @@ -132,8 +142,16 @@ export class MapApp extends React.Component { ) .subscribe(); - this._globalSyncUnsubscribe = startGlobalStateSyncing(); - this._appSyncUnsubscribe = startAppStateSyncing(this._appStateManager); + // syncGlobalQueryStateWithUrl mutates global state by merging URL state with Kibana QueryStart state + // capture _initialTimeFromUrl before global state is mutated + this._initialTimeFromUrl = this._getGlobalState()?.time; + const { stop } = syncGlobalQueryStateWithUrl(getData().query, this._kbnUrlStateStorage); + this._globalSyncUnsubscribe = stop; + + this._appSyncUnsubscribe = startAppStateSyncing( + this._appStateManager, + this._kbnUrlStateStorage + ); this._globalSyncChangeMonitorSubscription = getData().query.state$.subscribe( this._updateFromGlobalState ); @@ -193,6 +211,20 @@ export class MapApp extends React.Component { this._onQueryChange({ time: globalState.time }); }; + _getGlobalState() { + return this._kbnUrlStateStorage.get('_g') ?? {}; + } + + _updateGlobalState(newState: GlobalQueryStateFromUrl) { + this._kbnUrlStateStorage.set('_g', { + ...this._getGlobalState(), + ...newState, + }); + if (!this.state.initialized) { + this._kbnUrlStateStorage.kbnUrlControls.flush(true); + } + } + async _updateIndexPatterns() { const { nextIndexPatternIds } = this.props; @@ -247,17 +279,27 @@ export class MapApp extends React.Component { }); // sync globalState - const updatedGlobalState: MapsGlobalState = { + const updatedGlobalState: GlobalQueryStateFromUrl = { filters: filterManager.getGlobalFilters(), }; if (time) { updatedGlobalState.time = time; } - updateGlobalState(updatedGlobalState, !this.state.initialized); + this._updateGlobalState(updatedGlobalState); }; + _getInitialTime(serializedMapState?: SerializedMapState) { + if (this._initialTimeFromUrl) { + return this._initialTimeFromUrl; + } + + return !this.props.savedMap.hasSaveAndReturnConfig() && serializedMapState?.timeFilters + ? serializedMapState.timeFilters + : getTimeFilter().getTime(); + } + _initMapAndLayerSettings(serializedMapState?: SerializedMapState) { - const globalState: MapsGlobalState = getGlobalState(); + const globalState = this._getGlobalState(); const savedObjectFilters = serializedMapState?.filters ? serializedMapState.filters : []; const appFilters = this._appStateManager.getFilters() || []; @@ -273,11 +315,7 @@ export class MapApp extends React.Component { this._onQueryChange({ filters: [..._.get(globalState, 'filters', []), ...appFilters, ...savedObjectFilters], query, - time: getInitialTimeFilters({ - hasSaveAndReturnConfig: this.props.savedMap.hasSaveAndReturnConfig(), - serializedMapState, - globalState, - }), + time: this._getInitialTime(serializedMapState), }); this._onRefreshConfigChange( @@ -299,15 +337,12 @@ export class MapApp extends React.Component { isRefreshPaused: isPaused, refreshInterval: interval, }); - updateGlobalState( - { - refreshInterval: { - pause: isPaused, - value: interval, - }, + this._updateGlobalState({ + refreshInterval: { + pause: isPaused, + value: interval, }, - !this.state.initialized - ); + }); } _updateStateFromSavedQuery = (savedQuery: SavedQuery) => { diff --git a/x-pack/plugins/maps/public/routes/map_page/saved_map/get_initial_time_filters.ts b/x-pack/plugins/maps/public/routes/map_page/saved_map/get_initial_time_filters.ts deleted file mode 100644 index 12be55a07b257..0000000000000 --- a/x-pack/plugins/maps/public/routes/map_page/saved_map/get_initial_time_filters.ts +++ /dev/null @@ -1,27 +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 { GlobalQueryStateFromUrl } from '@kbn/data-plugin/public'; -import { getUiSettings } from '../../../kibana_services'; -import { SerializedMapState } from './types'; - -export function getInitialTimeFilters({ - hasSaveAndReturnConfig, - serializedMapState, - globalState, -}: { - hasSaveAndReturnConfig: boolean; - serializedMapState?: SerializedMapState; - globalState: GlobalQueryStateFromUrl; -}) { - if (!hasSaveAndReturnConfig && serializedMapState?.timeFilters) { - return serializedMapState.timeFilters; - } - - const defaultTime = getUiSettings().get('timepicker:timeDefaults'); - return { ...defaultTime, ...globalState.time }; -} diff --git a/x-pack/plugins/maps/public/routes/map_page/saved_map/index.ts b/x-pack/plugins/maps/public/routes/map_page/saved_map/index.ts index c204267e0f9a6..2c09f696a591d 100644 --- a/x-pack/plugins/maps/public/routes/map_page/saved_map/index.ts +++ b/x-pack/plugins/maps/public/routes/map_page/saved_map/index.ts @@ -10,6 +10,5 @@ export { SavedMap } from './saved_map'; export { getInitialLayersFromUrlParam } from './get_initial_layers_from_url_param'; export { getInitialQuery } from './get_initial_query'; export { getInitialRefreshConfig } from './get_initial_refresh_config'; -export { getInitialTimeFilters } from './get_initial_time_filters'; export { unsavedChangesTitle, unsavedChangesWarning } from './get_breadcrumbs'; export { getOpenLayerWizardFromUrlParam } from './get_open_layer_wizard_url_param'; diff --git a/x-pack/plugins/maps/public/routes/map_page/url_state/app_sync.ts b/x-pack/plugins/maps/public/routes/map_page/url_state/app_sync.ts index 63461315b0ac1..e12efd7a8a99d 100644 --- a/x-pack/plugins/maps/public/routes/map_page/url_state/app_sync.ts +++ b/x-pack/plugins/maps/public/routes/map_page/url_state/app_sync.ts @@ -8,12 +8,18 @@ import { map } from 'rxjs/operators'; import { FilterStateStore } from '@kbn/es-query'; import { connectToQueryState } from '@kbn/data-plugin/public'; -import { syncState, BaseStateContainer } from '@kbn/kibana-utils-plugin/public'; +import { + IKbnUrlStateStorage, + syncState, + BaseStateContainer, +} from '@kbn/kibana-utils-plugin/public'; import { getData } from '../../../kibana_services'; -import { kbnUrlStateStorage } from '../../../render_app'; import { AppStateManager } from './app_state_manager'; -export function startAppStateSyncing(appStateManager: AppStateManager) { +export function startAppStateSyncing( + appStateManager: AppStateManager, + kbnUrlStateStorage: IKbnUrlStateStorage +) { // get appStateContainer // sync app filters with app state container from data.query to state container const { query } = getData(); diff --git a/x-pack/plugins/maps/public/routes/map_page/url_state/global_sync.ts b/x-pack/plugins/maps/public/routes/map_page/url_state/global_sync.ts deleted file mode 100644 index eb9510c6bed23..0000000000000 --- a/x-pack/plugins/maps/public/routes/map_page/url_state/global_sync.ts +++ /dev/null @@ -1,38 +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 type { Filter, TimeRange } from '@kbn/es-query'; -import { RefreshInterval } from '@kbn/data-plugin/public'; -import { syncQueryStateWithUrl } from '@kbn/data-plugin/public'; -import { getData } from '../../../kibana_services'; -import { kbnUrlStateStorage } from '../../../render_app'; - -export interface MapsGlobalState { - time?: TimeRange; - refreshInterval?: RefreshInterval; - filters?: Filter[]; -} - -export function startGlobalStateSyncing() { - const { stop } = syncQueryStateWithUrl(getData().query, kbnUrlStateStorage); - return stop; -} - -export function getGlobalState(): MapsGlobalState { - return kbnUrlStateStorage.get('_g') as MapsGlobalState; -} - -export function updateGlobalState(newState: MapsGlobalState, flushUrlState = false) { - const globalState = getGlobalState(); - kbnUrlStateStorage.set('_g', { - ...globalState, - ...newState, - }); - if (flushUrlState) { - kbnUrlStateStorage.kbnUrlControls.flush(true); - } -} diff --git a/x-pack/plugins/maps/public/routes/map_page/url_state/index.ts b/x-pack/plugins/maps/public/routes/map_page/url_state/index.ts index 6fa6514ac08df..9691b34350715 100644 --- a/x-pack/plugins/maps/public/routes/map_page/url_state/index.ts +++ b/x-pack/plugins/maps/public/routes/map_page/url_state/index.ts @@ -5,8 +5,6 @@ * 2.0. */ -export type { MapsGlobalState } from './global_sync'; -export { getGlobalState, updateGlobalState, startGlobalStateSyncing } from './global_sync'; export type { MapsAppState } from './app_state_manager'; export { AppStateManager } from './app_state_manager'; export { startAppStateSyncing } from './app_sync'; diff --git a/x-pack/plugins/ml/public/application/contexts/storage/storage_context.test.tsx b/x-pack/plugins/ml/common/types/storage.test.tsx similarity index 77% rename from x-pack/plugins/ml/public/application/contexts/storage/storage_context.test.tsx rename to x-pack/plugins/ml/common/types/storage.test.tsx index 6aeeb396f38c3..c27c6e74d9edb 100644 --- a/x-pack/plugins/ml/public/application/contexts/storage/storage_context.test.tsx +++ b/x-pack/plugins/ml/common/types/storage.test.tsx @@ -5,33 +5,38 @@ * 2.0. */ +import React, { FC } from 'react'; import { renderHook, act } from '@testing-library/react-hooks'; -import { MlStorageContextProvider, useStorage } from './storage_context'; -import { MlStorageKey } from '../../../../common/types/storage'; + +import type { Storage } from '@kbn/kibana-utils-plugin/public'; +import { StorageContextProvider, useStorage } from '@kbn/ml-local-storage'; + +import { ML_STORAGE_KEYS } from './storage'; const mockSet = jest.fn(); const mockRemove = jest.fn(); - -jest.mock('../kibana', () => ({ - useMlKibana: () => { - return { - services: { - storage: { - set: mockSet, - get: jest.fn((key: MlStorageKey) => { - switch (key) { - case 'ml.gettingStarted.isDismissed': - return true; - default: - return; - } - }), - remove: mockRemove, - }, - }, - }; - }, -})); +const mockStorage: Storage = { + set: mockSet, + get: jest.fn((key: string) => { + switch (key) { + case 'ml.gettingStarted.isDismissed': + return true; + default: + return; + } + }), + remove: mockRemove, + store: jest.fn() as any, + clear: jest.fn(), +}; + +const Provider: FC = ({ children }) => { + return ( + + {children} + + ); +}; describe('useStorage', () => { afterEach(() => { @@ -40,7 +45,7 @@ describe('useStorage', () => { test('returns the default value', () => { const { result } = renderHook(() => useStorage('ml.jobSelectorFlyout.applyTimeRange', true), { - wrapper: MlStorageContextProvider, + wrapper: Provider, }); expect(result.current[0]).toBe(true); @@ -48,7 +53,7 @@ describe('useStorage', () => { test('returns the value from storage', () => { const { result } = renderHook(() => useStorage('ml.gettingStarted.isDismissed', false), { - wrapper: MlStorageContextProvider, + wrapper: Provider, }); expect(result.current[0]).toBe(true); @@ -58,7 +63,7 @@ describe('useStorage', () => { const { result, waitForNextUpdate } = renderHook( () => useStorage('ml.gettingStarted.isDismissed'), { - wrapper: MlStorageContextProvider, + wrapper: Provider, } ); @@ -79,7 +84,7 @@ describe('useStorage', () => { const { result, waitForNextUpdate } = renderHook( () => useStorage('ml.gettingStarted.isDismissed'), { - wrapper: MlStorageContextProvider, + wrapper: Provider, } ); @@ -100,7 +105,7 @@ describe('useStorage', () => { const { result, waitForNextUpdate } = renderHook( () => useStorage('ml.gettingStarted.isDismissed'), { - wrapper: MlStorageContextProvider, + wrapper: Provider, } ); diff --git a/x-pack/plugins/ml/common/types/storage.ts b/x-pack/plugins/ml/common/types/storage.ts index 34673b7c51059..7e2e1ba799961 100644 --- a/x-pack/plugins/ml/common/types/storage.ts +++ b/x-pack/plugins/ml/common/types/storage.ts @@ -14,6 +14,14 @@ export const ML_FROZEN_TIER_PREFERENCE = 'ml.frozenDataTierPreference'; export const ML_ANOMALY_EXPLORER_PANELS = 'ml.anomalyExplorerPanels'; export const ML_NOTIFICATIONS_LAST_CHECKED_AT = 'ml.notificationsLastCheckedAt'; +export const FROZEN_TIER_PREFERENCE = { + EXCLUDE: 'exclude-frozen', + INCLUDE: 'include-frozen', +} as const; + +export type FrozenTierPreference = + typeof FROZEN_TIER_PREFERENCE[keyof typeof FROZEN_TIER_PREFERENCE]; + export type PartitionFieldConfig = | { /** @@ -51,14 +59,17 @@ export interface AnomalyExplorerPanelsState { mainPage: { size: number }; } -export type MlStorage = Partial<{ +export interface MlStorageRecord { + [key: string]: unknown; [ML_ENTITY_FIELDS_CONFIG]: PartitionFieldsConfig; [ML_APPLY_TIME_RANGE_CONFIG]: ApplyTimeRangeConfig; [ML_GETTING_STARTED_CALLOUT_DISMISSED]: boolean | undefined; - [ML_FROZEN_TIER_PREFERENCE]: 'exclude-frozen' | 'include-frozen'; + [ML_FROZEN_TIER_PREFERENCE]: FrozenTierPreference; [ML_ANOMALY_EXPLORER_PANELS]: AnomalyExplorerPanelsState | undefined; [ML_NOTIFICATIONS_LAST_CHECKED_AT]: number | undefined; -}> | null; +} + +export type MlStorage = Partial | null; export type MlStorageKey = keyof Exclude; @@ -69,7 +80,7 @@ export type TMlStorageMapped = T extends typeof ML_ENTIT : T extends typeof ML_GETTING_STARTED_CALLOUT_DISMISSED ? boolean | undefined : T extends typeof ML_FROZEN_TIER_PREFERENCE - ? 'exclude-frozen' | 'include-frozen' | undefined + ? FrozenTierPreference | undefined : T extends typeof ML_ANOMALY_EXPLORER_PANELS ? AnomalyExplorerPanelsState | undefined : T extends typeof ML_NOTIFICATIONS_LAST_CHECKED_AT @@ -83,8 +94,4 @@ export const ML_STORAGE_KEYS = [ ML_FROZEN_TIER_PREFERENCE, ML_ANOMALY_EXPLORER_PANELS, ML_NOTIFICATIONS_LAST_CHECKED_AT, -]; - -export function isMlStorageKey(key: unknown): key is MlStorageKey { - return typeof key === 'string' && ML_STORAGE_KEYS.includes(key); -} +] as const; diff --git a/x-pack/plugins/ml/common/util/alerts.ts b/x-pack/plugins/ml/common/util/alerts.ts index 6abc5333a1f73..6c997dfb71566 100644 --- a/x-pack/plugins/ml/common/util/alerts.ts +++ b/x-pack/plugins/ml/common/util/alerts.ts @@ -6,9 +6,9 @@ */ import { pick } from 'lodash'; +import { isDefined } from '@kbn/ml-is-defined'; import { CombinedJobWithStats, Datafeed, Job } from '../types/anomaly_detection_jobs'; import { resolveMaxTimeInterval } from './job_utils'; -import { isDefined } from '../types/guards'; import { parseInterval } from './parse_interval'; import { JobsHealthRuleTestsConfig, JobsHealthTests } from '../types/alerts'; diff --git a/x-pack/plugins/ml/common/util/job_utils.ts b/x-pack/plugins/ml/common/util/job_utils.ts index 4d50af19a8b96..a0cbb5d5762de 100644 --- a/x-pack/plugins/ml/common/util/job_utils.ts +++ b/x-pack/plugins/ml/common/util/job_utils.ts @@ -16,6 +16,7 @@ import { isPopulatedObject } from '@kbn/ml-is-populated-object'; import type { SerializableRecord } from '@kbn/utility-types'; import { FilterStateStore } from '@kbn/es-query'; import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { isDefined } from '@kbn/ml-is-defined'; import { ALLOWED_DATA_UNITS, JOB_ID_MAX_LENGTH } from '../constants/validation'; import { parseInterval } from './parse_interval'; import { maxLengthValidator } from './validators'; @@ -35,7 +36,6 @@ import { MLCATEGORY } from '../constants/field_types'; import { getAggregations, getDatafeedAggregations } from './datafeed_utils'; import { findAggField } from './validation_utils'; import { getFirstKeyInObject } from './object_utils'; -import { isDefined } from '../types/guards'; export interface ValidationResults { valid: boolean; diff --git a/x-pack/plugins/ml/public/alerting/jobs_health_rule/anomaly_detection_jobs_health_rule_trigger.tsx b/x-pack/plugins/ml/public/alerting/jobs_health_rule/anomaly_detection_jobs_health_rule_trigger.tsx index 9fff85c82888f..daab200ff0709 100644 --- a/x-pack/plugins/ml/public/alerting/jobs_health_rule/anomaly_detection_jobs_health_rule_trigger.tsx +++ b/x-pack/plugins/ml/public/alerting/jobs_health_rule/anomaly_detection_jobs_health_rule_trigger.tsx @@ -12,6 +12,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import useDebounce from 'react-use/lib/useDebounce'; import { RuleTypeParamsExpressionProps } from '@kbn/triggers-actions-ui-plugin/public'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; +import { isDefined } from '@kbn/ml-is-defined'; import { MlAnomalyDetectionJobsHealthRuleParams } from '../../../common/types/alerts'; import { JobSelectorControl } from '../job_selector'; import { jobsApiProvider } from '../../application/services/ml_api_service/jobs'; @@ -20,7 +21,6 @@ import { useMlKibana } from '../../application/contexts/kibana'; import { TestsSelectionControl } from './tests_selection_control'; import { ALL_JOBS_SELECTION } from '../../../common/constants/alerts'; import { BetaBadge } from '../beta_badge'; -import { isDefined } from '../../../common/types/guards'; export type MlAnomalyAlertTriggerProps = RuleTypeParamsExpressionProps; diff --git a/x-pack/plugins/ml/public/alerting/ml_anomaly_alert_trigger.tsx b/x-pack/plugins/ml/public/alerting/ml_anomaly_alert_trigger.tsx index a5ef1e7943438..980abb23e659d 100644 --- a/x-pack/plugins/ml/public/alerting/ml_anomaly_alert_trigger.tsx +++ b/x-pack/plugins/ml/public/alerting/ml_anomaly_alert_trigger.tsx @@ -10,6 +10,7 @@ import { EuiSpacer, EuiForm } from '@elastic/eui'; import useMount from 'react-use/lib/useMount'; import { i18n } from '@kbn/i18n'; import { RuleTypeParamsExpressionProps } from '@kbn/triggers-actions-ui-plugin/public'; +import { isDefined } from '@kbn/ml-is-defined'; import { JobSelectorControl } from './job_selector'; import { useMlKibana } from '../application/contexts/kibana'; import { jobsApiProvider } from '../application/services/ml_api_service/jobs'; @@ -29,7 +30,6 @@ import { ConfigValidator } from './config_validator'; import { CombinedJobWithStats } from '../../common/types/anomaly_detection_jobs'; import { AdvancedSettings } from './advanced_settings'; import { getLookbackInterval, getTopNBuckets } from '../../common/util/alerts'; -import { isDefined } from '../../common/types/guards'; import { parseInterval } from '../../common/util/parse_interval'; import { BetaBadge } from './beta_badge'; diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx index 98fe9674bb567..463cb34691144 100644 --- a/x-pack/plugins/ml/public/application/app.tsx +++ b/x-pack/plugins/ml/public/application/app.tsx @@ -15,7 +15,8 @@ import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; -import { MlStorageContextProvider } from './contexts/storage'; +import { StorageContextProvider } from '@kbn/ml-local-storage'; +import { ML_STORAGE_KEYS } from '../../common/types/storage'; import { setDependencyCache, clearCache } from './util/dependency_cache'; import { setLicenseCache } from './license'; import type { MlSetupDependencies, MlStartDependencies } from '../plugin'; @@ -111,9 +112,9 @@ const App: FC = ({ coreStart, deps, appMountParams }) => { mlServices: getMlGlobalServices(coreStart.http, deps.usageCollection), }} > - + - + diff --git a/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.test.tsx b/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.test.tsx index 7566d3664af61..442b1407aaf6d 100644 --- a/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.test.tsx +++ b/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.test.tsx @@ -20,7 +20,7 @@ jest.mock('./full_time_range_selector_service', () => ({ mockSetFullTimeRange(indexPattern, query), })); -jest.mock('../../contexts/storage', () => { +jest.mock('@kbn/ml-local-storage', () => { return { useStorage: jest.fn(() => 'exclude-frozen'), }; diff --git a/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.tsx b/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.tsx index 9b9154eb33660..3f4c42bc30ca5 100644 --- a/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.tsx +++ b/x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector.tsx @@ -22,9 +22,15 @@ import { import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import { i18n } from '@kbn/i18n'; import type { DataView } from '@kbn/data-views-plugin/public'; +import { useStorage } from '@kbn/ml-local-storage'; import { setFullTimeRange } from './full_time_range_selector_service'; -import { useStorage } from '../../contexts/storage'; -import { ML_FROZEN_TIER_PREFERENCE } from '../../../../common/types/storage'; +import { + ML_FROZEN_TIER_PREFERENCE, + FROZEN_TIER_PREFERENCE, + type MlStorageKey, + type TMlStorageMapped, + type FrozenTierPreference, +} from '../../../../common/types/storage'; import { GetTimeFieldRangeResponse } from '../../services/ml_api_service'; interface Props { @@ -34,13 +40,6 @@ interface Props { callback?: (a: GetTimeFieldRangeResponse) => void; } -const FROZEN_TIER_PREFERENCE = { - EXCLUDE: 'exclude-frozen', - INCLUDE: 'include-frozen', -} as const; - -type FrozenTierPreference = typeof FROZEN_TIER_PREFERENCE[keyof typeof FROZEN_TIER_PREFERENCE]; - // Component for rendering a button which automatically sets the range of the time filter // to the time range of data in the index(es) mapped to the supplied Kibana index pattern or query. export const FullTimeRangeSelector: FC = ({ dataView, query, disabled, callback }) => { @@ -53,10 +52,10 @@ export const FullTimeRangeSelector: FC = ({ dataView, query, disabled, ca } const [isPopoverOpen, setPopover] = useState(false); - const [frozenDataPreference, setFrozenDataPreference] = useStorage( - ML_FROZEN_TIER_PREFERENCE, - FROZEN_TIER_PREFERENCE.EXCLUDE - ); + const [frozenDataPreference, setFrozenDataPreference] = useStorage< + MlStorageKey, + TMlStorageMapped + >(ML_FROZEN_TIER_PREFERENCE, FROZEN_TIER_PREFERENCE.EXCLUDE); const onButtonClick = () => { setPopover(!isPopoverOpen); diff --git a/x-pack/plugins/ml/public/application/components/job_selector/job_selector.tsx b/x-pack/plugins/ml/public/application/components/job_selector/job_selector.tsx index 9c49099c45946..fa2808638cbf5 100644 --- a/x-pack/plugins/ml/public/application/components/job_selector/job_selector.tsx +++ b/x-pack/plugins/ml/public/application/components/job_selector/job_selector.tsx @@ -19,6 +19,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { useUrlState } from '@kbn/ml-url-state'; import './_index.scss'; +import { useStorage } from '@kbn/ml-local-storage'; import { Dictionary } from '../../../../common/types/common'; import { IdBadges } from './id_badges'; import { @@ -27,7 +28,6 @@ import { JobSelectorFlyoutProps, } from './job_selector_flyout'; import { MlJobWithTimeRange } from '../../../../common/types/anomaly_detection_jobs'; -import { useStorage } from '../../contexts/storage'; import { ML_APPLY_TIME_RANGE_CONFIG } from '../../../../common/types/storage'; interface GroupObj { diff --git a/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx b/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx index dd24789462cf7..ad6c05d07d4e1 100644 --- a/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx +++ b/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx @@ -8,7 +8,7 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { of, throwError } from 'rxjs'; import { useMlNotifications, MlNotificationsContextProvider } from './ml_notifications_context'; -import { useStorage } from '../storage'; +import { useStorage } from '@kbn/ml-local-storage'; import { useMlKibana } from '../kibana'; const mockCountMessages = jest.fn(() => { @@ -43,7 +43,7 @@ jest.mock('../kibana', () => ({ })); const mockSetStorageValue = jest.fn(); -jest.mock('../storage', () => ({ +jest.mock('@kbn/ml-local-storage', () => ({ useStorage: jest.fn(() => { return [undefined, mockSetStorageValue]; }), diff --git a/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.tsx b/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.tsx index 74b0a1ad54cb8..67e479f1291f5 100644 --- a/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.tsx +++ b/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.tsx @@ -10,9 +10,13 @@ import { combineLatest, timer } from 'rxjs'; import { switchMap, map, tap, retry } from 'rxjs/operators'; import moment from 'moment'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; +import { useStorage } from '@kbn/ml-local-storage'; import { useMlKibana } from '../kibana'; -import { useStorage } from '../storage'; -import { ML_NOTIFICATIONS_LAST_CHECKED_AT } from '../../../../common/types/storage'; +import { + ML_NOTIFICATIONS_LAST_CHECKED_AT, + type MlStorageKey, + type TMlStorageMapped, +} from '../../../../common/types/storage'; import { useAsObservable } from '../../hooks'; import type { NotificationsCountResponse } from '../../../../common/types/notifications'; @@ -47,7 +51,10 @@ export const MlNotificationsContextProvider: FC = ({ children }) => { const canGetNotifications = canGetJobs && canGetDataFrameAnalytics && canGetTrainedModels; - const [lastCheckedAt, setLastCheckedAt] = useStorage(ML_NOTIFICATIONS_LAST_CHECKED_AT); + const [lastCheckedAt, setLastCheckedAt] = useStorage< + MlStorageKey, + TMlStorageMapped + >(ML_NOTIFICATIONS_LAST_CHECKED_AT); const lastCheckedAt$ = useAsObservable(lastCheckedAt); /** Holds the value used for the actual request */ diff --git a/x-pack/plugins/ml/public/application/contexts/storage/storage_context.tsx b/x-pack/plugins/ml/public/application/contexts/storage/storage_context.tsx deleted file mode 100644 index 65e2a64ee3181..0000000000000 --- a/x-pack/plugins/ml/public/application/contexts/storage/storage_context.tsx +++ /dev/null @@ -1,140 +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, { FC, useEffect, useMemo, useCallback, useState, useContext } from 'react'; -import { omit } from 'lodash'; -import { isDefined } from '../../../../common/types/guards'; -import { useMlKibana } from '../kibana'; -import { MlStorage, ML_STORAGE_KEYS, isMlStorageKey } from '../../../../common/types/storage'; -import { MlStorageKey, TMlStorageMapped } from '../../../../common/types/storage'; - -interface StorageAPI { - value: MlStorage; - setValue: >(key: K, value: T) => void; - removeValue: (key: K) => void; -} - -export const MlStorageContext = React.createContext({ - value: null, - setValue() { - throw new Error('MlStorageContext set method is not implemented'); - }, - removeValue() { - throw new Error('MlStorageContext remove method is not implemented'); - }, -}); - -export const MlStorageContextProvider: FC = ({ children }) => { - const { - services: { storage }, - } = useMlKibana(); - - const initialValue = useMemo(() => { - return ML_STORAGE_KEYS.reduce((acc, curr) => { - acc[curr as MlStorageKey] = storage.get(curr); - return acc; - }, {} as Exclude); - }, [storage]); - - const [state, setState] = useState(initialValue); - - const setStorageValue = useCallback( - >(key: K, value: T) => { - storage.set(key, value); - - setState((prevState) => ({ - ...prevState, - [key]: value, - })); - }, - [storage] - ); - - const removeStorageValue = useCallback( - (key: MlStorageKey) => { - storage.remove(key); - setState((prevState) => omit(prevState, key)); - }, - [storage] - ); - - useEffect(function updateStorageOnExternalChange() { - const eventListener = (event: StorageEvent) => { - if (!isMlStorageKey(event.key)) return; - - if (isDefined(event.newValue)) { - setState((prev) => { - return { - ...prev, - [event.key as MlStorageKey]: - typeof event.newValue === 'string' ? JSON.parse(event.newValue) : event.newValue, - }; - }); - } else { - setState((prev) => { - return omit(prev, event.key as MlStorageKey); - }); - } - }; - - /** - * This event listener is only invoked when - * the change happens in another browser's tab. - */ - window.addEventListener('storage', eventListener); - - return () => { - window.removeEventListener('storage', eventListener); - }; - }, []); - - const value: StorageAPI = useMemo(() => { - return { - value: state, - setValue: setStorageValue, - removeValue: removeStorageValue, - }; - }, [state, setStorageValue, removeStorageValue]); - - return {children}; -}; - -/** - * Hook for consuming a storage value - * @param key - * @param initValue - */ -export function useStorage>( - key: K, - initValue?: T -): [ - typeof initValue extends undefined - ? TMlStorageMapped | undefined - : Exclude, undefined>, - (value: TMlStorageMapped) => void -] { - const { value, setValue, removeValue } = useContext(MlStorageContext); - - const resultValue = useMemo(() => { - return (value?.[key] ?? initValue) as typeof initValue extends undefined - ? TMlStorageMapped | undefined - : Exclude, undefined>; - }, [value, key, initValue]); - - const setVal = useCallback( - (v: TMlStorageMapped) => { - if (isDefined(v)) { - setValue(key, v); - } else { - removeValue(key); - } - }, - [setValue, removeValue, key] - ); - - return [resultValue, setVal]; -} diff --git a/x-pack/plugins/ml/public/application/explorer/anomalies_map.tsx b/x-pack/plugins/ml/public/application/explorer/anomalies_map.tsx index b9a1ef555dbc1..3edfcd9842a18 100644 --- a/x-pack/plugins/ml/public/application/explorer/anomalies_map.tsx +++ b/x-pack/plugins/ml/public/application/explorer/anomalies_map.tsx @@ -25,8 +25,8 @@ import { VectorLayerDescriptor, } from '@kbn/maps-plugin/common'; import { EMSTermJoinConfig } from '@kbn/maps-plugin/public'; +import { isDefined } from '@kbn/ml-is-defined'; import { useMlKibana } from '../contexts/kibana'; -import { isDefined } from '../../../common/types/guards'; import { MlEmbeddedMapComponent } from '../components/ml_embedded_map'; import { AnomaliesTableRecord } from '../../../common/types/anomalies'; diff --git a/x-pack/plugins/ml/public/application/explorer/anomaly_context_menu.tsx b/x-pack/plugins/ml/public/application/explorer/anomaly_context_menu.tsx index 2bfe0c3b2844e..55feffe8ff5c4 100644 --- a/x-pack/plugins/ml/public/application/explorer/anomaly_context_menu.tsx +++ b/x-pack/plugins/ml/public/application/explorer/anomaly_context_menu.tsx @@ -19,7 +19,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import useObservable from 'react-use/lib/useObservable'; import type { Query, TimeRange } from '@kbn/es-query'; -import { isDefined } from '../../../common/types/guards'; +import { isDefined } from '@kbn/ml-is-defined'; import { useAnomalyExplorerContext } from './anomaly_explorer_context'; import { escapeKueryForFieldValuePair } from '../util/string_utils'; import { SEARCH_QUERY_LANGUAGE } from '../../../common/constants/search'; diff --git a/x-pack/plugins/ml/public/application/explorer/anomaly_timeline.tsx b/x-pack/plugins/ml/public/application/explorer/anomaly_timeline.tsx index 6b33ba8187d9d..a0ff293a2b203 100644 --- a/x-pack/plugins/ml/public/application/explorer/anomaly_timeline.tsx +++ b/x-pack/plugins/ml/public/application/explorer/anomaly_timeline.tsx @@ -27,6 +27,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import useDebounce from 'react-use/lib/useDebounce'; import useObservable from 'react-use/lib/useObservable'; import type { Query } from '@kbn/es-query'; +import { isDefined } from '@kbn/ml-is-defined'; import { SEARCH_QUERY_LANGUAGE } from '../../../common/constants/search'; import { useCasesModal } from '../contexts/kibana/use_cases_modal'; import { useTimeRangeUpdates } from '../contexts/kibana/use_timefilter'; @@ -46,7 +47,6 @@ import { AppStateSelectedCells, OverallSwimlaneData, ViewBySwimLaneData } from ' import { NoOverallData } from './components/no_overall_data'; import { SeverityControl } from '../components/severity_control'; import { AnomalyTimelineHelpPopover } from './anomaly_timeline_help_popover'; -import { isDefined } from '../../../common/types/guards'; import { MlTooltipComponent } from '../components/chart_tooltip'; import { SwimlaneAnnotationContainer, Y_AXIS_LABEL_WIDTH } from './swimlane_annotation_container'; import { AnomalyTimelineService } from '../services/anomaly_timeline_service'; diff --git a/x-pack/plugins/ml/public/application/explorer/dashboard_controls/add_anomaly_charts_to_dashboard_controls.tsx b/x-pack/plugins/ml/public/application/explorer/dashboard_controls/add_anomaly_charts_to_dashboard_controls.tsx index 0e928166127fd..cb5d6d2b0201b 100644 --- a/x-pack/plugins/ml/public/application/explorer/dashboard_controls/add_anomaly_charts_to_dashboard_controls.tsx +++ b/x-pack/plugins/ml/public/application/explorer/dashboard_controls/add_anomaly_charts_to_dashboard_controls.tsx @@ -9,8 +9,8 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { EuiFieldNumber, EuiFormRow, htmlIdGenerator } from '@elastic/eui'; import type { Query } from '@kbn/es-query'; import useObservable from 'react-use/lib/useObservable'; +import { isDefined } from '@kbn/ml-is-defined'; import { getSelectionInfluencers } from '../explorer_utils'; -import { isDefined } from '../../../../common/types/guards'; import { useAnomalyExplorerContext } from '../anomaly_explorer_context'; import { escapeKueryForFieldValuePair } from '../../util/string_utils'; import { SEARCH_QUERY_LANGUAGE } from '../../../../common/constants/search'; diff --git a/x-pack/plugins/ml/public/application/explorer/explorer.tsx b/x-pack/plugins/ml/public/application/explorer/explorer.tsx index 6e224b25f506f..f764ede7750c9 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer.tsx +++ b/x-pack/plugins/ml/public/application/explorer/explorer.tsx @@ -31,6 +31,8 @@ import { css } from '@emotion/react'; import useObservable from 'react-use/lib/useObservable'; import type { DataView } from '@kbn/data-views-plugin/common'; import type { TimefilterContract } from '@kbn/data-plugin/public'; +import { useStorage } from '@kbn/ml-local-storage'; +import { isDefined } from '@kbn/ml-is-defined'; import { HelpPopover } from '../components/help_popover'; import { AnnotationFlyout } from '../components/annotations/annotation_flyout'; // @ts-ignore @@ -69,7 +71,6 @@ import { AnomaliesTable } from '../components/anomalies_table/anomalies_table'; import { AnomaliesMap } from './anomalies_map'; import { ANOMALY_DETECTION_DEFAULT_TIME_RANGE } from '../../../common/constants/settings'; import { AnomalyContextMenu } from './anomaly_context_menu'; -import { isDefined } from '../../../common/types/guards'; import type { JobSelectorProps } from '../components/job_selector/job_selector'; import type { ExplorerState } from './reducers'; import type { TimeBuckets } from '../util/time_buckets'; @@ -78,7 +79,6 @@ import { useMlKibana, useMlLocator } from '../contexts/kibana'; import { useMlContext } from '../contexts/ml'; import { useAnomalyExplorerContext } from './anomaly_explorer_context'; import { ML_ANOMALY_EXPLORER_PANELS } from '../../../common/types/storage'; -import { useStorage } from '../contexts/storage'; interface ExplorerPageProps { jobSelectorProps: JobSelectorProps; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/geo_view/settings.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/geo_view/settings.tsx index d5ad0488cec2f..0693a85d20cec 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/geo_view/settings.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/geo_view/settings.tsx @@ -29,7 +29,7 @@ export const GeoSettings: FC = ({ setIsValid }) => { - + diff --git a/x-pack/plugins/ml/public/application/overview/components/getting_started_callout.tsx b/x-pack/plugins/ml/public/application/overview/components/getting_started_callout.tsx index 7b1f380c90658..d7a0370b4aeac 100644 --- a/x-pack/plugins/ml/public/application/overview/components/getting_started_callout.tsx +++ b/x-pack/plugins/ml/public/application/overview/components/getting_started_callout.tsx @@ -8,8 +8,8 @@ import React, { FC } from 'react'; import { EuiButton, EuiCallOut, EuiLink, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; +import { useStorage } from '@kbn/ml-local-storage'; import { useMlKibana } from '../../contexts/kibana'; -import { useStorage } from '../../contexts/storage'; import { ML_GETTING_STARTED_CALLOUT_DISMISSED } from '../../../../common/types/storage'; const feedbackLink = 'https://www.elastic.co/community/'; diff --git a/x-pack/plugins/ml/public/application/services/anomaly_explorer_charts_service.ts b/x-pack/plugins/ml/public/application/services/anomaly_explorer_charts_service.ts index 7aa0bb03611e1..6a0f3c8c692b0 100644 --- a/x-pack/plugins/ml/public/application/services/anomaly_explorer_charts_service.ts +++ b/x-pack/plugins/ml/public/application/services/anomaly_explorer_charts_service.ts @@ -10,6 +10,7 @@ import { map as mapObservable } from 'rxjs/operators'; import type { TimeRange } from '@kbn/es-query'; import type { TimefilterContract } from '@kbn/data-plugin/public'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; +import { isDefined } from '@kbn/ml-is-defined'; import type { RecordForInfluencer } from './results_service/results_service'; import type { EntityField } from '../../../common/util/anomaly_utils'; import type { CombinedJob } from '../../../common/types/anomaly_detection_jobs'; @@ -17,7 +18,6 @@ import type { MlApiServices } from './ml_api_service'; import type { MlResultsService } from './results_service'; import { ExplorerChartsData } from '../explorer/explorer_charts/explorer_charts_container_service'; import type { TimeRangeBounds } from '../util/time_buckets'; -import { isDefined } from '../../../common/types/guards'; import type { AppStateSelectedCells } from '../explorer/explorer_utils'; import type { InfluencersFilterQuery } from '../../../common/types/es_client'; import type { SeriesConfigWithMetadata } from '../../../common/types/results'; diff --git a/x-pack/plugins/ml/public/application/services/ml_api_service/notifications.ts b/x-pack/plugins/ml/public/application/services/ml_api_service/notifications.ts index 653ceebc52cda..fd6f7bd708cd4 100644 --- a/x-pack/plugins/ml/public/application/services/ml_api_service/notifications.ts +++ b/x-pack/plugins/ml/public/application/services/ml_api_service/notifications.ts @@ -6,7 +6,7 @@ */ import { omitBy } from 'lodash'; -import { isDefined } from '../../../../common/types/guards'; +import { isDefined } from '@kbn/ml-is-defined'; import type { NotificationsQueryParams, NotificationsSearchResponse, diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/series_controls/series_controls.tsx b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/series_controls/series_controls.tsx index 23084c8d8886d..8d79a41b0ab36 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/series_controls/series_controls.tsx +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/series_controls/series_controls.tsx @@ -10,6 +10,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiSelect, EuiSelectProps } from '@elastic/eui'; import { debounce } from 'lodash'; import { lastValueFrom } from 'rxjs'; +import { useStorage } from '@kbn/ml-local-storage'; import { EntityControl } from '../entity_control'; import { mlJobService } from '../../../services/job_service'; import { Detector, JobId } from '../../../../../common/types/anomaly_detection_jobs'; @@ -23,10 +24,11 @@ import { import { getControlsForDetector } from '../../get_controls_for_detector'; import { ML_ENTITY_FIELDS_CONFIG, - PartitionFieldConfig, - PartitionFieldsConfig, + type PartitionFieldConfig, + type PartitionFieldsConfig, + type MlStorageKey, + type TMlStorageMapped, } from '../../../../../common/types/storage'; -import { useStorage } from '../../../contexts/storage'; import { EntityFieldType } from '../../../../../common/types/anomalies'; import { FieldDefinition } from '../../../services/results_service/result_service_rx'; import { getViewableDetectors } from '../../timeseriesexplorer_utils/get_viewable_detectors'; @@ -113,7 +115,10 @@ export const SeriesControls: FC = ({ return getControlsForDetector(selectedDetectorIndex, selectedEntities, selectedJobId); }, [selectedDetectorIndex, selectedEntities, selectedJobId]); - const [storageFieldsConfig, setStorageFieldsConfig] = useStorage(ML_ENTITY_FIELDS_CONFIG); + const [storageFieldsConfig, setStorageFieldsConfig] = useStorage< + MlStorageKey, + TMlStorageMapped + >(ML_ENTITY_FIELDS_CONFIG); // Merge the default config with the one from the local storage const resultFieldsConfig = useMemo(() => { diff --git a/x-pack/plugins/ml/public/application/trained_models/models_management/expanded_row.tsx b/x-pack/plugins/ml/public/application/trained_models/models_management/expanded_row.tsx index 879bed447c864..daa813fe4e1e6 100644 --- a/x-pack/plugins/ml/public/application/trained_models/models_management/expanded_row.tsx +++ b/x-pack/plugins/ml/public/application/trained_models/models_management/expanded_row.tsx @@ -24,8 +24,8 @@ import { import { FormattedMessage } from '@kbn/i18n-react'; import { FIELD_FORMAT_IDS } from '@kbn/field-formats-plugin/common'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; +import { isDefined } from '@kbn/ml-is-defined'; import type { ModelItemFull } from './models_list'; -import { isDefined } from '../../../../common/types/guards'; import { ModelPipelines } from './pipelines'; import { AllocatedModels } from '../nodes_overview/allocated_models'; import type { AllocatedModel } from '../../../../common/types/trained_models'; diff --git a/x-pack/plugins/ml/public/application/util/string_utils.ts b/x-pack/plugins/ml/public/application/util/string_utils.ts index b870cdff345b5..e1fa570efc20c 100644 --- a/x-pack/plugins/ml/public/application/util/string_utils.ts +++ b/x-pack/plugins/ml/public/application/util/string_utils.ts @@ -12,7 +12,7 @@ import d3 from 'd3'; import he from 'he'; import { escapeKuery } from '@kbn/es-query'; -import { isDefined } from '../../../common/types/guards'; +import { isDefined } from '@kbn/ml-is-defined'; import { CustomUrlAnomalyRecordDoc } from '../../../common/types/custom_urls'; import { Detector } from '../../../common/types/anomaly_detection_jobs'; diff --git a/x-pack/plugins/ml/server/lib/alerts/alerting_service.ts b/x-pack/plugins/ml/server/lib/alerts/alerting_service.ts index 45eef7f63226a..36182956b7388 100644 --- a/x-pack/plugins/ml/server/lib/alerts/alerting_service.ts +++ b/x-pack/plugins/ml/server/lib/alerts/alerting_service.ts @@ -15,6 +15,7 @@ import { IFieldFormat, SerializedFieldFormat, } from '@kbn/field-formats-plugin/common'; +import { isDefined } from '@kbn/ml-is-defined'; import { MlClient } from '../ml_client'; import { MlAnomalyDetectionAlertParams, @@ -32,7 +33,6 @@ import { } from '../../../common/types/alerts'; import { AnomalyDetectionAlertContext } from './register_anomaly_detection_alert_type'; import { resolveMaxTimeInterval } from '../../../common/util/job_utils'; -import { isDefined } from '../../../common/types/guards'; import { getTopNBuckets, resolveLookbackInterval } from '../../../common/util/alerts'; import type { DatafeedsService } from '../../models/job_service/datafeeds'; import { getEntityFieldName, getEntityFieldValue } from '../../../common/util/anomaly_utils'; diff --git a/x-pack/plugins/ml/server/lib/alerts/jobs_health_service.ts b/x-pack/plugins/ml/server/lib/alerts/jobs_health_service.ts index 4c19846794de1..a1ec1931485ac 100644 --- a/x-pack/plugins/ml/server/lib/alerts/jobs_health_service.ts +++ b/x-pack/plugins/ml/server/lib/alerts/jobs_health_service.ts @@ -9,6 +9,7 @@ import { groupBy, keyBy, memoize, partition } from 'lodash'; import { KibanaRequest, Logger, SavedObjectsClientContract } from '@kbn/core/server'; import { i18n } from '@kbn/i18n'; import { MlJob } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { isDefined } from '@kbn/ml-is-defined'; import { MlClient } from '../ml_client'; import { JobSelection } from '../../routes/schemas/alerting_schema'; import { datafeedsProvider, DatafeedsService } from '../../models/job_service/datafeeds'; @@ -30,7 +31,6 @@ import { import { AnnotationService } from '../../models/annotation_service/annotation'; import { annotationServiceProvider } from '../../models/annotation_service'; import { parseInterval } from '../../../common/util/parse_interval'; -import { isDefined } from '../../../common/types/guards'; import { jobAuditMessagesProvider, JobAuditMessagesService, diff --git a/x-pack/plugins/ml/server/models/data_frame_analytics/models_provider.ts b/x-pack/plugins/ml/server/models/data_frame_analytics/models_provider.ts index 1f6bb64fd76f4..ccb60e6379e48 100644 --- a/x-pack/plugins/ml/server/models/data_frame_analytics/models_provider.ts +++ b/x-pack/plugins/ml/server/models/data_frame_analytics/models_provider.ts @@ -11,6 +11,7 @@ import { MlTrainedModelStats, NodesInfoNodeInfo, } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { isDefined } from '@kbn/ml-is-defined'; import type { NodeDeploymentStatsResponse, PipelineDefinition, @@ -21,7 +22,6 @@ import { TrainedModelDeploymentStatsResponse, TrainedModelModelSizeStats, } from '../../../common/types/trained_models'; -import { isDefined } from '../../../common/types/guards'; export type ModelService = ReturnType; diff --git a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts index 136722f4ab5b1..e9b92c2f01e6c 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts +++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts @@ -18,6 +18,7 @@ import moment from 'moment'; import { merge } from 'lodash'; import type { DataViewsService } from '@kbn/data-views-plugin/common'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; +import { isDefined } from '@kbn/ml-is-defined'; import type { AnalysisLimits } from '../../../common/types/anomaly_detection_jobs'; import { getAuthorizationHeader } from '../../lib/request_authorization'; import type { MlClient } from '../../lib/ml_client'; @@ -54,7 +55,6 @@ import { resultsServiceProvider } from '../results_service'; import type { JobExistResult, JobStat } from '../../../common/types/data_recognizer'; import type { Datafeed } from '../../../common/types/anomaly_detection_jobs'; import type { MLSavedObjectService } from '../../saved_objects'; -import { isDefined } from '../../../common/types/guards'; const ML_DIR = 'ml'; const KIBANA_DIR = 'kibana'; diff --git a/x-pack/plugins/ml/server/models/results_service/anomaly_charts.ts b/x-pack/plugins/ml/server/models/results_service/anomaly_charts.ts index dbbf95d4806c2..bcce2455539f7 100644 --- a/x-pack/plugins/ml/server/models/results_service/anomaly_charts.ts +++ b/x-pack/plugins/ml/server/models/results_service/anomaly_charts.ts @@ -11,6 +11,7 @@ import { each, find, get, keyBy, map, reduce, sortBy } from 'lodash'; import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { extent, max, min } from 'd3'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; +import { isDefined } from '@kbn/ml-is-defined'; import type { MlClient } from '../../lib/ml_client'; import { isRuntimeMappings } from '../../../common'; import type { @@ -40,7 +41,6 @@ import { isMultiBucketAnomaly, } from '../../../common/util/anomaly_utils'; import { InfluencersFilterQuery } from '../../../common/types/es_client'; -import { isDefined } from '../../../common/types/guards'; import { AnomalyRecordDoc, CombinedJob, Datafeed, RecordForInfluencer } from '../../shared'; import { ES_AGGREGATION, ML_JOB_AGGREGATION } from '../../../common/constants/aggregation_types'; import { parseInterval } from '../../../common/util/parse_interval'; diff --git a/x-pack/plugins/ml/tsconfig.json b/x-pack/plugins/ml/tsconfig.json index d5d42f865e2c0..2b99e5d22616a 100644 --- a/x-pack/plugins/ml/tsconfig.json +++ b/x-pack/plugins/ml/tsconfig.json @@ -68,6 +68,8 @@ "@kbn/repo-info", "@kbn/ml-url-state", "@kbn/ml-nested-property", + "@kbn/ml-local-storage", + "@kbn/ml-is-defined", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/observability/common/index.ts b/x-pack/plugins/observability/common/index.ts index 86104ab47c07a..63efd8494dbf8 100644 --- a/x-pack/plugins/observability/common/index.ts +++ b/x-pack/plugins/observability/common/index.ts @@ -8,6 +8,7 @@ export type { AsDuration, AsPercent, TimeUnitChar } from './utils/formatters'; export { formatDurationFromTimeUnitChar } from './utils/formatters'; +export { getInspectResponse } from './utils/get_inspect_response'; export { ProcessorEvent } from './processor_event'; diff --git a/x-pack/plugins/observability/e2e/synthetics_runner.ts b/x-pack/plugins/observability/e2e/synthetics_runner.ts index 51ca09abfadfc..cb824fadf256f 100644 --- a/x-pack/plugins/observability/e2e/synthetics_runner.ts +++ b/x-pack/plugins/observability/e2e/synthetics_runner.ts @@ -12,6 +12,7 @@ import { run as syntheticsRun } from '@elastic/synthetics'; import { PromiseType } from 'utility-types'; import { createApmUsers } from '@kbn/apm-plugin/server/test_helpers/create_apm_users/create_apm_users'; +import { EsArchiver } from '@kbn/es-archiver'; import { esArchiverUnload } from './tasks/es_archiver'; import { TestReporter } from './test_reporter'; @@ -59,9 +60,17 @@ export class SyntheticsRunner { try { console.log('Loading esArchiver...'); - const esArchiver = this.getService('esArchiver'); - - const promises = dataArchives.map((archive) => esArchiver.loadIfNeeded(e2eDir + archive)); + const esArchiver: EsArchiver = this.getService('esArchiver'); + + const promises = dataArchives.map((archive) => { + if (archive === 'synthetics_data') { + return esArchiver.load(e2eDir + archive, { + docsOnly: true, + skipExisting: true, + }); + } + return esArchiver.load(e2eDir + archive, { skipExisting: true }); + }); await Promise.all([...promises]); } catch (e) { diff --git a/x-pack/plugins/observability/e2e/test_reporter.ts b/x-pack/plugins/observability/e2e/test_reporter.ts index 85f007d0867aa..be4b04190f8a1 100644 --- a/x-pack/plugins/observability/e2e/test_reporter.ts +++ b/x-pack/plugins/observability/e2e/test_reporter.ts @@ -135,7 +135,12 @@ export class TestReporter implements Reporter { ); successfulJourneys.forEach(([journeyName, steps]) => { - // fs.unlinkSync('.journeys/videos/' + journeyName + '.webm'); + try { + fs.unlinkSync('.journeys/videos/' + journeyName + '.webm'); + } catch (e) { + // eslint-disable-next-line no-console + console.log(e); + } }); const { failed, succeeded, skipped } = this.metrics; diff --git a/x-pack/plugins/observability/e2e/tsconfig.json b/x-pack/plugins/observability/e2e/tsconfig.json index b6b7f0d2c6808..1488f5f3b5b55 100644 --- a/x-pack/plugins/observability/e2e/tsconfig.json +++ b/x-pack/plugins/observability/e2e/tsconfig.json @@ -9,5 +9,6 @@ "kbn_references": [ "@kbn/apm-plugin", "@kbn/test", + "@kbn/es-archiver", ] } diff --git a/x-pack/plugins/observability/public/hooks/use_es_search.ts b/x-pack/plugins/observability/public/hooks/use_es_search.ts index b25feef4d3f54..d99a7e80781c0 100644 --- a/x-pack/plugins/observability/public/hooks/use_es_search.ts +++ b/x-pack/plugins/observability/public/hooks/use_es_search.ts @@ -105,7 +105,10 @@ export const useEsSearch = , loading }; + return { + data: rawResponse as ESSearchResponse, + loading: Boolean(loading), + }; }; export function createEsParams(params: T): T { diff --git a/x-pack/plugins/observability/public/pages/rule_details/helpers/get_alert_summary_time_range.test.tsx b/x-pack/plugins/observability/public/pages/rule_details/helpers/get_alert_summary_time_range.test.tsx index c8214d8d310bf..9c437f5f5da64 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/helpers/get_alert_summary_time_range.test.tsx +++ b/x-pack/plugins/observability/public/pages/rule_details/helpers/get_alert_summary_time_range.test.tsx @@ -6,11 +6,11 @@ */ import moment from 'moment'; -import { getDefaultAlertSummaryTimeRange } from '.'; +import { getAlertSummaryWidgetTimeRange } from '.'; describe('getDefaultAlertSummaryTimeRange', () => { it('should return default time in UTC format', () => { - const defaultTimeRange = getDefaultAlertSummaryTimeRange(); + const defaultTimeRange = getAlertSummaryWidgetTimeRange(); const utcFormat = 'YYYY-MM-DDTHH:mm:ss.SSSZ'; expect(moment(defaultTimeRange.utcFrom, utcFormat, true).isValid()).toBeTruthy(); diff --git a/x-pack/plugins/observability/public/pages/rule_details/helpers/get_alert_summary_time_range.tsx b/x-pack/plugins/observability/public/pages/rule_details/helpers/get_alert_summary_time_range.tsx index dea999736fdfd..973bfc628ea60 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/helpers/get_alert_summary_time_range.tsx +++ b/x-pack/plugins/observability/public/pages/rule_details/helpers/get_alert_summary_time_range.tsx @@ -10,7 +10,7 @@ import React from 'react'; import { getAbsoluteTimeRange } from '@kbn/data-plugin/common'; import { FormattedMessage } from '@kbn/i18n-react'; -export const getDefaultAlertSummaryTimeRange = (): AlertSummaryTimeRange => { +export const getAlertSummaryWidgetTimeRange = (): AlertSummaryTimeRange => { const { to, from } = getAbsoluteTimeRange({ from: 'now-30d', to: 'now', diff --git a/x-pack/plugins/observability/public/pages/rule_details/helpers/index.ts b/x-pack/plugins/observability/public/pages/rule_details/helpers/index.ts index 711c088601a99..e93f2f4cc5ee0 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/helpers/index.ts +++ b/x-pack/plugins/observability/public/pages/rule_details/helpers/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { getDefaultAlertSummaryTimeRange } from './get_alert_summary_time_range'; +export { getAlertSummaryWidgetTimeRange } from './get_alert_summary_time_range'; diff --git a/x-pack/plugins/observability/public/pages/rule_details/index.tsx b/x-pack/plugins/observability/public/pages/rule_details/index.tsx index 7201e3882667c..420757b7b50bd 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/index.tsx +++ b/x-pack/plugins/observability/public/pages/rule_details/index.tsx @@ -42,7 +42,7 @@ import { fromQuery, toQuery } from '../../utils/url'; import { ObservabilityAlertSearchbarWithUrlSync } from '../../components/shared/alert_search_bar'; import { DeleteModalConfirmation } from './components/delete_modal_confirmation'; import { CenterJustifiedSpinner } from './components/center_justified_spinner'; -import { getDefaultAlertSummaryTimeRange } from './helpers'; +import { getAlertSummaryWidgetTimeRange } from './helpers'; import { EXECUTION_TAB, @@ -111,7 +111,9 @@ export function RuleDetailsPage() { const [editFlyoutVisible, setEditFlyoutVisible] = useState(false); const [isRuleEditPopoverOpen, setIsRuleEditPopoverOpen] = useState(false); const [esQuery, setEsQuery] = useState<{ bool: BoolQuery }>(); - const [defaultAlertTimeRange] = useState(getDefaultAlertSummaryTimeRange); + const [alertSummaryWidgetTimeRange, setAlertSummaryWidgetTimeRange] = useState( + getAlertSummaryWidgetTimeRange + ); const ruleQuery = useRef([ { query: `kibana.alert.rule.uuid: ${ruleId}`, language: 'kuery' }, ]); @@ -123,11 +125,15 @@ export function RuleDetailsPage() { const tabsRef = useRef(null); const onAlertSummaryWidgetClick = async (status: AlertStatus = ALERT_STATUS_ALL) => { + const timeRange = getAlertSummaryWidgetTimeRange(); + setAlertSummaryWidgetTimeRange(timeRange); await locators.get(ruleDetailsLocatorID)?.navigate( { + rangeFrom: timeRange.utcFrom, + rangeTo: timeRange.utcTo, ruleId, - tabId: ALERTS_TAB, status, + tabId: ALERTS_TAB, }, { replace: true, @@ -386,7 +392,7 @@ export function RuleDetailsPage() { diff --git a/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/executor.ts b/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/executor.ts index d22d1f9748504..38ac4e4eb32d6 100644 --- a/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/executor.ts +++ b/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/executor.ts @@ -58,8 +58,8 @@ export const getRuleExecutor = (): LifecycleRuleExecutor< ); const sliData = await sliClient.fetchSLIDataFrom(slo, [ - { name: LONG_WINDOW, duration: longWindowDuration }, - { name: SHORT_WINDOW, duration: shortWindowDuration }, + { name: LONG_WINDOW, duration: longWindowDuration.add(slo.settings.syncDelay) }, + { name: SHORT_WINDOW, duration: shortWindowDuration.add(slo.settings.syncDelay) }, ]); const longWindowBurnRate = computeBurnRate(slo, sliData[LONG_WINDOW]); diff --git a/x-pack/plugins/osquery/common/ecs/file/index.ts b/x-pack/plugins/osquery/common/ecs/file/index.ts index 5b8a269b7941e..6a69ea1b70ae5 100644 --- a/x-pack/plugins/osquery/common/ecs/file/index.ts +++ b/x-pack/plugins/osquery/common/ecs/file/index.ts @@ -10,7 +10,7 @@ export interface CodeSignature { trusted: string[]; } export interface Ext { - code_signature: CodeSignature[] | CodeSignature; + code_signature?: CodeSignature[] | CodeSignature; } export interface Hash { sha256: string[]; diff --git a/x-pack/plugins/osquery/common/ecs/rule/index.ts b/x-pack/plugins/osquery/common/ecs/rule/index.ts index 51d7722a3ecde..ae7e5064a8ece 100644 --- a/x-pack/plugins/osquery/common/ecs/rule/index.ts +++ b/x-pack/plugins/osquery/common/ecs/rule/index.ts @@ -9,7 +9,7 @@ export interface RuleEcs { id?: string[]; rule_id?: string[]; name?: string[]; - false_positives: string[]; + false_positives?: string[]; saved_id?: string[]; timeline_id?: string[]; timeline_title?: string[]; @@ -27,10 +27,7 @@ export interface RuleEcs { severity?: string[]; tags?: string[]; threat?: unknown; - threshold?: { - field: string | string[]; - value: number; - }; + threshold?: unknown; type?: string[]; size?: string[]; to?: string[]; diff --git a/x-pack/plugins/osquery/common/schemas/routes/live_query/create_live_query_request_body_schema.ts b/x-pack/plugins/osquery/common/schemas/routes/live_query/create_live_query_request_body_schema.ts index beb46aac98b58..462490fdbae96 100644 --- a/x-pack/plugins/osquery/common/schemas/routes/live_query/create_live_query_request_body_schema.ts +++ b/x-pack/plugins/osquery/common/schemas/routes/live_query/create_live_query_request_body_schema.ts @@ -12,7 +12,7 @@ import { savedQueryIdOrUndefined, packIdOrUndefined, queryOrUndefined, - queriesOrUndefined, + arrayQueries, } from '@kbn/osquery-io-ts-types'; export const createLiveQueryRequestBodySchema = t.partial({ @@ -21,7 +21,7 @@ export const createLiveQueryRequestBodySchema = t.partial({ agent_platforms: t.array(t.string), agent_policy_ids: t.array(t.string), query: queryOrUndefined, - queries: queriesOrUndefined, + queries: arrayQueries, saved_query_id: savedQueryIdOrUndefined, ecs_mapping: ecsMappingOrUndefined, pack_id: packIdOrUndefined, diff --git a/x-pack/plugins/osquery/common/utils/replace_params_query.test.ts b/x-pack/plugins/osquery/common/utils/replace_params_query.test.ts new file mode 100644 index 0000000000000..3a6a5416f2b97 --- /dev/null +++ b/x-pack/plugins/osquery/common/utils/replace_params_query.test.ts @@ -0,0 +1,85 @@ +/* + * 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 { replaceParamsQuery } from './replace_params_query'; + +describe('replaceParamsQuery', () => { + it('should return unchanged query, and skipped true', () => { + const query = 'SELECT * FROM processes WHERE version = {{params.version}}'; + const { result, skipped } = replaceParamsQuery(query, {}); + expect(result).toBe(query); + expect(skipped).toBe(true); + }); + it('should return proper value instead of params if field is found', () => { + const query = 'SELECT * FROM processes WHERE version = {{kibana.version}}'; + const { result, skipped } = replaceParamsQuery(query, { kibana: { version: '8.7.0' } }); + const expectedQuery = 'SELECT * FROM processes WHERE version = 8.7.0'; + expect(result).toBe(expectedQuery); + expect(skipped).toBe(false); + }); + it('should return proper value instead of params with multiple params', () => { + const query = + 'SELECT * FROM processes WHERE version = {{kibana.version}} and pid = {{kibana.pid}}'; + const { result, skipped } = replaceParamsQuery(query, { + kibana: { version: '8.7.0', pid: '123' }, + }); + const expectedQuery = 'SELECT * FROM processes WHERE version = 8.7.0 and pid = 123'; + expect(result).toBe(expectedQuery); + expect(skipped).toBe(false); + }); + it('should return proper value if param has white spaces inside', () => { + const query = 'SELECT * FROM processes WHERE version = {{ kibana.version }}'; + const { result, skipped } = replaceParamsQuery(query, { kibana: { version: '8.7.0' } }); + const expectedQuery = 'SELECT * FROM processes WHERE version = 8.7.0'; + expect(result).toBe(expectedQuery); + expect(skipped).toBe(false); + }); + + it('should not change query if there are no opening curly braces but still skipped false', () => { + const query = 'SELECT * FROM processes WHERE version = kibana.version }}'; + const { result, skipped } = replaceParamsQuery(query, { kibana: { version: '8.7.0' } }); + const expectedQuery = 'SELECT * FROM processes WHERE version = kibana.version }}'; + expect(result).toBe(expectedQuery); + expect(skipped).toBe(false); + }); + it('should return skipped true if {{params}} field not found', () => { + const query = + 'SELECT * FROM processes WHERE version = {{kibana.version}} {{not.existing}} {{agent.name}}'; + const { result, skipped } = replaceParamsQuery(query, { + kibana: { version: '8.7.0' }, + agent: { name: 'testAgent' }, + }); + const expectedQuery = + 'SELECT * FROM processes WHERE version = 8.7.0 {{not.existing}} testAgent'; + expect(result).toBe(expectedQuery); + expect(skipped).toBe(true); + }); + it('should return replaced values even if params are duplicated, but also return skip true', () => { + const query = + 'SELECT * FROM processes WHERE version = {{ kibana.version}} {{not.existing }} {{kibana.version}} {{kibana.version}} {{agent.name}}'; + const { result, skipped } = replaceParamsQuery(query, { + kibana: { version: '8.7.0' }, + agent: { name: 'testAgent' }, + }); + const expectedQuery = + 'SELECT * FROM processes WHERE version = 8.7.0 {{not.existing }} 8.7.0 8.7.0 testAgent'; + expect(result).toBe(expectedQuery); + expect(skipped).toBe(true); + }); + + it('handle complex windows query with registry as param', () => { + // eslint-disable-next-line no-useless-escape + const query = `select * FROM registry WHERE key LIKE 'HKEY_USERS\{{user.id}}\Software\Microsoft\IdentityCRL\Immersive\production\Token\{0CB4A94A-6E8C-477B-88C8-A3799FC97414}'`; + const { result, skipped } = replaceParamsQuery(query, { + user: { id: 'S-1-5-20' }, + }); + // eslint-disable-next-line no-useless-escape + const expectedQuery = `select * FROM registry WHERE key LIKE 'HKEY_USERS\S-1-5-20\Software\Microsoft\IdentityCRL\Immersive\production\Token\{0CB4A94A-6E8C-477B-88C8-A3799FC97414}'`; + expect(result).toBe(expectedQuery); + expect(skipped).toBe(false); + }); +}); diff --git a/x-pack/plugins/osquery/common/utils/replace_params_query.ts b/x-pack/plugins/osquery/common/utils/replace_params_query.ts new file mode 100644 index 0000000000000..2f7df42e6a3b1 --- /dev/null +++ b/x-pack/plugins/osquery/common/utils/replace_params_query.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 { each, get } from 'lodash'; + +export const replaceParamsQuery = (query: string, data: object) => { + const regex = /\{{([^}]+)\}}/g; // when there are 2 opening and 2 closing curly brackets (including brackets) + const matchedBrackets = query.match(regex); + let resultQuery = query; + + if (matchedBrackets) { + each(matchedBrackets, (bracesText: string) => { + const field = bracesText.replace(/{{|}}/g, '').trim(); + if (resultQuery.includes(bracesText)) { + const foundFieldValue = get(data, field); + if (foundFieldValue) { + resultQuery = resultQuery.replace(bracesText, foundFieldValue); + } + } + }); + } + + const skipped = regex.test(resultQuery); + + return { + result: resultQuery, + skipped, + }; +}; diff --git a/x-pack/plugins/osquery/cypress/e2e/all/alerts.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/alerts.cy.ts index 3c52f70b6d491..d098c2bc57fb2 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/alerts.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/alerts.cy.ts @@ -10,6 +10,7 @@ import { RESPONSE_ACTIONS_ITEM_1, RESPONSE_ACTIONS_ITEM_2, OSQUERY_RESPONSE_ACTION_ADD_BUTTON, + RESPONSE_ACTIONS_ITEM_3, } from '../../tasks/response_actions'; import { ArchiverMethod, runKbnArchiverScript } from '../../tasks/archiver'; import { login } from '../../tasks/login'; @@ -34,6 +35,7 @@ describe('Alert Event Details', () => { runKbnArchiverScript(ArchiverMethod.LOAD, 'example_pack'); runKbnArchiverScript(ArchiverMethod.LOAD, 'rule'); }); + beforeEach(() => { login(ROLES.soc_manager); }); @@ -196,6 +198,40 @@ describe('Alert Event Details', () => { }); }); + it('should be able to add investigation guides to response actions', () => { + const investigationGuideNote = + 'It seems that you have suggested queries in investigation guide, would you like to add them as response actions?'; + cy.visit('/app/security/rules'); + cy.contains(RULE_NAME).click(); + cy.contains('Edit rule settings').click(); + cy.getBySel('edit-rule-actions-tab').wait(500).click(); + + cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { + cy.contains('Example'); + }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { + cy.contains('select * from uptime'); + }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_2).should('not.exist'); + cy.getBySel(RESPONSE_ACTIONS_ITEM_3).should('not.exist'); + cy.contains(investigationGuideNote); + cy.getBySel('osqueryAddInvestigationGuideQueries').click(); + cy.contains(investigationGuideNote).should('not.exist'); + + cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { + cy.contains('Example'); + }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { + cy.contains('select * from uptime'); + }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_2).within(() => { + cy.contains('SELECT * FROM processes;'); + }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_3).within(() => { + cy.contains('select * from users'); + }); + }); + it('should be able to run live query and add to timeline (-depending on the previous test)', () => { const TIMELINE_NAME = 'Untitled timeline'; cy.visit('/app/security/alerts'); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/edit_saved_queries.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/edit_saved_queries.cy.ts index 7551176853f5e..4453132dccd5e 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/edit_saved_queries.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/edit_saved_queries.cy.ts @@ -32,31 +32,35 @@ describe('ALL - Edit saved query', () => { }).click(); cy.contains('Custom key/value pairs.').should('exist'); cy.contains('Hours of uptime').should('exist'); - cy.get('[data-test-subj="ECSMappingEditorForm"]').within(() => { - cy.react('EuiButtonIcon', { props: { iconType: 'trash' } }).click(); - }); + cy.get('[data-test-subj="ECSMappingEditorForm"]') + .first() + .within(() => { + cy.react('EuiButtonIcon', { props: { iconType: 'trash' } }).click(); + }); - cy.react('PlatformCheckBoxGroupField').within(() => { - cy.react('EuiCheckbox', { - props: { - id: 'linux', - checked: true, - }, - }).should('exist'); - cy.react('EuiCheckbox', { - props: { - id: 'darwin', - checked: true, - }, - }).should('exist'); + cy.react('PlatformCheckBoxGroupField') + .first() + .within(() => { + cy.react('EuiCheckbox', { + props: { + id: 'linux', + checked: true, + }, + }).should('exist'); + cy.react('EuiCheckbox', { + props: { + id: 'darwin', + checked: true, + }, + }).should('exist'); - cy.react('EuiCheckbox', { - props: { - id: 'windows', - checked: false, - }, - }).should('exist'); - }); + cy.react('EuiCheckbox', { + props: { + id: 'windows', + checked: false, + }, + }).should('exist'); + }); cy.get('#windows').check({ force: true }); @@ -70,26 +74,28 @@ describe('ALL - Edit saved query', () => { cy.contains('Custom key/value pairs').should('not.exist'); cy.contains('Hours of uptime').should('not.exist'); - cy.react('PlatformCheckBoxGroupField').within(() => { - cy.react('EuiCheckbox', { - props: { - id: 'linux', - checked: true, - }, - }).should('exist'); - cy.react('EuiCheckbox', { - props: { - id: 'darwin', - checked: true, - }, - }).should('exist'); + cy.react('PlatformCheckBoxGroupField') + .first() + .within(() => { + cy.react('EuiCheckbox', { + props: { + id: 'linux', + checked: true, + }, + }).should('exist'); + cy.react('EuiCheckbox', { + props: { + id: 'darwin', + checked: true, + }, + }).should('exist'); - cy.react('EuiCheckbox', { - props: { - id: 'windows', - checked: true, - }, - }).should('exist'); - }); + cy.react('EuiCheckbox', { + props: { + id: 'windows', + checked: true, + }, + }).should('exist'); + }); }); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/roles/t2_analyst.cy.ts b/x-pack/plugins/osquery/cypress/e2e/roles/t2_analyst.cy.ts index 6f2ba0a26882f..7c468a679404d 100644 --- a/x-pack/plugins/osquery/cypress/e2e/roles/t2_analyst.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/roles/t2_analyst.cy.ts @@ -24,13 +24,14 @@ describe('T2 Analyst - READ + Write Live/Saved + runSavedQueries ', () => { // // const NEW_SAVED_QUERY_ID = `Saved-Query-Id-${randomNumber}`; // const NEW_SAVED_QUERY_DESCRIPTION = `Test saved query description ${randomNumber}`; + before(() => { + runKbnArchiverScript(ArchiverMethod.LOAD, 'saved_query'); + }); + beforeEach(() => { login(ROLES.t2_analyst); navigateTo('/app/osquery'); }); - before(() => { - runKbnArchiverScript(ArchiverMethod.LOAD, 'saved_query'); - }); after(() => { runKbnArchiverScript(ArchiverMethod.UNLOAD, 'saved_query'); @@ -100,6 +101,7 @@ describe('T2 Analyst - READ + Write Live/Saved + runSavedQueries ', () => { }); }); }); + it('to click the edit button and edit pack', () => { navigateTo('/app/osquery/saved_queries'); cy.getBySel('pagination-button-next').click(); @@ -109,9 +111,11 @@ describe('T2 Analyst - READ + Write Live/Saved + runSavedQueries ', () => { }).click(); cy.contains('Custom key/value pairs.').should('exist'); cy.contains('Hours of uptime').should('exist'); - cy.get('[data-test-subj="ECSMappingEditorForm"]').within(() => { - cy.react('EuiButtonIcon', { props: { iconType: 'trash' } }).click(); - }); + cy.get('[data-test-subj="ECSMappingEditorForm"]') + .first() + .within(() => { + cy.react('EuiButtonIcon', { props: { iconType: 'trash' } }).click(); + }); cy.react('EuiButton').contains('Update query').click(); cy.wait(5000); diff --git a/x-pack/plugins/osquery/cypress/tasks/login.ts b/x-pack/plugins/osquery/cypress/tasks/login.ts index 0f19f71f67011..eec845c255e65 100644 --- a/x-pack/plugins/osquery/cypress/tasks/login.ts +++ b/x-pack/plugins/osquery/cypress/tasks/login.ts @@ -163,19 +163,21 @@ export const loginWithRole = async (role: ROLES) => { port: Cypress.env('configport'), } as UrlObject); cy.log(`origin: ${theUrl}`); - cy.request({ - body: { - providerType: 'basic', - providerName: 'basic', - currentURL: '/', - params: { - username: role, - password: 'changeme', + cy.session([role], () => { + cy.request({ + body: { + providerType: 'basic', + providerName: 'basic', + currentURL: '/', + params: { + username: role, + password: 'changeme', + }, }, - }, - headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, - method: 'POST', - url: getUrlWithRoute(role, LOGIN_API_ENDPOINT), + headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, + method: 'POST', + url: getUrlWithRoute(role, LOGIN_API_ENDPOINT), + }); }); }; @@ -217,20 +219,25 @@ const loginViaEnvironmentCredentials = () => { `Authenticating via environment credentials from the \`CYPRESS_${ELASTICSEARCH_USERNAME}\` and \`CYPRESS_${ELASTICSEARCH_PASSWORD}\` environment variables` ); + const username = Cypress.env(ELASTICSEARCH_USERNAME); + const password = Cypress.env(ELASTICSEARCH_PASSWORD); + // programmatically authenticate without interacting with the Kibana login page - cy.request({ - body: { - providerType: 'basic', - providerName: url && !url.includes('localhost') ? 'cloud-basic' : 'basic', - currentURL: '/', - params: { - username: Cypress.env(ELASTICSEARCH_USERNAME), - password: Cypress.env(ELASTICSEARCH_PASSWORD), + cy.session([username, password], () => { + cy.request({ + body: { + providerType: 'basic', + providerName: url && !url.includes('localhost') ? 'cloud-basic' : 'basic', + currentURL: '/', + params: { + username, + password, + }, }, - }, - headers: { 'kbn-xsrf': 'cypress-creds-via-env' }, - method: 'POST', - url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`, + headers: { 'kbn-xsrf': 'cypress-creds-via-env' }, + method: 'POST', + url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`, + }); }); }; @@ -248,20 +255,25 @@ const loginViaConfig = () => { cy.readFile(KIBANA_DEV_YML_PATH).then((kibanaDevYml) => { const config = yaml.safeLoad(kibanaDevYml); + const username = 'elastic'; + const password = config.elasticsearch.password; + // programmatically authenticate without interacting with the Kibana login page - cy.request({ - body: { - providerType: 'basic', - providerName: 'basic', - currentURL: '/', - params: { - username: 'elastic', - password: config.elasticsearch.password, + cy.session([username, password], () => { + cy.request({ + body: { + providerType: 'basic', + providerName: 'basic', + currentURL: '/', + params: { + username, + password, + }, }, - }, - headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, - method: 'POST', - url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`, + headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, + method: 'POST', + url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`, + }); }); }); }; diff --git a/x-pack/plugins/osquery/cypress/tasks/response_actions.ts b/x-pack/plugins/osquery/cypress/tasks/response_actions.ts index 2c9d726648340..4a5567238c8fd 100644 --- a/x-pack/plugins/osquery/cypress/tasks/response_actions.ts +++ b/x-pack/plugins/osquery/cypress/tasks/response_actions.ts @@ -8,5 +8,6 @@ export const RESPONSE_ACTIONS_ITEM_0 = 'response-actions-list-item-0'; export const RESPONSE_ACTIONS_ITEM_1 = 'response-actions-list-item-1'; export const RESPONSE_ACTIONS_ITEM_2 = 'response-actions-list-item-2'; +export const RESPONSE_ACTIONS_ITEM_3 = 'response-actions-list-item-3'; export const OSQUERY_RESPONSE_ACTION_ADD_BUTTON = 'osquery-response-action-type-selection-option'; diff --git a/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx b/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx index 81feb53fb4012..d8299dd672d35 100644 --- a/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx +++ b/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx @@ -18,6 +18,7 @@ interface ActionResultsSummaryProps { actionId: string; expirationDate?: string; agentIds?: string[]; + error?: string; } const renderErrorMessage = (error: string) => ( @@ -30,6 +31,7 @@ const ActionResultsSummaryComponent: React.FC = ({ actionId, expirationDate, agentIds, + error, }) => { const [pageIndex] = useState(0); const [pageSize] = useState(50); @@ -52,22 +54,42 @@ const ActionResultsSummaryComponent: React.FC = ({ isLive, skip: !hasActionResultsPrivileges, }); - if (expired) { - edges.forEach((edge) => { - if (!edge.fields?.completed_at && edge.fields) { - edge.fields['error.keyword'] = edge.fields.error = [ - i18n.translate('xpack.osquery.liveQueryActionResults.table.expiredErrorText', { - defaultMessage: 'The action request timed out.', - }), - ]; - } - }); - } + + useEffect(() => { + if (error) { + edges.forEach((edge) => { + if (edge.fields) { + edge.fields['error.skipped'] = edge.fields.error = [ + i18n.translate('xpack.osquery.liveQueryActionResults.table.skippedErrorText', { + defaultMessage: + "This query hasn't been called due to parameter used and its value not found in the alert.", + }), + ]; + } + }); + } else if (expired) { + edges.forEach((edge) => { + if (!edge.fields?.completed_at && edge.fields) { + edge.fields['error.keyword'] = edge.fields.error = [ + i18n.translate('xpack.osquery.liveQueryActionResults.table.expiredErrorText', { + defaultMessage: 'The action request timed out.', + }), + ]; + } + }); + } + }, [edges, error, expired]); const renderAgentIdColumn = useCallback((agentId) => , []); const renderRowsColumn = useCallback((rowsCount) => rowsCount ?? '-', []); const renderStatusColumn = useCallback( (_, item) => { + if (item.fields['error.skipped']) { + return i18n.translate('xpack.osquery.liveQueryActionResults.table.skippedStatusText', { + defaultMessage: 'skipped', + }); + } + if (!item.fields.completed_at) { return expired ? i18n.translate('xpack.osquery.liveQueryActionResults.table.expiredStatusText', { @@ -139,11 +161,11 @@ const ActionResultsSummaryComponent: React.FC = ({ useEffect(() => { setIsLive(() => { - if (!agentIds?.length || expired) return false; + if (!agentIds?.length || expired || error) return false; return !!(aggregations.totalResponded !== agentIds?.length); }); - }, [agentIds?.length, aggregations.totalResponded, expired]); + }, [agentIds?.length, aggregations.totalResponded, error, expired]); return edges.length ? ( diff --git a/x-pack/plugins/osquery/public/actions/use_all_live_queries.ts b/x-pack/plugins/osquery/public/actions/use_all_live_queries.ts index 8310217a7f864..78a6514ce4a3a 100644 --- a/x-pack/plugins/osquery/public/actions/use_all_live_queries.ts +++ b/x-pack/plugins/osquery/public/actions/use_all_live_queries.ts @@ -10,33 +10,42 @@ import { useQuery } from '@tanstack/react-query'; import { i18n } from '@kbn/i18n'; import { createFilter } from '../common/helpers'; import { useKibana } from '../common/lib/kibana'; -import type { ActionEdges, ActionsStrategyResponse, Direction } from '../../common/search_strategy'; +import type { ActionEdges, ActionsStrategyResponse } from '../../common/search_strategy'; import type { ESTermQuery, ESExistsQuery } from '../../common/typed_json'; import { useErrorToast } from '../common/hooks/use_error_toast'; +import { Direction } from '../../common/search_strategy'; -interface UseAllLiveQueries { +export interface UseAllLiveQueriesConfig { activePage: number; - direction: Direction; + direction?: Direction; limit: number; sortField: string; filterQuery?: ESTermQuery | ESExistsQuery | string; skip?: boolean; + alertId?: string; } +// Make sure we keep this and ACTIONS_QUERY_KEY in osquery_flyout.tsx in sync. +const ACTIONS_QUERY_KEY = 'actions'; + export const useAllLiveQueries = ({ activePage, - direction, + direction = Direction.desc, limit, sortField, filterQuery, skip = false, -}: UseAllLiveQueries) => { + alertId, +}: UseAllLiveQueriesConfig) => { const { http } = useKibana().services; const setErrorToast = useErrorToast(); return useQuery( - ['actions', { activePage, direction, limit, sortField }], + [ + ACTIONS_QUERY_KEY, + { activePage, direction, limit, sortField, ...(alertId ? { alertId } : {}) }, + ], () => http.get<{ data: Omit & { items: ActionEdges } }>( '/api/osquery/live_queries', diff --git a/x-pack/plugins/osquery/public/common/contexts.tsx b/x-pack/plugins/osquery/public/common/contexts.tsx index e035e08710a91..f0967f9c94d44 100644 --- a/x-pack/plugins/osquery/public/common/contexts.tsx +++ b/x-pack/plugins/osquery/public/common/contexts.tsx @@ -6,10 +6,6 @@ */ import React from 'react'; +import type { Ecs } from '../../common/ecs'; -export interface AlertEcsData { - _id: string; - _index?: string; -} - -export const AlertAttachmentContext = React.createContext(null); +export const AlertAttachmentContext = React.createContext(null); diff --git a/x-pack/plugins/osquery/public/live_queries/form/pack_queries_status_table.tsx b/x-pack/plugins/osquery/public/live_queries/form/pack_queries_status_table.tsx index 78bde0469651d..6808684fa8cf3 100644 --- a/x-pack/plugins/osquery/public/live_queries/form/pack_queries_status_table.tsx +++ b/x-pack/plugins/osquery/public/live_queries/form/pack_queries_status_table.tsx @@ -86,7 +86,7 @@ const DocsColumnResults: React.FC = ({ count, isLive }) {count ? {count} : '-'} - {isLive ? ( + {!isLive ? ( @@ -130,6 +130,7 @@ type PackQueryStatusItem = Partial<{ status?: string; pending?: number; docs?: number; + error?: string; }>; interface PackQueriesStatusTableProps { @@ -192,15 +193,12 @@ const PackQueriesStatusTableComponent: React.FC = ( [handleQueryFlyoutOpen] ); - const renderDocsColumn = useCallback( - (item: PackQueryStatusItem) => ( - - ), - [] - ); + const renderDocsColumn = useCallback((item: PackQueryStatusItem) => { + const isLive = + !item?.status || !!item.error || (item?.status !== 'running' && item?.pending === 0); + + return ; + }, []); const renderAgentsColumn = useCallback((item) => { if (!item.action_id) return; @@ -239,6 +237,7 @@ const PackQueriesStatusTableComponent: React.FC = ( endDate={expirationDate} agentIds={agentIds} failedAgentsCount={item?.failed ?? 0} + error={item.error} /> diff --git a/x-pack/plugins/osquery/public/live_queries/form/query_pack_selectable.tsx b/x-pack/plugins/osquery/public/live_queries/form/query_pack_selectable.tsx index 97618369dfd81..f3e8c2d9cc966 100644 --- a/x-pack/plugins/osquery/public/live_queries/form/query_pack_selectable.tsx +++ b/x-pack/plugins/osquery/public/live_queries/form/query_pack_selectable.tsx @@ -12,22 +12,29 @@ import styled from 'styled-components'; import { useController } from 'react-hook-form'; const StyledEuiCard = styled(EuiCard)` - padding: 16px 92px 16px 16px !important; - + padding: 0; + display: flex; + flex-direction: row; + border: ${(props) => { + if (props.selectable?.isSelected) { + return `1px solid ${props.theme.eui.euiColorSuccess}`; + } + }}; + .euiCard__content { + padding: 16px 92px 16px 16px !important; + } .euiTitle { font-size: 1rem; } - .euiText { margin-top: 0; color: ${(props) => props.theme.eui.euiTextSubduedColor}; } > button[role='switch'] { - left: auto; + min-inline-size: 80px; height: 100% !important; width: 80px; - right: 0; border-radius: 0 5px 5px 0; > span { @@ -43,12 +50,7 @@ const StyledEuiCard = styled(EuiCard)` } } } - - button[aria-checked='false'] > span > svg { - display: none; - } `; - interface QueryPackSelectableProps { canRunSingleQuery: boolean; canRunPacks: boolean; @@ -79,6 +81,7 @@ export const QueryPackSelectable = ({ onClick: () => handleChange('query'), isSelected: queryType === 'query', iconType: 'check', + textProps: {}, // this is needed for the text to get wrapped in span }), [queryType, handleChange] ); @@ -88,6 +91,7 @@ export const QueryPackSelectable = ({ onClick: () => handleChange('pack'), isSelected: queryType === 'pack', iconType: 'check', + textProps: {}, // this is needed for the text to get wrapped in span }), [queryType, handleChange] ); diff --git a/x-pack/plugins/osquery/public/live_queries/index.tsx b/x-pack/plugins/osquery/public/live_queries/index.tsx index c0900c8565d37..9f149c0082669 100644 --- a/x-pack/plugins/osquery/public/live_queries/index.tsx +++ b/x-pack/plugins/osquery/public/live_queries/index.tsx @@ -7,10 +7,12 @@ import { castArray, isEmpty, pickBy } from 'lodash'; import { EuiCode, EuiLoadingContent, EuiEmptyPrompt } from '@elastic/eui'; -import React, { useMemo } from 'react'; +import React, { useContext, useMemo } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import type { ECSMapping } from '@kbn/osquery-io-ts-types'; +import { replaceParamsQuery } from '../../common/utils/replace_params_query'; +import { AlertAttachmentContext } from '../common/contexts'; import { LiveQueryForm } from './form'; import { useActionResultsPrivileges } from '../action_results/use_action_privileges'; import { OSQUERY_INTEGRATION_NAME } from '../../common'; @@ -72,19 +74,30 @@ const LiveQueryComponent: React.FC = ({ return null; }, [agentId, agentIds, agentPolicyIds, agentSelection]); + const ecsData = useContext(AlertAttachmentContext); + + const initialQuery = useMemo(() => { + if (ecsData && query) { + const { result } = replaceParamsQuery(query, ecsData); + + return result; + } + + return query; + }, [ecsData, query]); const defaultValue = useMemo(() => { const initialValue = { ...(initialAgentSelection ? { agentSelection: initialAgentSelection } : {}), alertIds, - query, + query: initialQuery, savedQueryId, ecs_mapping, packId, }; return !isEmpty(pickBy(initialValue, (value) => !isEmpty(value))) ? initialValue : undefined; - }, [alertIds, ecs_mapping, initialAgentSelection, packId, query, savedQueryId]); + }, [alertIds, ecs_mapping, initialAgentSelection, initialQuery, packId, savedQueryId]); if (isLoading) { return ; diff --git a/x-pack/plugins/osquery/public/packs/form/shards/pack_type_selectable.tsx b/x-pack/plugins/osquery/public/packs/form/shards/pack_type_selectable.tsx index 35da6a666ea22..a63fe1fb57c9d 100644 --- a/x-pack/plugins/osquery/public/packs/form/shards/pack_type_selectable.tsx +++ b/x-pack/plugins/osquery/public/packs/form/shards/pack_type_selectable.tsx @@ -23,6 +23,10 @@ const StyledEuiCard = styled(EuiCard)` font-size: 1rem; } + .euiSpacer { + display: none; + } + .euiText { margin-top: 0; margin-left: 25px; diff --git a/x-pack/plugins/osquery/public/plugin.ts b/x-pack/plugins/osquery/public/plugin.ts index 7e7a91da2e908..fa36d5adabfb6 100644 --- a/x-pack/plugins/osquery/public/plugin.ts +++ b/x-pack/plugins/osquery/public/plugin.ts @@ -14,6 +14,7 @@ import type { } from '@kbn/core/public'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; +import { useAllLiveQueries } from './actions/use_all_live_queries'; import { getLazyOsqueryResponseActionTypeForm } from './shared_components/lazy_osquery_action_params_form'; import { useFetchStatus } from './fleet_integration/use_fetch_status'; import { getLazyOsqueryResults } from './shared_components/lazy_osquery_results'; @@ -128,6 +129,7 @@ export class OsqueryPlugin implements Plugin = ({ @@ -70,6 +71,7 @@ const ResultsTableComponent: React.FC = ({ startDate, endDate, liveQueryActionId, + error, }) => { const [isLive, setIsLive] = useState(true); const { data: hasActionResultsPrivileges } = useActionResultsPrivileges(); @@ -367,7 +369,7 @@ const ResultsTableComponent: React.FC = ({ useEffect( () => setIsLive(() => { - if (!agentIds?.length || expired) return false; + if (!agentIds?.length || expired || error) return false; return !!( aggregations.totalResponded !== agentIds?.length || @@ -381,6 +383,7 @@ const ResultsTableComponent: React.FC = ({ aggregations?.totalRowCount, allResultsData?.edges.length, allResultsData?.total, + error, expired, ] ); diff --git a/x-pack/plugins/osquery/public/routes/saved_queries/edit/tabs.tsx b/x-pack/plugins/osquery/public/routes/saved_queries/edit/tabs.tsx index 9fe31e920564c..3094a076afedf 100644 --- a/x-pack/plugins/osquery/public/routes/saved_queries/edit/tabs.tsx +++ b/x-pack/plugins/osquery/public/routes/saved_queries/edit/tabs.tsx @@ -27,6 +27,7 @@ interface ResultTabsProps { failedAgentsCount?: number; endDate?: string; liveQueryActionId?: string; + error?: string; } const ResultTabsComponent: React.FC = ({ @@ -37,6 +38,7 @@ const ResultTabsComponent: React.FC = ({ failedAgentsCount, startDate, liveQueryActionId, + error, }) => { const tabs = useMemo( () => [ @@ -52,6 +54,7 @@ const ResultTabsComponent: React.FC = ({ startDate={startDate} endDate={endDate} liveQueryActionId={liveQueryActionId} + error={error} /> ), }, @@ -60,7 +63,12 @@ const ResultTabsComponent: React.FC = ({ name: 'Status', 'data-test-subj': 'osquery-status-tab', content: ( - + ), append: failedAgentsCount ? ( @@ -69,7 +77,16 @@ const ResultTabsComponent: React.FC = ({ ) : null, }, ], - [actionId, agentIds, ecsMapping, startDate, endDate, liveQueryActionId, failedAgentsCount] + [ + actionId, + agentIds, + ecsMapping, + startDate, + endDate, + liveQueryActionId, + error, + failedAgentsCount, + ] ); return ( diff --git a/x-pack/plugins/osquery/public/shared_components/lazy_live_query_field.tsx b/x-pack/plugins/osquery/public/shared_components/lazy_live_query_field.tsx index a8b369b86342f..00ef03a941e5b 100644 --- a/x-pack/plugins/osquery/public/shared_components/lazy_live_query_field.tsx +++ b/x-pack/plugins/osquery/public/shared_components/lazy_live_query_field.tsx @@ -12,6 +12,8 @@ import type { LiveQueryQueryFieldProps } from '../live_queries/form/live_query_q import type { ServicesWrapperProps } from './services_wrapper'; import ServicesWrapper from './services_wrapper'; +const LiveQueryField = lazy(() => import('../live_queries/form/live_query_query_field')); + export const getLazyLiveQueryField = (services: ServicesWrapperProps['services']) => // eslint-disable-next-line react/display-name @@ -24,10 +26,8 @@ export const getLazyLiveQueryField = query: string; ecs_mapping: Record; }>; - }) => { - const LiveQueryField = lazy(() => import('../live_queries/form/live_query_query_field')); - - return ( + }) => + ( @@ -36,4 +36,3 @@ export const getLazyLiveQueryField = ); - }; diff --git a/x-pack/plugins/osquery/public/shared_components/lazy_osquery_action.tsx b/x-pack/plugins/osquery/public/shared_components/lazy_osquery_action.tsx index 15ffbdee14c4a..968e43cea5477 100644 --- a/x-pack/plugins/osquery/public/shared_components/lazy_osquery_action.tsx +++ b/x-pack/plugins/osquery/public/shared_components/lazy_osquery_action.tsx @@ -6,18 +6,17 @@ */ import React, { lazy, Suspense, useMemo } from 'react'; +import type { Ecs } from '../../common/ecs'; import ServicesWrapper from './services_wrapper'; import type { ServicesWrapperProps } from './services_wrapper'; import type { OsqueryActionProps } from './osquery_action'; -import type { AlertEcsData } from '../common/contexts'; import { AlertAttachmentContext } from '../common/contexts'; +const OsqueryAction = lazy(() => import('./osquery_action')); export const getLazyOsqueryAction = (services: ServicesWrapperProps['services']) => // eslint-disable-next-line react/display-name - (props: OsqueryActionProps & { ecsData?: AlertEcsData }) => { - const OsqueryAction = lazy(() => import('./osquery_action')); - + (props: OsqueryActionProps & { ecsData?: Ecs }) => { const { ecsData, ...restProps } = props; const renderAction = useMemo(() => { if (ecsData && ecsData?._id) { @@ -29,7 +28,7 @@ export const getLazyOsqueryAction = } return ; - }, [OsqueryAction, ecsData, restProps]); + }, [ecsData, restProps]); return ( diff --git a/x-pack/plugins/osquery/public/shared_components/lazy_osquery_results.tsx b/x-pack/plugins/osquery/public/shared_components/lazy_osquery_results.tsx index a50de706ab067..22b6af098a468 100644 --- a/x-pack/plugins/osquery/public/shared_components/lazy_osquery_results.tsx +++ b/x-pack/plugins/osquery/public/shared_components/lazy_osquery_results.tsx @@ -14,14 +14,13 @@ interface BigServices extends StartServices { storage: unknown; } +const OsqueryResults = lazy(() => import('./osquery_results')); + export const getLazyOsqueryResults = // eslint-disable-next-line react/display-name - (services: BigServices) => (props: OsqueryActionResultsProps) => { - const OsqueryResults = lazy(() => import('./osquery_results')); - - return ( + (services: BigServices) => (props: OsqueryActionResultsProps) => + ( ); - }; diff --git a/x-pack/plugins/osquery/public/shared_components/osquery_action/index.tsx b/x-pack/plugins/osquery/public/shared_components/osquery_action/index.tsx index 402dacf7a6542..13d4e8745e233 100644 --- a/x-pack/plugins/osquery/public/shared_components/osquery_action/index.tsx +++ b/x-pack/plugins/osquery/public/shared_components/osquery_action/index.tsx @@ -21,6 +21,7 @@ export interface OsqueryActionProps { defaultValues?: {}; formType: 'steps' | 'simple'; hideAgentsField?: boolean; + onSuccess?: () => void; } const OsqueryActionComponent: React.FC = ({ @@ -28,6 +29,7 @@ const OsqueryActionComponent: React.FC = ({ formType = 'simple', defaultValues, hideAgentsField, + onSuccess, }) => { const permissions = useKibana().services.application.capabilities.osquery; @@ -91,6 +93,7 @@ const OsqueryActionComponent: React.FC = ({ formType={formType} agentId={agentId} hideAgentsField={hideAgentsField} + onSuccess={onSuccess} {...defaultValues} /> ); diff --git a/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/index.tsx b/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/index.tsx index 1d2f79f273c58..5902eafddaa84 100644 --- a/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/index.tsx +++ b/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/index.tsx @@ -7,7 +7,6 @@ import React, { useEffect, useMemo } from 'react'; import { EuiSpacer } from '@elastic/eui'; -import uuid from 'uuid'; import type { FieldErrors } from 'react-hook-form'; import { useFieldArray } from 'react-hook-form'; import { useForm as useHookForm, FormProvider } from 'react-hook-form'; @@ -35,7 +34,6 @@ interface OsqueryResponseActionsValues { interface OsqueryResponseActionsParamsFormFields { savedQueryId: string | null; - id: string; ecs_mapping: ECSMapping; query: string; packId?: string[]; @@ -58,7 +56,6 @@ const OsqueryResponseActionParamsFormComponent = ({ onError, onChange, }: OsqueryResponseActionsParamsFormProps) => { - const uniqueId = useMemo(() => uuid.v4(), []); const hooksForm = useHookForm({ mode: 'all', defaultValues: defaultValues @@ -70,14 +67,13 @@ const OsqueryResponseActionParamsFormComponent = ({ } : { ecs_mapping: {}, - id: uniqueId, queryType: 'query', }, }); const { watch, register, formState, control } = hooksForm; - const [packId, queryType, queries, id] = watch(['packId', 'queryType', 'queries', 'id']); + const [packId, queryType, queries] = watch(['packId', 'queryType', 'queries']); const { data: packData } = usePack({ packId: packId?.[0], skip: !packId?.[0], @@ -105,7 +101,6 @@ const OsqueryResponseActionParamsFormComponent = ({ useEffect(() => { register('savedQueryId'); - register('id'); }, [register]); useEffect(() => { @@ -114,12 +109,10 @@ const OsqueryResponseActionParamsFormComponent = ({ // @ts-expect-error update types formData.queryType === 'pack' ? { - id: formData.id, packId: formData?.packId?.length ? formData?.packId[0] : undefined, queries: formData.queries, } : { - id: formData.id, savedQueryId: formData.savedQueryId, query: formData.query, ecsMapping: formData.ecs_mapping, @@ -150,10 +143,9 @@ const OsqueryResponseActionParamsFormComponent = ({ const queryDetails = useMemo( () => ({ queries, - action_id: id, agents: [], }), - [id, queries] + [queries] ); return ( diff --git a/x-pack/plugins/osquery/public/shared_components/osquery_results/index.tsx b/x-pack/plugins/osquery/public/shared_components/osquery_results/index.tsx index 36c09a2bce188..e7f3bd47a181a 100644 --- a/x-pack/plugins/osquery/public/shared_components/osquery_results/index.tsx +++ b/x-pack/plugins/osquery/public/shared_components/osquery_results/index.tsx @@ -10,9 +10,7 @@ import React from 'react'; import { QueryClientProvider } from '@tanstack/react-query'; import type { CoreStart } from '@kbn/core/public'; -import { useAllLiveQueries } from '../../actions/use_all_live_queries'; import { KibanaContextProvider } from '../../common/lib/kibana'; -import { Direction } from '../../../common/search_strategy'; import { queryClient } from '../../query_client'; import { KibanaThemeProvider } from '../../shared_imports'; @@ -23,41 +21,30 @@ import { OsqueryResult } from './osquery_result'; const OsqueryActionResultsComponent: React.FC = ({ agentIds, ruleName, - alertId, + actionItems, ecsData, -}) => { - const { data: actionsData } = useAllLiveQueries({ - filterQuery: { term: { alert_ids: alertId } }, - activePage: 0, - limit: 100, - direction: Direction.desc, - sortField: '@timestamp', - }); - - return ( -
- {actionsData?.data.items.map((item, index) => { - const actionId = item.fields?.action_id?.[0]; - const queryId = item.fields?.['queries.action_id']?.[0]; - // const query = item.fields?.['queries.query']?.[0]; - const startDate = item.fields?.['@timestamp'][0]; +}) => ( +
+ {actionItems?.map((item) => { + const actionId = item.fields?.action_id?.[0]; + const queryId = item.fields?.['queries.action_id']?.[0]; + const startDate = item.fields?.['@timestamp'][0]; - return ( - - ); - })} - -
- ); -}; + return ( + + ); + })} + +
+); export const OsqueryActionResults = React.memo(OsqueryActionResultsComponent); diff --git a/x-pack/plugins/osquery/public/shared_components/osquery_results/osquery_result.tsx b/x-pack/plugins/osquery/public/shared_components/osquery_results/osquery_result.tsx index c48e75c44ba82..a726f7c9b9070 100644 --- a/x-pack/plugins/osquery/public/shared_components/osquery_results/osquery_result.tsx +++ b/x-pack/plugins/osquery/public/shared_components/osquery_results/osquery_result.tsx @@ -15,7 +15,7 @@ import { ATTACHED_QUERY } from '../../agents/translations'; import { PackQueriesStatusTable } from '../../live_queries/form/pack_queries_status_table'; import { AlertAttachmentContext } from '../../common/contexts'; -interface OsqueryResultProps extends Omit { +interface OsqueryResultProps extends OsqueryActionResultsProps { actionId: string; queryId: string; startDate: string; diff --git a/x-pack/plugins/osquery/public/shared_components/osquery_results/osquery_results.test.tsx b/x-pack/plugins/osquery/public/shared_components/osquery_results/osquery_results.test.tsx index fcfa6b1a720a3..5a8ac2a3b9846 100644 --- a/x-pack/plugins/osquery/public/shared_components/osquery_results/osquery_results.test.tsx +++ b/x-pack/plugins/osquery/public/shared_components/osquery_results/osquery_results.test.tsx @@ -13,11 +13,11 @@ import { QueryClientProvider } from '@tanstack/react-query'; import { OsqueryActionResults } from '.'; import { queryClient } from '../../query_client'; import { useKibana } from '../../common/lib/kibana'; -import * as useAllLiveQueries from '../../actions/use_all_live_queries'; import * as useLiveQueryDetails from '../../actions/use_live_query_details'; import { PERMISSION_DENIED } from '../osquery_action/translations'; import * as privileges from '../../action_results/use_action_privileges'; import { defaultLiveQueryDetails, DETAILS_QUERY, getMockedKibanaConfig } from './test_utils'; +import type { OsqueryActionResultsProps } from './types'; jest.mock('../../common/lib/kibana'); @@ -31,11 +31,21 @@ const enablePrivileges = () => { })); }; -const defaultProps = { +const defaultProps: OsqueryActionResultsProps = { agentIds: ['agent1'], ruleName: ['Test-rule'], - ruleActions: [{ action_type_id: 'action1' }, { action_type_id: 'action2' }], - alertId: 'test-alert-id', + actionItems: [ + { + _id: 'test', + _index: 'test', + fields: { + action_id: ['testActionId'], + 'queries.action_id': ['queriesActionId'], + 'queries.query': [DETAILS_QUERY], + '@timestamp': ['2022-09-08T18:16:30.256Z'], + }, + }, + ], ecsData: { _id: 'test', }, @@ -66,23 +76,6 @@ const renderWithContext = (Element: React.ReactElement) => describe('Osquery Results', () => { beforeAll(() => { mockKibana(); - // @ts-expect-error update types - jest.spyOn(useAllLiveQueries, 'useAllLiveQueries').mockImplementation(() => ({ - data: { - data: { - items: [ - { - fields: { - action_id: ['sfdsfds'], - 'queries.action_id': ['dsadas'], - 'queries.query': [DETAILS_QUERY], - '@timestamp': ['2022-09-08T18:16:30.256Z'], - }, - }, - ], - }, - }, - })); jest .spyOn(useLiveQueryDetails, 'useLiveQueryDetails') diff --git a/x-pack/plugins/osquery/public/shared_components/osquery_results/types.ts b/x-pack/plugins/osquery/public/shared_components/osquery_results/types.ts index cb4b11651ee45..6cc918f936751 100644 --- a/x-pack/plugins/osquery/public/shared_components/osquery_results/types.ts +++ b/x-pack/plugins/osquery/public/shared_components/osquery_results/types.ts @@ -5,11 +5,12 @@ * 2.0. */ -import type { AlertEcsData } from '../../common/contexts'; +import type { Ecs } from '../../../common/ecs'; +import type { ActionEdges } from '../../../common/search_strategy'; export interface OsqueryActionResultsProps { agentIds?: string[]; ruleName?: string[]; - alertId: string; - ecsData: AlertEcsData; + ecsData: Ecs; + actionItems?: ActionEdges; } diff --git a/x-pack/plugins/osquery/public/types.ts b/x-pack/plugins/osquery/public/types.ts index d591776a41ecd..f6d05a3d45996 100644 --- a/x-pack/plugins/osquery/public/types.ts +++ b/x-pack/plugins/osquery/public/types.ts @@ -25,6 +25,7 @@ import type { getLazyOsqueryAction, getLazyOsqueryResponseActionTypeForm, } from './shared_components'; +import type { useAllLiveQueries, UseAllLiveQueriesConfig } from './actions/use_all_live_queries'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface OsqueryPluginSetup {} @@ -36,6 +37,7 @@ export interface OsqueryPluginStart { isOsqueryAvailable: (props: { agentId: string }) => boolean; fetchInstallationStatus: () => { loading: boolean; disabled: boolean; permissionDenied: boolean }; OsqueryResponseActionTypeForm: ReturnType; + fetchAllLiveQueries: (config: UseAllLiveQueriesConfig) => ReturnType; } export interface AppPluginStartDependencies { diff --git a/x-pack/plugins/osquery/server/handlers/action/create_action_handler.ts b/x-pack/plugins/osquery/server/handlers/action/create_action_handler.ts index cd7a46cfa72c8..a38f8eb08b57b 100644 --- a/x-pack/plugins/osquery/server/handlers/action/create_action_handler.ts +++ b/x-pack/plugins/osquery/server/handlers/action/create_action_handler.ts @@ -7,16 +7,16 @@ import uuid from 'uuid'; import moment from 'moment'; -import { flatten, isEmpty, map, omit, pick, pickBy, some } from 'lodash'; +import { filter, flatten, isEmpty, map, omit, pick, pickBy, some } from 'lodash'; import { AGENT_ACTIONS_INDEX } from '@kbn/fleet-plugin/common'; -import type { SavedObjectsClientContract } from '@kbn/core/server'; +import type { Ecs, SavedObjectsClientContract } from '@kbn/core/server'; +import { createDynamicQueries, createQueries } from './create_queries'; import { getInternalSavedObjectsClient } from '../../routes/utils'; import { parseAgentSelection } from '../../lib/parse_agent_groups'; import { packSavedObjectType } from '../../../common/types'; import type { OsqueryAppContext } from '../../lib/osquery_app_context_services'; import type { CreateLiveQueryRequestBodySchema } from '../../../common/schemas/routes/live_query'; import { convertSOQueriesToPack } from '../../routes/pack/utils'; -import { isSavedQueryPrebuilt } from '../../routes/saved_query/utils'; import { ACTIONS_INDEX } from '../../../common/constants'; import { TELEMETRY_EBT_LIVE_QUERY_EVENT } from '../../lib/telemetry/constants'; import type { PackSavedObjectAttributes } from '../../common/types'; @@ -25,17 +25,23 @@ interface Metadata { currentUser: string | undefined; } +interface CreateActionHandlerOptions { + soClient?: SavedObjectsClientContract; + metadata?: Metadata; + ecsData?: Ecs; +} + export const createActionHandler = async ( osqueryContext: OsqueryAppContext, params: CreateLiveQueryRequestBodySchema, - soClient?: SavedObjectsClientContract, - metadata?: Metadata + options: CreateActionHandlerOptions ) => { const [coreStartServices] = await osqueryContext.getStartServices(); const esClientInternal = coreStartServices.elasticsearch.client.asInternalUser; const internalSavedObjectsClient = await getInternalSavedObjectsClient( osqueryContext.getStartServices ); + const { soClient, metadata, ecsData } = options; const savedObjectsClient = soClient ?? coreStartServices.savedObjects.createInternalRepository(); // eslint-disable-next-line @typescript-eslint/naming-convention @@ -46,6 +52,7 @@ export const createActionHandler = async ( platformsSelected: agent_platforms, policiesSelected: agent_policy_ids, }); + if (!selectedAgents.length) { throw new Error('No agents found for selection'); } @@ -95,49 +102,24 @@ export const createActionHandler = async ( (value) => !isEmpty(value) ) ) - : params.queries?.length - ? map(params.queries, (query) => - pickBy( - { - // @ts-expect-error where does type 'number' comes from? - ...query, - action_id: uuid.v4(), - agents: selectedAgents, - }, - (value) => !isEmpty(value) - ) - ) - : [ - pickBy( - { - action_id: uuid.v4(), - id: uuid.v4(), - query: params.query, - saved_query_id: params.saved_query_id, - saved_query_prebuilt: params.saved_query_id - ? await isSavedQueryPrebuilt( - osqueryContext.service.getPackageService()?.asInternalUser, - params.saved_query_id - ) - : undefined, - ecs_mapping: params.ecs_mapping, - agents: selectedAgents, - }, - (value) => !isEmpty(value) - ), - ], + : ecsData + ? await createDynamicQueries(params, ecsData, osqueryContext) + : await createQueries(params, selectedAgents, osqueryContext), }; - const fleetActions = map(osqueryAction.queries, (query) => ({ - action_id: query.action_id, - '@timestamp': moment().toISOString(), - expiration: moment().add(5, 'minutes').toISOString(), - type: 'INPUT_ACTION', - input_type: 'osquery', - agents: query.agents, - user_id: metadata?.currentUser, - data: pick(query, ['id', 'query', 'ecs_mapping', 'version', 'platform']), - })); + const fleetActions = map( + filter(osqueryAction.queries, (query) => !query.error), + (query) => ({ + action_id: query.action_id, + '@timestamp': moment().toISOString(), + expiration: moment().add(5, 'minutes').toISOString(), + type: 'INPUT_ACTION', + input_type: 'osquery', + agents: query.agents, + user_id: metadata?.currentUser, + data: pick(query, ['id', 'query', 'ecs_mapping', 'version', 'platform']), + }) + ); await esClientInternal.bulk({ refresh: 'wait_for', diff --git a/x-pack/plugins/osquery/server/handlers/action/create_queries.ts b/x-pack/plugins/osquery/server/handlers/action/create_queries.ts new file mode 100644 index 0000000000000..f9f918a7ea623 --- /dev/null +++ b/x-pack/plugins/osquery/server/handlers/action/create_queries.ts @@ -0,0 +1,118 @@ +/* + * 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 { isEmpty, map, pickBy } from 'lodash'; +import uuid from 'uuid'; +import type { Ecs } from '@kbn/core/server'; +import { i18n } from '@kbn/i18n'; + +import type { OsqueryAppContext } from '../../lib/osquery_app_context_services'; +import type { CreateLiveQueryRequestBodySchema } from '../../../common/schemas/routes/live_query'; +import { replaceParamsQuery } from '../../../common/utils/replace_params_query'; +import { isSavedQueryPrebuilt } from '../../routes/saved_query/utils'; + +export const createQueries = async ( + params: CreateLiveQueryRequestBodySchema, + agents: string[], + osqueryContext: OsqueryAppContext +) => + params.queries?.length + ? map(params.queries, (query) => + pickBy( + { + ...query, + action_id: uuid.v4(), + agents, + }, + (value) => !isEmpty(value) || value === true + ) + ) + : [ + pickBy( + { + action_id: uuid.v4(), + id: uuid.v4(), + query: params.query, + saved_query_id: params.saved_query_id, + saved_query_prebuilt: params.saved_query_id + ? await isSavedQueryPrebuilt( + osqueryContext.service.getPackageService()?.asInternalUser, + params.saved_query_id + ) + : undefined, + ecs_mapping: params.ecs_mapping, + agents, + }, + (value) => !isEmpty(value) + ), + ]; + +export const createDynamicQueries = async ( + params: CreateLiveQueryRequestBodySchema, + alert: Ecs, + osqueryContext: OsqueryAppContext +) => + params.queries?.length + ? map(params.queries, ({ query, ...restQuery }) => { + const replacedQuery = replacedQueries(query, alert); + + return pickBy( + { + ...replacedQuery, + ...restQuery, + action_id: uuid.v4(), + alert_ids: params.alert_ids, + agents: params.agent_ids, + }, + (value) => !isEmpty(value) || value === true + ); + }) + : [ + pickBy( + { + action_id: uuid.v4(), + id: uuid.v4(), + ...replacedQueries(params.query, alert), + // just for single queries - we need to overwrite the error property + error: undefined, + saved_query_id: params.saved_query_id, + saved_query_prebuilt: params.saved_query_id + ? await isSavedQueryPrebuilt( + osqueryContext.service.getPackageService()?.asInternalUser, + params.saved_query_id + ) + : undefined, + ecs_mapping: params.ecs_mapping, + alert_ids: params.alert_ids, + agents: params.agent_ids, + }, + (value) => !isEmpty(value) + ), + ]; + +const replacedQueries = ( + query: string | undefined, + ecsData?: Ecs +): { query: string | undefined; error?: string } => { + if (ecsData && query) { + const { result, skipped } = replaceParamsQuery(query, ecsData); + + return { + query: result, + ...(skipped + ? { + error: i18n.translate('xpack.osquery.liveQueryActions.error.notFoundParameters', { + defaultMessage: + "This query hasn't been called due to parameter used and its value not found in the alert.", + }), + } + : {}), + }; + } + + return { query }; +}; diff --git a/x-pack/plugins/osquery/server/plugin.ts b/x-pack/plugins/osquery/server/plugin.ts index fd23d67741dbc..365299750a9ce 100644 --- a/x-pack/plugins/osquery/server/plugin.ts +++ b/x-pack/plugins/osquery/server/plugin.ts @@ -11,6 +11,7 @@ import type { CoreStart, Plugin, Logger, + Ecs, } from '@kbn/core/server'; import { SavedObjectsClient } from '@kbn/core/server'; import type { DataRequestHandlerContext } from '@kbn/data-plugin/server'; @@ -92,8 +93,8 @@ export class OsqueryPlugin implements Plugin - createActionHandler(osqueryContext, params), + osqueryCreateAction: (params: CreateLiveQueryRequestBodySchema, ecsData?: Ecs) => + createActionHandler(osqueryContext, params, { ecsData }), }; } diff --git a/x-pack/plugins/osquery/server/routes/live_query/create_live_query_route.ts b/x-pack/plugins/osquery/server/routes/live_query/create_live_query_route.ts index fd4754577d1cd..668b5b3f924df 100644 --- a/x-pack/plugins/osquery/server/routes/live_query/create_live_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/live_query/create_live_query_route.ts @@ -86,8 +86,7 @@ export const createLiveQueryRoute = (router: IRouter, osqueryContext: OsqueryApp const { response: osqueryAction } = await createActionHandler( osqueryContext, request.body, - soClient, - { currentUser } + { soClient, metadata: { currentUser } } ); return response.ok({ diff --git a/x-pack/plugins/osquery/server/types.ts b/x-pack/plugins/osquery/server/types.ts index ef0bdacf0dfd2..5a5725bbc019b 100644 --- a/x-pack/plugins/osquery/server/types.ts +++ b/x-pack/plugins/osquery/server/types.ts @@ -11,6 +11,8 @@ import type { PluginSetup as DataPluginSetup, PluginStart as DataPluginStart, } from '@kbn/data-plugin/server'; +import type { Ecs } from '@kbn/ecs'; + import type { FleetStartContract } from '@kbn/fleet-plugin/server'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import type { PluginSetupContract } from '@kbn/features-plugin/server'; @@ -24,7 +26,7 @@ import type { RuleRegistryPluginStartContract } from '@kbn/rule-registry-plugin/ import type { CreateLiveQueryRequestBodySchema } from '../common/schemas/routes/live_query'; export interface OsqueryPluginSetup { - osqueryCreateAction: (payload: CreateLiveQueryRequestBodySchema) => void; + osqueryCreateAction: (payload: CreateLiveQueryRequestBodySchema, ecsData?: Ecs) => void; } // eslint-disable-next-line @typescript-eslint/no-empty-interface diff --git a/x-pack/plugins/osquery/tsconfig.json b/x-pack/plugins/osquery/tsconfig.json index e29bd4d10cd73..7896d572e5bd5 100644 --- a/x-pack/plugins/osquery/tsconfig.json +++ b/x-pack/plugins/osquery/tsconfig.json @@ -65,5 +65,6 @@ "@kbn/securitysolution-es-utils", "@kbn/core-elasticsearch-client-server-mocks", "@kbn/std", + "@kbn/ecs", ] } diff --git a/x-pack/plugins/security_solution/common/detection_engine/rule_response_actions/schemas/osquery.ts b/x-pack/plugins/security_solution/common/detection_engine/rule_response_actions/schemas/osquery.ts index 878f76129463f..0fd840a0c8e71 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/rule_response_actions/schemas/osquery.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/rule_response_actions/schemas/osquery.ts @@ -9,7 +9,6 @@ import * as t from 'io-ts'; import { ecsMapping, arrayQueries } from '@kbn/osquery-io-ts-types'; export const OsqueryParams = t.type({ - id: t.string, query: t.union([t.string, t.undefined]), ecs_mapping: t.union([ecsMapping, t.undefined]), queries: t.union([arrayQueries, t.undefined]), @@ -18,7 +17,6 @@ export const OsqueryParams = t.type({ }); export const OsqueryParamsCamelCase = t.type({ - id: t.string, query: t.union([t.string, t.undefined]), ecsMapping: t.union([ecsMapping, t.undefined]), queries: t.union([arrayQueries, t.undefined]), diff --git a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts index c9a72be3bdcc8..18b59998b0745 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts @@ -11,11 +11,7 @@ import type { AxiosResponse } from 'axios'; import uuid from 'uuid'; import type { KbnClient } from '@kbn/test'; import type { DeleteByQueryResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import type { - Agent, - CreatePackagePolicyResponse, - GetPackagesResponse, -} from '@kbn/fleet-plugin/common'; +import type { Agent, CreatePackagePolicyResponse, GetInfoResponse } from '@kbn/fleet-plugin/common'; import { EndpointDocGenerator } from '../generate_data'; import type { HostMetadata, HostPolicyResponse } from '../types'; import type { @@ -95,7 +91,7 @@ export async function indexEndpointHostDocs({ client: Client; kbnClient: KbnClient; realPolicies: Record; - epmEndpointPackage: GetPackagesResponse['items'][0]; + epmEndpointPackage: GetInfoResponse['item']; metadataIndex: string; policyResponseIndex: string; enrollFleet: boolean; diff --git a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts index 59808b1df430c..9cda7554f0819 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts @@ -10,8 +10,10 @@ import { assertNever } from '@kbn/std'; import type { GetAgentPoliciesResponseItem, GetPackagesResponse, + GetInfoResponse, EsAssetReference, KibanaAssetReference, + AssetsGroupedByServiceByType, } from '@kbn/fleet-plugin/common'; import { agentPolicyStatuses } from '@kbn/fleet-plugin/common'; import { EndpointMetadataGenerator } from './data_generators/endpoint_metadata_generator'; @@ -1657,6 +1659,90 @@ export class EndpointDocGenerator extends BaseDataGenerator { }; } + /** + * Generate a Fleet EPM Package for Endpoint + */ + public generateEpmPackageInfo(): GetInfoResponse['item'] { + return { + name: 'endpoint', + title: 'Elastic Endpoint', + version: '0.5.0', + description: 'This is the Elastic Endpoint package.', + type: 'integration', + download: '/epr/endpoint/endpoint-0.5.0.tar.gz', + path: '/package/endpoint/0.5.0', + format_version: '', + owner: { github: '' }, + latestVersion: '', + assets: {} as AssetsGroupedByServiceByType, + icons: [ + { + path: '/package/endpoint/0.5.0/img/logo-endpoint-64-color.svg', + src: '/img/logo-endpoint-64-color.svg', + size: '16x16', + type: 'image/svg+xml', + }, + ], + status: 'installed', + release: 'ga', + savedObject: { + type: 'epm-packages', + id: 'endpoint', + attributes: { + installed_kibana: [ + { id: '826759f0-7074-11ea-9bc8-6b38f4d29a16', type: 'dashboard' }, + { id: '1cfceda0-728b-11ea-9bc8-6b38f4d29a16', type: 'visualization' }, + { id: '1e525190-7074-11ea-9bc8-6b38f4d29a16', type: 'visualization' }, + { id: '55387750-729c-11ea-9bc8-6b38f4d29a16', type: 'visualization' }, + { id: '92b1edc0-706a-11ea-9bc8-6b38f4d29a16', type: 'visualization' }, + { id: 'a3a3bd10-706b-11ea-9bc8-6b38f4d29a16', type: 'map' }, + ] as KibanaAssetReference[], + installed_es: [ + { id: 'logs-endpoint.alerts', type: 'index_template' }, + { id: 'events-endpoint', type: 'index_template' }, + { id: 'logs-endpoint.events.file', type: 'index_template' }, + { id: 'logs-endpoint.events.library', type: 'index_template' }, + { id: 'metrics-endpoint.metadata', type: 'index_template' }, + { id: 'metrics-endpoint.metadata_mirror', type: 'index_template' }, + { id: 'logs-endpoint.events.network', type: 'index_template' }, + { id: 'metrics-endpoint.policy', type: 'index_template' }, + { id: 'logs-endpoint.events.process', type: 'index_template' }, + { id: 'logs-endpoint.events.registry', type: 'index_template' }, + { id: 'logs-endpoint.events.security', type: 'index_template' }, + { id: 'metrics-endpoint.telemetry', type: 'index_template' }, + ] as EsAssetReference[], + package_assets: [], + es_index_patterns: { + alerts: 'logs-endpoint.alerts-*', + events: 'events-endpoint-*', + file: 'logs-endpoint.events.file-*', + library: 'logs-endpoint.events.library-*', + metadata: 'metrics-endpoint.metadata-*', + metadata_mirror: 'metrics-endpoint.metadata_mirror-*', + network: 'logs-endpoint.events.network-*', + policy: 'metrics-endpoint.policy-*', + process: 'logs-endpoint.events.process-*', + registry: 'logs-endpoint.events.registry-*', + security: 'logs-endpoint.events.security-*', + telemetry: 'metrics-endpoint.telemetry-*', + }, + name: 'endpoint', + version: '0.5.0', + internal: false, + install_version: '0.5.0', + install_status: 'installed', + install_started_at: '2020-06-24T14:41:23.098Z', + install_source: 'registry', + keep_policies_up_to_date: false, + verification_status: 'unknown', + }, + references: [], + updated_at: '2020-06-24T14:41:23.098Z', + version: 'Wzc0LDFd', + }, + }; + } + /** * Generates a Host Policy response message */ diff --git a/x-pack/plugins/security_solution/common/endpoint/index_data.ts b/x-pack/plugins/security_solution/common/endpoint/index_data.ts index 4971dc83c29aa..454f945ca656a 100644 --- a/x-pack/plugins/security_solution/common/endpoint/index_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/index_data.ts @@ -9,8 +9,8 @@ import type { Client } from '@elastic/elasticsearch'; import seedrandom from 'seedrandom'; import type { KbnClient } from '@kbn/test'; import type { AxiosResponse } from 'axios'; -import type { CreatePackagePolicyResponse, GetPackagesResponse } from '@kbn/fleet-plugin/common'; -import { EPM_API_ROUTES } from '@kbn/fleet-plugin/common'; +import type { CreatePackagePolicyResponse, GetInfoResponse } from '@kbn/fleet-plugin/common'; +import { epmRouteService } from '@kbn/fleet-plugin/common'; import type { TreeOptions } from './generate_data'; import { EndpointDocGenerator } from './generate_data'; import type { @@ -121,15 +121,16 @@ export async function indexHostsAndAlerts( return response; } -const getEndpointPackageInfo = async ( +export const getEndpointPackageInfo = async ( kbnClient: KbnClient -): Promise => { +): Promise => { + const path = epmRouteService.getInfoPath('endpoint'); const endpointPackage = ( (await kbnClient.request({ - path: `${EPM_API_ROUTES.LIST_PATTERN}?category=security`, + path, method: 'GET', - })) as AxiosResponse - ).data.items.find((epmPackage) => epmPackage.name === 'endpoint'); + })) as AxiosResponse + ).data.item; if (!endpointPackage) { throw new Error('EPM Endpoint package was not found!'); diff --git a/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.test.ts b/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.test.ts index 6bd6bbdbda02b..34226900cbcc7 100644 --- a/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.test.ts +++ b/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.test.ts @@ -5,13 +5,7 @@ * 2.0. */ -import { - calculateEndpointAuthz, - calculatePermissionsFromCapabilities, - calculatePermissionsFromPrivileges, - defaultEndpointPermissions, - getEndpointAuthzInitialState, -} from './authz'; +import { calculateEndpointAuthz, getEndpointAuthzInitialState } from './authz'; import type { FleetAuthz } from '@kbn/fleet-plugin/common'; import { createFleetAuthzMock } from '@kbn/fleet-plugin/common'; import { createLicenseServiceMock } from '../../../license/mocks'; @@ -87,9 +81,7 @@ describe('Endpoint Authz service', () => { it(`should allow Host Isolation Exception read/delete when license is not Platinum+, but entries exist`, () => { licenseService.isPlatinumPlus.mockReturnValue(false); - expect( - calculateEndpointAuthz(licenseService, fleetAuthz, userRoles, false, undefined, true) - ).toEqual( + expect(calculateEndpointAuthz(licenseService, fleetAuthz, userRoles, false, true)).toEqual( expect.objectContaining({ canWriteHostIsolationExceptions: false, canReadHostIsolationExceptions: true, @@ -197,24 +189,6 @@ describe('Endpoint Authz service', () => { expect(authz[auth]).toBe(false); }); }); - - it('correctly handles permissions', () => { - const authz = calculateEndpointAuthz(licenseService, fleetAuthz, userRoles, true, { - canWriteSecuritySolution: false, - canReadSecuritySolution: true, - }); - expect(authz.canWriteSecuritySolution).toBe(false); - expect(authz.canReadSecuritySolution).toBe(true); - }); - }); - - describe('defaultEndpointPermissions', () => { - it('returns expected permissions', () => { - expect(defaultEndpointPermissions()).toEqual({ - canWriteSecuritySolution: false, - canReadSecuritySolution: false, - }); - }); }); describe('getEndpointAuthzInitialState()', () => { @@ -251,49 +225,4 @@ describe('Endpoint Authz service', () => { }); }); }); - - describe('calculatePermissionsFromPrivileges', () => { - it('returns default permissions if no privileges', () => { - const permissions = calculatePermissionsFromPrivileges(undefined); - expect(permissions).toEqual(defaultEndpointPermissions()); - }); - - it('returns expected permissions from privileges', () => { - const privileges = [ - { privilege: 'ui:8.6.0:siem/crud', authorized: false }, - { privilege: 'ui:8.6.0:siem/show', authorized: true }, - { privilege: 'ui:8.6.0:siem/foobar', authorized: true }, - ]; - const permissions = calculatePermissionsFromPrivileges(privileges); - expect(permissions).toEqual({ - canWriteSecuritySolution: false, - canReadSecuritySolution: true, - }); - }); - }); - - describe('calculatePermissionsFromCapabilities', () => { - it('returns default permissions if no capabilities', () => { - const permissions = calculatePermissionsFromCapabilities(undefined); - expect(permissions).toEqual(defaultEndpointPermissions()); - }); - - it('returns expected permissions from capabilities', () => { - const capabilities = { - navLinks: {}, - management: {}, - catalogue: {}, - siem: { - crud: false, - show: true, - foobar: true, - }, - }; - const permissions = calculatePermissionsFromCapabilities(capabilities); - expect(permissions).toEqual({ - canWriteSecuritySolution: false, - canReadSecuritySolution: true, - }); - }); - }); }); diff --git a/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.ts b/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.ts index 87c56ff4d94b1..45bc24e42416b 100644 --- a/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.ts +++ b/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.ts @@ -6,19 +6,11 @@ */ import type { ENDPOINT_PRIVILEGES, FleetAuthz } from '@kbn/fleet-plugin/common'; -import type { Capabilities } from '@kbn/core-capabilities-common'; import type { LicenseService } from '../../../license'; -import type { EndpointPermissions, EndpointAuthz } from '../../types/authz'; +import type { EndpointAuthz } from '../../types/authz'; import type { MaybeImmutable } from '../../types'; -export function defaultEndpointPermissions(): EndpointPermissions { - return { - canWriteSecuritySolution: false, - canReadSecuritySolution: false, - }; -} - /** * Checks to see if a given Kibana privilege was granted. * Note that this only checks if the user has the privilege as part of their role. That @@ -35,7 +27,7 @@ export function hasKibanaPrivilege( fleetAuthz: FleetAuthz, isEndpointRbacEnabled: boolean, isSuperuser: boolean, - privilege: typeof ENDPOINT_PRIVILEGES[number] + privilege: keyof typeof ENDPOINT_PRIVILEGES ): boolean { // user is superuser, always return true if (isSuperuser) { @@ -70,13 +62,21 @@ export const calculateEndpointAuthz = ( fleetAuthz: FleetAuthz, userRoles: MaybeImmutable, isEndpointRbacEnabled: boolean = false, - permissions: Partial = defaultEndpointPermissions(), hasHostIsolationExceptionsItems: boolean = false ): EndpointAuthz => { const isPlatinumPlusLicense = licenseService.isPlatinumPlus(); const isEnterpriseLicense = licenseService.isEnterprise(); const hasEndpointManagementAccess = userRoles.includes('superuser'); - const { canWriteSecuritySolution = false, canReadSecuritySolution = false } = permissions; + + const canWriteSecuritySolution = hasKibanaPrivilege( + fleetAuthz, + true, + hasEndpointManagementAccess, + 'writeSecuritySolution' + ); + const canReadSecuritySolution = + canWriteSecuritySolution || + hasKibanaPrivilege(fleetAuthz, true, hasEndpointManagementAccess, 'readSecuritySolution'); const canWriteEndpointList = hasKibanaPrivilege( fleetAuthz, isEndpointRbacEnabled, @@ -251,7 +251,8 @@ export const calculateEndpointAuthz = ( export const getEndpointAuthzInitialState = (): EndpointAuthz => { return { - ...defaultEndpointPermissions(), + canWriteSecuritySolution: false, + canReadSecuritySolution: false, canAccessFleet: false, canAccessEndpointActionsLogManagement: false, canAccessEndpointManagement: false, @@ -280,66 +281,3 @@ export const getEndpointAuthzInitialState = (): EndpointAuthz => { canReadEventFilters: false, }; }; - -const SIEM_PERMISSIONS = [ - { permission: 'canWriteSecuritySolution', privilege: 'crud' }, - { permission: 'canReadSecuritySolution', privilege: 'show' }, -] as const; - -function hasPrivilege( - kibanaPrivileges: Array<{ - resource?: string; - privilege: string; - authorized: boolean; - }>, - prefix: string, - searchPrivilege: string -): boolean { - const privilege = kibanaPrivileges.find((p) => - p.privilege.endsWith(`${prefix}${searchPrivilege}`) - ); - return privilege?.authorized || false; -} - -export function calculatePermissionsFromPrivileges( - kibanaPrivileges: - | Array<{ - resource?: string; - privilege: string; - authorized: boolean; - }> - | undefined -): EndpointPermissions { - if (!kibanaPrivileges || !kibanaPrivileges.length) { - return defaultEndpointPermissions(); - } - - const siemPermissions: EndpointPermissions = SIEM_PERMISSIONS.reduce( - (acc, { permission, privilege }) => { - return { - ...acc, - [permission]: hasPrivilege(kibanaPrivileges, 'siem/', privilege), - }; - }, - {} as EndpointPermissions - ); - - return { - ...siemPermissions, - }; -} - -export function calculatePermissionsFromCapabilities( - capabilities: Capabilities | undefined -): EndpointPermissions { - if (!capabilities || !capabilities.siem) { - return defaultEndpointPermissions(); - } - - return SIEM_PERMISSIONS.reduce((acc, { permission, privilege }) => { - return { - ...acc, - [permission]: capabilities.siem[privilege] || false, - }; - }, {} as EndpointPermissions); -} diff --git a/x-pack/plugins/security_solution/common/endpoint/service/authz/index.ts b/x-pack/plugins/security_solution/common/endpoint/service/authz/index.ts index e1e2d241754e9..03d14a0945184 100644 --- a/x-pack/plugins/security_solution/common/endpoint/service/authz/index.ts +++ b/x-pack/plugins/security_solution/common/endpoint/service/authz/index.ts @@ -5,10 +5,4 @@ * 2.0. */ -export { - getEndpointAuthzInitialState, - calculateEndpointAuthz, - calculatePermissionsFromPrivileges, - calculatePermissionsFromCapabilities, - defaultEndpointPermissions, -} from './authz'; +export { getEndpointAuthzInitialState, calculateEndpointAuthz } from './authz'; diff --git a/x-pack/plugins/security_solution/common/endpoint/types/authz.ts b/x-pack/plugins/security_solution/common/endpoint/types/authz.ts index e693e6d0e4cff..d6f67e3efe8c5 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/authz.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/authz.ts @@ -6,20 +6,14 @@ */ /** - * Endpoint permissions derived from Kibana capabilities and privileges + * Set of Endpoint Specific privileges that control application authorization. This interface is + * used both on the client and server for consistency */ -export interface EndpointPermissions { +export interface EndpointAuthz { /** if user has write permissions to the security solution app */ canWriteSecuritySolution: boolean; /** if user has read permissions to the security solution app */ canReadSecuritySolution: boolean; -} - -/** - * Set of Endpoint Specific privileges that control application authorization. This interface is - * used both on the client and server for consistency - */ -export interface EndpointAuthz extends EndpointPermissions { /** If user has permissions to access Fleet */ canAccessFleet: boolean; /** If user has permissions to access Endpoint management (includes check to ensure they also have access to fleet) */ diff --git a/x-pack/plugins/security_solution/common/utils/format_page_filter_search_param.ts b/x-pack/plugins/security_solution/common/utils/format_page_filter_search_param.ts index eb33e8cd629fe..c8deaf824bc2c 100644 --- a/x-pack/plugins/security_solution/common/utils/format_page_filter_search_param.ts +++ b/x-pack/plugins/security_solution/common/utils/format_page_filter_search_param.ts @@ -5,16 +5,14 @@ * 2.0. */ -import rison from '@kbn/rison'; import type { FilterItemObj } from '../../public/common/components/filter_group/types'; export const formatPageFilterSearchParam = (filters: FilterItemObj[]) => { - const modifiedFilters = filters.map((filter) => ({ + return filters.map((filter) => ({ title: filter.title ?? filter.fieldName, selectedOptions: filter.selectedOptions ?? [], fieldName: filter.fieldName, existsSelected: filter.existsSelected ?? false, exclude: filter.exclude ?? false, })); - return rison.encode(modifiedFilters); }; diff --git a/x-pack/plugins/security_solution/cypress/e2e/dashboards/entity_analytics.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/dashboards/entity_analytics.cy.ts index b5c2b07dc72b6..525ee79a8e1dc 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/dashboards/entity_analytics.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/dashboards/entity_analytics.cy.ts @@ -47,7 +47,7 @@ describe('Entity Analytics Dashboard', () => { }); describe('Without data', () => { - before(() => { + beforeEach(() => { visit(ENTITY_ANALYTICS_URL); }); @@ -64,7 +64,9 @@ describe('Entity Analytics Dashboard', () => { before(() => { esArchiverLoad('risk_hosts_no_data'); esArchiverLoad('risk_users_no_data'); + }); + beforeEach(() => { visit(ENTITY_ANALYTICS_URL); }); @@ -86,7 +88,9 @@ describe('Entity Analytics Dashboard', () => { before(() => { esArchiverLoad('risk_hosts_legacy_data'); esArchiverLoad('risk_users_legacy_data'); + }); + beforeEach(() => { visit(ENTITY_ANALYTICS_URL); }); @@ -107,6 +111,9 @@ describe('Entity Analytics Dashboard', () => { describe('With host risk data', () => { before(() => { esArchiverLoad('risk_hosts'); + }); + + beforeEach(() => { visit(ENTITY_ANALYTICS_URL); }); @@ -137,6 +144,9 @@ describe('Entity Analytics Dashboard', () => { describe('With alerts data', () => { before(() => { createCustomRuleEnabled(getNewRule()); + }); + + beforeEach(() => { visit(ALERTS_URL); waitForAlertsToPopulate(); visit(ENTITY_ANALYTICS_URL); @@ -161,6 +171,9 @@ describe('Entity Analytics Dashboard', () => { describe('With user risk data', () => { before(() => { esArchiverLoad('risk_users'); + }); + + beforeEach(() => { visit(ENTITY_ANALYTICS_URL); }); @@ -191,6 +204,9 @@ describe('Entity Analytics Dashboard', () => { describe('With alerts data', () => { before(() => { createCustomRuleEnabled(getNewRule()); + }); + + beforeEach(() => { visit(ALERTS_URL); waitForAlertsToPopulate(); visit(ENTITY_ANALYTICS_URL); @@ -213,7 +229,7 @@ describe('Entity Analytics Dashboard', () => { }); describe('With anomalies data', () => { - before(() => { + beforeEach(() => { visit(ENTITY_ANALYTICS_URL); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alert_details/navigation.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alert_details/navigation.cy.ts index 4e9953b88e495..32a582cbbeac7 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_alert_details/navigation.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alert_details/navigation.cy.ts @@ -17,6 +17,7 @@ import { ALERTS_URL } from '../../urls/navigation'; import { OPEN_ALERT_DETAILS_PAGE_CONTEXT_MENU_BTN, TIMELINE_CONTEXT_MENU_BTN, + ALERTS_REFRESH_BTN, } from '../../screens/alerts'; import { PAGE_TITLE } from '../../screens/common/page'; import { OPEN_ALERT_DETAILS_PAGE } from '../../screens/alerts_details'; @@ -29,12 +30,21 @@ describe('Alert Details Page Navigation', () => { cleanKibana(); login(); createCustomRuleEnabled(rule, 'rule1'); - visit(ALERTS_URL); - waitForAlertsPanelToBeLoaded(); }); describe('context menu', () => { + beforeEach(() => { + visit(ALERTS_URL); + waitForAlertsPanelToBeLoaded(); + }); + it('should navigate to the details page from the alert context menu', () => { + // Sometimes the alerts are not loaded yet, so we need to refresh the page + cy.get(TIMELINE_CONTEXT_MENU_BTN).then(($btns) => { + if ($btns.length === 0) { + cy.get(ALERTS_REFRESH_BTN).click(); + } + }); cy.get(TIMELINE_CONTEXT_MENU_BTN).first().click({ force: true }); cy.get(OPEN_ALERT_DETAILS_PAGE_CONTEXT_MENU_BTN).click({ force: true }); cy.get(PAGE_TITLE).should('contain.text', rule.name); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_flyout.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_flyout.cy.ts index 7f3eef4015ba2..d2b5f88994658 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_flyout.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alert_flyout.cy.ts @@ -34,6 +34,9 @@ describe('Alert Flyout', () => { cleanKibana(); login(); createCustomRuleEnabled(getNewRule(), 'rule1'); + }); + + beforeEach(() => { visitWithoutDateRange(ALERTS_URL); const dateContainingAllEvents = 'Jul 27, 2015 @ 00:00:00.000'; setStartDate(dateContainingAllEvents); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_details.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_details.cy.ts index 31af8147b1940..6471fbb98e81f 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_details.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_details.cy.ts @@ -36,6 +36,13 @@ describe('Alert details with unmapped fields', () => { waitForAlertsToPopulate(); expandFirstAlert(); }); + + beforeEach(() => { + visitWithoutDateRange(ALERTS_URL); + waitForAlertsToPopulate(); + expandFirstAlert(); + }); + after(() => { esArchiverUnload('unmapped_fields'); }); @@ -52,7 +59,7 @@ describe('Alert details with unmapped fields', () => { }); it('Displays the unmapped field on the table', () => { - const expectedUnmmappedField = { + const expectedUnmappedField = { field: 'unmapped', text: 'This is the unmapped field', }; @@ -61,9 +68,10 @@ describe('Alert details with unmapped fields', () => { cy.get(ALERT_FLYOUT).find(pageSelector(4)).click({ force: true }); cy.get(ALERT_FLYOUT) .find(TABLE_ROWS) + .last() .within(() => { - cy.get(CELL_TEXT).should('contain', expectedUnmmappedField.field); - cy.get(CELL_TEXT).should('contain', expectedUnmmappedField.text); + cy.get(CELL_TEXT).should('contain', expectedUnmappedField.field); + cy.get(CELL_TEXT).should('contain', expectedUnmappedField.text); }); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/detection_page_filters.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/detection_page_filters.cy.ts index c246f28ac09b3..f3ff1569a4cb7 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/detection_page_filters.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/detection_page_filters.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { encode } from '@kbn/rison'; import { getNewRule } from '../../objects/rule'; import { CONTROL_FRAMES, @@ -58,6 +59,10 @@ describe('Detections : Page Filters', () => { cleanKibana(); login(); createCustomRuleEnabled(getNewRule(), 'custom_rule_filters'); + }); + + beforeEach(() => { + login(); visit(ALERTS_URL); waitForAlerts(); waitForPageFilters(); @@ -83,7 +88,7 @@ describe('Detections : Page Filters', () => { cy.url().then((url) => { const currURL = new URL(url); - currURL.searchParams.set('pageFilters', formatPageFilterSearchParam(NEW_FILTERS)); + currURL.searchParams.set('pageFilters', encode(formatPageFilterSearchParam(NEW_FILTERS))); cy.visit(currURL.toString()); waitForAlerts(); assertFilterControlsWithFilterObject(NEW_FILTERS); @@ -104,7 +109,7 @@ describe('Detections : Page Filters', () => { cy.url().then((url) => { const currURL = new URL(url); - currURL.searchParams.set('pageFilters', pageFilterUrlString); + currURL.searchParams.set('pageFilters', encode(pageFilterUrlString)); cy.visit(currURL.toString()); waitForAlerts(); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/all_rules_read_only.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/all_rules_read_only.cy.ts index ad2222d54fb3b..b0915305e23ba 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/all_rules_read_only.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/all_rules_read_only.cy.ts @@ -27,6 +27,9 @@ describe('All rules - read only', () => { cleanKibana(); createCustomRule(getNewRule(), '1'); login(ROLES.reader); + }); + + beforeEach(() => { visitWithoutDateRange(SECURITY_DETECTIONS_RULES_URL, ROLES.reader); waitForRulesTableToBeLoaded(); cy.get(RULE_NAME).should('have.text', getNewRule().name); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/indicator_match_rule.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/indicator_match_rule.cy.ts index 23e27dff84b3f..2114dd3b1fe63 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/indicator_match_rule.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/indicator_match_rule.cy.ts @@ -123,18 +123,19 @@ describe('indicator match', () => { esArchiverLoad('suspicious_source_event'); login(); }); + after(() => { esArchiverUnload('threat_indicator'); esArchiverUnload('suspicious_source_event'); }); describe('Creating new indicator match rules', () => { - before(() => { - visitWithoutDateRange(RULE_CREATION); - selectIndicatorMatchType(); - }); - describe('Index patterns', () => { + beforeEach(() => { + visitWithoutDateRange(RULE_CREATION); + selectIndicatorMatchType(); + }); + it('Contains a predefined index pattern', () => { getIndicatorIndex().should('have.text', getIndexPatterns().join('')); }); @@ -153,7 +154,7 @@ describe('indicator match', () => { }); describe('Indicator index patterns', () => { - before(() => { + beforeEach(() => { visitWithoutDateRange(RULE_CREATION); selectIndicatorMatchType(); }); @@ -174,7 +175,7 @@ describe('indicator match', () => { }); describe('custom query input', () => { - before(() => { + beforeEach(() => { visitWithoutDateRange(RULE_CREATION); selectIndicatorMatchType(); }); @@ -190,10 +191,11 @@ describe('indicator match', () => { }); describe('custom indicator query input', () => { - before(() => { + beforeEach(() => { visitWithoutDateRange(RULE_CREATION); selectIndicatorMatchType(); }); + it(`Has a default set of ${DEFAULT_THREAT_MATCH_QUERY}`, () => { getCustomIndicatorQueryInput().should('have.text', DEFAULT_THREAT_MATCH_QUERY); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/exceptions/add_edit_flyout/flyout_validation.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/add_edit_flyout/flyout_validation.cy.ts index fcde59d0bd79a..f96af6b5f2572 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/exceptions/add_edit_flyout/flyout_validation.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/exceptions/add_edit_flyout/flyout_validation.cy.ts @@ -85,6 +85,9 @@ describe('Exceptions flyout', () => { ], }) ); + }); + + beforeEach(() => { visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); goToRuleDetails(); cy.get(RULE_STATUS).should('have.text', '—'); diff --git a/x-pack/plugins/security_solution/cypress/e2e/exceptions/exceptions_management_flow/exceptions_table.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/exceptions_management_flow/exceptions_table.cy.ts index 42ad3c20962aa..d571d7cd4fae8 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/exceptions/exceptions_management_flow/exceptions_table.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/exceptions/exceptions_management_flow/exceptions_table.cy.ts @@ -65,7 +65,9 @@ describe('Exceptions Table', () => { createExceptionList(getExceptionList1(), getExceptionList1().list_id).as( 'exceptionListResponse' ); + }); + beforeEach(() => { visitWithoutDateRange(EXCEPTIONS_URL); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/add_edit_endpoint_exception.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/add_edit_endpoint_exception.cy.ts index da975710c7f39..9e5ee8b393282 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/add_edit_endpoint_exception.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/add_edit_endpoint_exception.cy.ts @@ -56,9 +56,6 @@ describe('Add endpoint exception from rule details', () => { esArchiverResetKibana(); esArchiverLoad('auditbeat'); login(); - }); - - before(() => { deleteAlertsAndRules(); // create rule with exception createEndpointExceptionList().then((response) => { @@ -79,7 +76,9 @@ describe('Add endpoint exception from rule details', () => { '2' ); }); + }); + beforeEach(() => { visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); goToRuleDetails(); goToEndpointExceptionsTab(); diff --git a/x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/read_only_view.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/read_only_view.cy.ts index b11c688520b1a..9bc7d19eb44f7 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/read_only_view.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/read_only_view.cy.ts @@ -54,6 +54,9 @@ describe('Exceptions viewer read only', () => { }); login(ROLES.reader); + }); + + beforeEach(() => { visitWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL, ROLES.reader); goToRuleDetails(); goToExceptionsTab(); diff --git a/x-pack/plugins/security_solution/cypress/e2e/header/navigation.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/header/navigation.cy.ts index ec48304c382cf..ee031142894aa 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/header/navigation.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/header/navigation.cy.ts @@ -77,12 +77,12 @@ import { THREAT_INTELLIGENCE_PAGE, } from '../../screens/kibana_navigation'; -before(() => { - login(); -}); - describe('top-level navigation common to all pages in the Security app', () => { before(() => { + login(); + }); + + beforeEach(() => { visit(TIMELINES_URL); }); @@ -203,12 +203,11 @@ describe('top-level navigation common to all pages in the Security app', () => { }); describe('Kibana navigation to all pages in the Security app ', () => { - before(() => { - visit(KIBANA_HOME); - }); beforeEach(() => { + visit(KIBANA_HOME); openKibanaNavigation(); }); + it('navigates to the Dashboards page', () => { navigateFromKibanaCollapsibleTo(DASHBOARDS_PAGE); cy.url().should('include', DASHBOARDS_URL); diff --git a/x-pack/plugins/security_solution/cypress/e2e/header/search_bar.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/header/search_bar.cy.ts index e09dac46c04e7..073ee64a8212f 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/header/search_bar.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/header/search_bar.cy.ts @@ -25,6 +25,9 @@ import { waitForAllHostsToBeLoaded } from '../../tasks/hosts/all_hosts'; describe('SearchBar', () => { before(() => { login(); + }); + + beforeEach(() => { visit(HOSTS_URL); waitForAllHostsToBeLoaded(); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/hosts/events_viewer.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/hosts/events_viewer.cy.ts index a45a95e6c68fa..0929a673828c1 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/hosts/events_viewer.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/hosts/events_viewer.cy.ts @@ -60,12 +60,9 @@ describe('Events Viewer', () => { }); context('Fields rendering', () => { - before(() => { + beforeEach(() => { visit(HOSTS_URL); openEvents(); - }); - - beforeEach(() => { openEventsViewerFieldsBrowser(); }); @@ -92,7 +89,7 @@ describe('Events Viewer', () => { }); context('Events viewer query modal', () => { - before(() => { + beforeEach(() => { visit(HOSTS_URL); openEvents(); }); @@ -105,12 +102,9 @@ describe('Events Viewer', () => { }); context('Events viewer fields behaviour', () => { - before(() => { + beforeEach(() => { visit(HOSTS_URL); openEvents(); - }); - - beforeEach(() => { openEventsViewerFieldsBrowser(); }); @@ -135,7 +129,7 @@ describe('Events Viewer', () => { }); context('Events behavior', () => { - before(() => { + beforeEach(() => { visit(HOSTS_URL); openEvents(); waitsForEventsToBeLoaded(); diff --git a/x-pack/plugins/security_solution/cypress/e2e/hosts/host_risk_tab.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/hosts/host_risk_tab.cy.ts index cf35a51e49865..bc8ccf8bcbe61 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/hosts/host_risk_tab.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/hosts/host_risk_tab.cy.ts @@ -27,6 +27,9 @@ describe('risk tab', () => { cleanKibana(); esArchiverLoad('risk_hosts'); login(); + }); + + beforeEach(() => { visit(HOSTS_URL); navigateToHostRiskDetailTab(); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/hosts/inspect.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/hosts/inspect.cy.ts index 8246222f5598d..d562db678e79b 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/hosts/inspect.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/hosts/inspect.cy.ts @@ -18,10 +18,12 @@ describe('Inspect', () => { before(() => { login(); }); + context('Hosts stats and tables', () => { - before(() => { + beforeEach(() => { visit(HOSTS_URL); }); + afterEach(() => { closesModal(); }); @@ -35,7 +37,7 @@ describe('Inspect', () => { }); context('Hosts details', () => { - before(() => { + beforeEach(() => { visitHostDetailsPage('test.local'); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/network/inspect.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/network/inspect.cy.ts index c54072799b290..ff5054187f860 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/network/inspect.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/network/inspect.cy.ts @@ -16,8 +16,12 @@ describe('Inspect', () => { context('Network stats and tables', () => { before(() => { login(); + }); + + beforeEach(() => { visit(NETWORK_URL); }); + afterEach(() => { closesModal(); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/network/overflow_items.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/network/overflow_items.cy.ts index ed84a7855fe8e..961e86308e3e6 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/network/overflow_items.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/network/overflow_items.cy.ts @@ -28,6 +28,9 @@ describe('Overflow items', () => { before(() => { esArchiverLoad('network'); login(); + }); + + beforeEach(() => { visit(NETWORK_URL); cy.get(DESTINATION_DOMAIN).should('not.exist'); cy.get(FILTER_IN).should('not.exist'); diff --git a/x-pack/plugins/security_solution/cypress/e2e/overview/overview.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/overview/overview.cy.ts index 97dd53c9b591b..0bfd1cc88cec7 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/overview/overview.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/overview/overview.cy.ts @@ -25,6 +25,9 @@ describe('Overview Page', () => { before(() => { cleanKibana(); esArchiverLoad('overview'); + }); + + beforeEach(() => { visit(OVERVIEW_URL); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/pagination/pagination.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/pagination/pagination.cy.ts index fd63e2957f5fe..f0256a1b34b4b 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/pagination/pagination.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/pagination/pagination.cy.ts @@ -15,7 +15,7 @@ import { waitsForEventsToBeLoaded } from '../../tasks/hosts/events'; import { openEvents, openUncommonProcesses } from '../../tasks/hosts/main'; import { waitForUncommonProcessesToBeLoaded } from '../../tasks/hosts/uncommon_processes'; import { login, visit } from '../../tasks/login'; -import { goToFirstPage, goToSecondPage, sortFirstColumn } from '../../tasks/pagination'; +import { goToSecondPage, sortFirstColumn } from '../../tasks/pagination'; import { refreshPage } from '../../tasks/security_header'; import { HOSTS_URL, USERS_URL, HOSTS_PAGE_TAB_URLS } from '../../urls/navigation'; import { ALL_HOSTS_TABLE } from '../../screens/hosts/all_hosts'; @@ -29,17 +29,17 @@ describe('Pagination', () => { describe('Host uncommon processes table)', () => { before(() => { esArchiverLoad('host_uncommon_processes'); + }); + + beforeEach(() => { visit(HOSTS_PAGE_TAB_URLS.uncommonProcesses); waitForUncommonProcessesToBeLoaded(); }); + after(() => { esArchiverUnload('host_uncommon_processes'); }); - afterEach(() => { - goToFirstPage(); - }); - it('pagination updates results and page number', () => { cy.get(UNCOMMON_PROCESSES_TABLE) .find(FIRST_PAGE_SELECTOR) diff --git a/x-pack/plugins/security_solution/cypress/e2e/timelines/bulk_add_to_timeline.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/bulk_add_to_timeline.cy.ts index 1d419c5bd75d4..d79569097a137 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/timelines/bulk_add_to_timeline.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/timelines/bulk_add_to_timeline.cy.ts @@ -20,7 +20,6 @@ import { esArchiverLoad, esArchiverUnload } from '../../tasks/es_archiver'; import { waitsForEventsToBeLoaded } from '../../tasks/hosts/events'; import { openEvents, openSessions } from '../../tasks/hosts/main'; import { login, visit } from '../../tasks/login'; -import { closeTimelineUsingCloseButton } from '../../tasks/security_main'; import { ALERTS_URL, HOSTS_URL } from '../../urls/navigation'; const assertFirstPageEventsAddToTimeline = () => { @@ -59,16 +58,13 @@ describe('Bulk Investigate in Timeline', () => { context('Alerts', () => { before(() => { createCustomRuleEnabled(getNewRule()); - visit(ALERTS_URL); }); + beforeEach(() => { + visit(ALERTS_URL); waitForAlertsToPopulate(); }); - afterEach(() => { - closeTimelineUsingCloseButton(); - }); - it('Adding multiple alerts to the timeline should be successful', () => { assertFirstPageEventsAddToTimeline(); }); @@ -79,16 +75,12 @@ describe('Bulk Investigate in Timeline', () => { }); context('Host -> Events Viewer', () => { - before(() => { + beforeEach(() => { visit(HOSTS_URL); openEvents(); waitsForEventsToBeLoaded(); }); - afterEach(() => { - closeTimelineUsingCloseButton(); - }); - it('Adding multiple alerts to the timeline should be successful', () => { assertFirstPageEventsAddToTimeline(); }); @@ -99,16 +91,12 @@ describe('Bulk Investigate in Timeline', () => { }); context('Host -> Sessions Viewer', () => { - before(() => { + beforeEach(() => { visit(HOSTS_URL); openSessions(); waitsForEventsToBeLoaded(); }); - afterEach(() => { - closeTimelineUsingCloseButton(); - }); - it('Adding multiple alerts to the timeline should be successful', () => { assertFirstPageEventsAddToTimeline(); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/timelines/creation.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/creation.cy.ts index d62e73b321d53..62d8fdb8f1b41 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/timelines/creation.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/timelines/creation.cy.ts @@ -49,6 +49,9 @@ describe('Create a timeline from a template', () => { before(() => { deleteTimelines(); createTimelineTemplate(getTimeline()); + }); + + beforeEach(() => { visitWithoutDateRange(TIMELINE_TEMPLATES_URL); }); @@ -67,15 +70,15 @@ describe('Create a timeline from a template', () => { describe('Timelines', (): void => { before(() => { cleanKibana(); - login(); - visit(OVERVIEW_URL); }); describe('Toggle create timeline from plus icon', () => { - after(() => { - closeTimeline(); - }); context('Privileges: CRUD', () => { + before(() => { + login(); + visit(OVERVIEW_URL); + }); + it('toggle create timeline ', () => { createNewTimeline(); addNameAndDescriptionToTimeline(getTimeline()); @@ -88,6 +91,7 @@ describe('Timelines', (): void => { login(ROLES.reader); visit(OVERVIEW_URL, undefined, ROLES.reader); }); + it('should not be able to create/update timeline ', () => { createNewTimeline(); cy.get(TIMELINE_PANEL).should('be.visible'); @@ -103,19 +107,15 @@ describe('Timelines', (): void => { }); describe('Creates a timeline by clicking untitled timeline from bottom bar', () => { - after(() => { - closeTimeline(); - }); - before(() => { login(); + }); + + beforeEach(() => { visit(OVERVIEW_URL); openTimelineUsingToggle(); addNameAndDescriptionToTimeline(getTimeline()); populateTimeline(); - }); - - beforeEach(() => { goToQueryTab(); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/timelines/data_providers.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/data_providers.cy.ts index feb82397fe60c..68b646265d213 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/timelines/data_providers.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/timelines/data_providers.cy.ts @@ -22,7 +22,6 @@ import { addNameAndDescriptionToTimeline, populateTimeline, waitForTimelineChanges, - closeTimeline, createNewTimeline, updateDataProviderByFieldHoverAction, } from '../../tasks/timeline'; @@ -34,21 +33,17 @@ describe('timeline data providers', () => { before(() => { cleanKibana(); login(); - visit(HOSTS_URL); - waitForAllHostsToBeLoaded(); - scrollToBottom(); }); beforeEach(() => { + visit(HOSTS_URL); + waitForAllHostsToBeLoaded(); + scrollToBottom(); createNewTimeline(); addNameAndDescriptionToTimeline(getTimeline()); populateTimeline(); }); - afterEach(() => { - closeTimeline(); - }); - it('displays the data provider action menu when Enter is pressed', (done) => { addDataProvider({ field: 'host.name', operator: 'exists' }).then(() => { cy.get(TIMELINE_DATA_PROVIDERS_ACTION_MENU).should('not.exist'); diff --git a/x-pack/plugins/security_solution/cypress/e2e/timelines/fields_browser.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/fields_browser.cy.ts index dd6d1b80507bc..963fca415b2fc 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/timelines/fields_browser.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/timelines/fields_browser.cy.ts @@ -23,7 +23,6 @@ import { cleanKibana } from '../../tasks/common'; import { addsHostGeoCityNameToTimeline, addsHostGeoContinentNameToTimeline, - clearFieldsBrowser, closeFieldsBrowser, filterFieldsBrowser, toggleCategoryFilter, @@ -56,17 +55,13 @@ describe('Fields Browser', () => { login(); }); context('Fields Browser rendering', () => { - before(() => { + beforeEach(() => { visit(HOSTS_URL); openTimelineUsingToggle(); populateTimeline(); openTimelineFieldsBrowser(); }); - afterEach(() => { - clearFieldsBrowser(); - }); - it('displays all categories (by default)', () => { cy.get(FIELDS_BROWSER_SELECTED_CATEGORIES_BADGES).should('be.empty'); }); @@ -126,18 +121,13 @@ describe('Fields Browser', () => { }); context('Editing the timeline', () => { - before(() => { + beforeEach(() => { visit(HOSTS_URL); openTimelineUsingToggle(); populateTimeline(); openTimelineFieldsBrowser(); }); - afterEach(() => { - openTimelineFieldsBrowser(); - clearFieldsBrowser(); - }); - it('removes the message field from the timeline when the user un-checks the field', () => { cy.get(FIELDS_BROWSER_MESSAGE_HEADER).should('exist'); diff --git a/x-pack/plugins/security_solution/cypress/e2e/timelines/flyout_button.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/flyout_button.cy.ts index b4285ffe0f885..ba0ca01d203d5 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/timelines/flyout_button.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/timelines/flyout_button.cy.ts @@ -27,6 +27,9 @@ describe('timeline flyout button', () => { before(() => { cleanKibana(); login(); + }); + + beforeEach(() => { visit(HOSTS_URL); waitForAllHostsToBeLoaded(); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/timelines/full_screen.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/full_screen.cy.ts index 819edfee5ffe5..1ea2e723bd1fb 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/timelines/full_screen.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/timelines/full_screen.cy.ts @@ -22,6 +22,9 @@ describe('Toggle full screen', () => { before(() => { cleanKibana(); login(); + }); + + beforeEach(() => { visit(HOSTS_URL); openTimelineUsingToggle(); populateTimeline(); @@ -35,6 +38,7 @@ describe('Toggle full screen', () => { }); it('Should show timeline header and tab list area', () => { + enterFullScreenMode(); exitFullScreenMode(); cy.get(TIMELINE_TABS).should('exist'); cy.get(TIMELINE_HEADER).should('be.visible'); diff --git a/x-pack/plugins/security_solution/cypress/e2e/timelines/notes_tab.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/notes_tab.cy.ts index a6691225808ef..c386abace9724 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/timelines/notes_tab.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/timelines/notes_tab.cy.ts @@ -44,12 +44,17 @@ describe('Timeline notes tab', () => { refreshTimelinesUntilTimeLinePresent(timelineId) // This cy.wait is here because we cannot do a pipe on a timeline as that will introduce multiple URL // request responses and indeterminism since on clicks to activates URL's. - .then(() => cy.wait(1000)) - .then(() => openTimelineById(timelineId)) - .then(() => goToNotesTab()) + .then(() => cy.wrap(timelineId).as('timelineId')) ); }); + beforeEach(function () { + visitWithoutDateRange(TIMELINES_URL); + openTimelineById(this?.timelineId as string) + .then(() => goToNotesTab()) + .then(() => cy.wait(1000)); + }); + it('should render mockdown', () => { addNotesToTimeline(getTimelineNonValidQuery().notes); cy.get(NOTES_TEXT_AREA).should('exist'); diff --git a/x-pack/plugins/security_solution/cypress/e2e/timelines/open_timeline.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/open_timeline.cy.ts index a84330df1b833..a392b83276cdd 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/timelines/open_timeline.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/timelines/open_timeline.cy.ts @@ -22,7 +22,6 @@ import { cleanKibana } from '../../tasks/common'; import { login, visitWithoutDateRange } from '../../tasks/login'; import { - closeOpenTimelineModal, markAsFavorite, openTimelineById, openTimelineFromSettings, @@ -44,6 +43,7 @@ describe('Open timeline', () => { refreshTimelinesUntilTimeLinePresent(timelineId) // This cy.wait is here because we cannot do a pipe on a timeline as that will introduce multiple URL // request responses and indeterminism since on clicks to activates URL's. + .then(() => cy.wrap(timelineId).as('timelineId')) .then(() => cy.wait(1000)) .then(() => addNoteToTimeline(getTimeline().notes, timelineId).should((response) => @@ -57,12 +57,10 @@ describe('Open timeline', () => { }); describe('Open timeline modal', () => { - before(() => { + beforeEach(function () { + visitWithoutDateRange(TIMELINES_URL); openTimelineFromSettings(); - }); - - after(() => { - closeOpenTimelineModal(); + openTimelineById(this.timelineId); }); it('should open a modal', () => { diff --git a/x-pack/plugins/security_solution/cypress/e2e/timelines/overview.cy.tsx b/x-pack/plugins/security_solution/cypress/e2e/timelines/overview.cy.tsx index 3e87ee30e29b9..9683ee81903a5 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/timelines/overview.cy.tsx +++ b/x-pack/plugins/security_solution/cypress/e2e/timelines/overview.cy.tsx @@ -34,10 +34,10 @@ describe('timeline overview search', () => { createTimeline(getTimeline()); login(); - visitWithoutDateRange(TIMELINES_URL); }); beforeEach(() => { + visitWithoutDateRange(TIMELINES_URL); cy.get(TIMELINES_OVERVIEW_SEARCH).clear(); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/timelines/pagination.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/pagination.cy.ts index bc8635a9a9116..a354fb8359f50 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/timelines/pagination.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/timelines/pagination.cy.ts @@ -29,10 +29,14 @@ describe('Pagination', () => { cleanKibana(); esArchiverLoad('timeline'); login(); + }); + + beforeEach(() => { visit(HOSTS_URL); openTimelineUsingToggle(); populateTimeline(); }); + after(() => { esArchiverUnload('timeline'); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/timelines/query_tab.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/query_tab.cy.ts index 2e5ec0576199f..07a06139e2866 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/timelines/query_tab.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/timelines/query_tab.cy.ts @@ -22,7 +22,6 @@ import { cleanKibana } from '../../tasks/common'; import { login, visitWithoutDateRange } from '../../tasks/login'; import { addFilter, - closeTimeline, openTimelineById, persistNoteToFirstEvent, pinFirstEvent, @@ -42,6 +41,7 @@ describe('Timeline query tab', () => { refreshTimelinesUntilTimeLinePresent(timelineId) // This cy.wait is here because we cannot do a pipe on a timeline as that will introduce multiple URL // request responses and indeterminism since on clicks to activates URL's. + .then(() => cy.wrap(timelineId).as('timelineId')) .then(() => cy.wait(1000)) .then(() => addNoteToTimeline(getTimeline().notes, timelineId).should((response) => @@ -56,8 +56,9 @@ describe('Timeline query tab', () => { }); describe('Query tab', () => { - after(() => { - closeTimeline(); + beforeEach(function () { + visitWithoutDateRange(TIMELINES_URL); + openTimelineById(this.timelineId).then(() => addFilter(getTimeline().filter)); }); it('should contain the right query', () => { diff --git a/x-pack/plugins/security_solution/cypress/e2e/timelines/search_or_filter.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/search_or_filter.cy.ts index 39420b27e3866..4317365c1aaab 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/timelines/search_or_filter.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/timelines/search_or_filter.cy.ts @@ -30,6 +30,7 @@ describe('Timeline search and filters', () => { cleanKibana(); login(); }); + describe('timeline search or filter KQL bar', () => { beforeEach(() => { visit(HOSTS_URL); @@ -54,13 +55,10 @@ describe('Timeline search and filters', () => { }); describe('Update kqlMode for timeline', () => { - before(() => { + beforeEach(() => { visitWithoutDateRange(TIMELINES_URL); waitForTimelinesPanelToBeLoaded(); openTimelineUsingToggle(); - }); - - beforeEach(() => { cy.intercept('PATCH', '/api/timeline').as('update'); cy.get(TIMELINE_SEARCH_OR_FILTER) .pipe(($el) => $el.trigger('click')) diff --git a/x-pack/plugins/security_solution/cypress/e2e/timelines/toggle_column.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/toggle_column.cy.ts index f531dcfc9fbdf..ee922d42b646c 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/timelines/toggle_column.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/timelines/toggle_column.cy.ts @@ -26,10 +26,10 @@ describe('toggle column in timeline', () => { cleanKibana(); cy.intercept('POST', '/api/timeline/_export?file_name=timelines_export.ndjson').as('export'); login(); - visit(HOSTS_URL); }); beforeEach(() => { + visit(HOSTS_URL); openTimelineUsingToggle(); populateTimeline(); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/users/inspect.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/users/inspect.cy.ts index 41f421baab971..95c0c1f8fa680 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/users/inspect.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/users/inspect.cy.ts @@ -10,7 +10,7 @@ import { INSPECT_MODAL } from '../../screens/inspect'; import { ALL_USERS_TABLE } from '../../screens/users/all_users'; import { AUTHENTICATIONS_TAB } from '../../screens/users/user_authentications'; -import { clickInspectButton, closesModal } from '../../tasks/inspect'; +import { clickInspectButton } from '../../tasks/inspect'; import { login, visit } from '../../tasks/login'; import { USERS_URL } from '../../urls/navigation'; @@ -19,10 +19,10 @@ describe('Inspect', () => { context('Users stats and tables', () => { before(() => { login(); - visit(USERS_URL); }); - afterEach(() => { - closesModal(); + + beforeEach(() => { + visit(USERS_URL); }); it(`inspects all users table`, () => { diff --git a/x-pack/plugins/security_solution/cypress/e2e/users/users_tabs.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/users/users_tabs.cy.ts index c345d5dc66872..3cfc225a4b7d2 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/users/users_tabs.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/users/users_tabs.cy.ts @@ -27,8 +27,12 @@ describe('Users stats and tables', () => { esArchiverLoad('risk_users'); login(); + }); + + beforeEach(() => { visit(USERS_URL); }); + after(() => { esArchiverUnload('users'); esArchiverUnload('risk_users'); diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts.ts b/x-pack/plugins/security_solution/cypress/screens/alerts.ts index 4ab83c7ef69e2..24d8ad383b73f 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts.ts @@ -64,6 +64,12 @@ export const MANAGE_ALERT_DETECTION_RULES_BTN = '[data-test-subj="manage-alert-d export const MARK_ALERT_ACKNOWLEDGED_BTN = '[data-test-subj="acknowledged-alert-status"]'; +export const ALERTS_REFRESH_BTN = '[data-test-subj="querySubmitButton"]'; + +export const ALERTS_HISTOGRAM_PANEL_LOADER = '[data-test-subj="loadingPanelAlertsHistogram"]'; + +export const ALERTS_CONTAINER_LOADING_BAR = '[data-test-subj="events-container-loading-true"]'; + export const NUMBER_OF_ALERTS = '[data-test-subj="events-viewer-panel"] [data-test-subj="server-side-event-count"]'; diff --git a/x-pack/plugins/security_solution/cypress/support/e2e.js b/x-pack/plugins/security_solution/cypress/support/e2e.js index 73a9f1503a47d..8e2ba386125b2 100644 --- a/x-pack/plugins/security_solution/cypress/support/e2e.js +++ b/x-pack/plugins/security_solution/cypress/support/e2e.js @@ -24,10 +24,6 @@ import './commands'; import 'cypress-pipe'; -Cypress.Cookies.defaults({ - preserve: 'sid', -}); - Cypress.on('uncaught:exception', () => { return false; }); diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts index 715c071b9fb68..ee0b56ebd1660 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts @@ -26,6 +26,8 @@ import { TAKE_ACTION_BTN, TAKE_ACTION_MENU, ADD_ENDPOINT_EXCEPTION_BTN, + ALERTS_HISTOGRAM_PANEL_LOADER, + ALERTS_CONTAINER_LOADING_BAR, DATAGRID_CHANGES_IN_PROGRESS, EVENT_CONTAINER_TABLE_NOT_LOADING, CLOSED_ALERTS_FILTER_BTN, @@ -288,6 +290,8 @@ export const waitForAlerts = () => { export const waitForAlertsPanelToBeLoaded = () => { cy.get(LOADING_ALERTS_PANEL).should('exist'); cy.get(LOADING_ALERTS_PANEL).should('not.exist'); + cy.get(ALERTS_CONTAINER_LOADING_BAR).should('not.exist'); + cy.get(ALERTS_HISTOGRAM_PANEL_LOADER).should('not.exist'); }; export const expandAlertTableCellValue = (columnSelector: string, row = 1) => { diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts index db782538ee887..821b4c415fdd8 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts @@ -368,11 +368,7 @@ export const expectNumberOfRules = (expectedNumber: number) => { }; export const expectToContainRule = (ruleName: string) => { - cy.get(RULES_TABLE).then(($table) => { - const rulesRow = cy.wrap($table.find(RULES_ROW)); - - rulesRow.should('include.text', ruleName); - }); + cy.get(RULES_TABLE).find(RULES_ROW).should('include.text', ruleName); }; const selectOverwriteRulesImport = () => { diff --git a/x-pack/plugins/security_solution/cypress/tasks/host_risk.ts b/x-pack/plugins/security_solution/cypress/tasks/host_risk.ts index 8573ec1c642c4..c1817cbea8548 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/host_risk.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/host_risk.ts @@ -26,7 +26,7 @@ export const openRiskTableFilterAndSelectTheCriticalOption = () => { }; export const openRiskTableFilterAndSelectTheLowOption = () => { - cy.get(HOST_BY_RISK_TABLE_FILTER).click(); + cy.get(HOST_BY_RISK_TABLE_FILTER).first().click(); cy.get(HOST_BY_RISK_TABLE_FILTER_LOW).click(); }; diff --git a/x-pack/plugins/security_solution/cypress/tasks/login.ts b/x-pack/plugins/security_solution/cypress/tasks/login.ts index d7568d1c2e880..eb02d393a4764 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/login.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/login.ts @@ -136,19 +136,21 @@ export const deleteRoleAndUser = (role: ROLES) => { }; export const loginWithUser = (user: User) => { - cy.request({ - body: { - providerType: 'basic', - providerName: 'basic', - currentURL: '/', - params: { - username: user.username, - password: user.password, + cy.session(user, () => { + cy.request({ + body: { + providerType: 'basic', + providerName: 'basic', + currentURL: '/', + params: { + username: user.username, + password: user.password, + }, }, - }, - headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, - method: 'POST', - url: constructUrlWithUser(user, LOGIN_API_ENDPOINT), + headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, + method: 'POST', + url: constructUrlWithUser(user, LOGIN_API_ENDPOINT), + }); }); }; @@ -163,19 +165,21 @@ const loginWithRole = async (role: ROLES) => { port: Cypress.env('configport'), } as UrlObject); cy.log(`origin: ${theUrl}`); - cy.request({ - body: { - providerType: 'basic', - providerName: 'basic', - currentURL: '/', - params: { - username: role, - password: 'changeme', + cy.session(role, () => { + cy.request({ + body: { + providerType: 'basic', + providerName: 'basic', + currentURL: '/', + params: { + username: role, + password: 'changeme', + }, }, - }, - headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, - method: 'POST', - url: getUrlWithRoute(role, LOGIN_API_ENDPOINT), + headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, + method: 'POST', + url: getUrlWithRoute(role, LOGIN_API_ENDPOINT), + }); }); }; @@ -215,20 +219,25 @@ const loginViaEnvironmentCredentials = () => { `Authenticating via environment credentials from the \`CYPRESS_${ELASTICSEARCH_USERNAME}\` and \`CYPRESS_${ELASTICSEARCH_PASSWORD}\` environment variables` ); - // programmatically authenticate without interacting with the Kibana login page - cy.request({ - body: { - providerType: 'basic', - providerName: 'basic', - currentURL: '/', - params: { - username: Cypress.env(ELASTICSEARCH_USERNAME), - password: Cypress.env(ELASTICSEARCH_PASSWORD), + const username = Cypress.env(ELASTICSEARCH_USERNAME); + const password = Cypress.env(ELASTICSEARCH_PASSWORD); + + cy.session([username, password], () => { + // programmatically authenticate without interacting with the Kibana login page + cy.request({ + body: { + providerType: 'basic', + providerName: 'basic', + currentURL: '/', + params: { + username, + password, + }, }, - }, - headers: { 'kbn-xsrf': 'cypress-creds-via-env' }, - method: 'POST', - url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`, + headers: { 'kbn-xsrf': 'cypress-creds-via-env' }, + method: 'POST', + url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`, + }); }); }; diff --git a/x-pack/plugins/security_solution/cypress/tasks/timeline.ts b/x-pack/plugins/security_solution/cypress/tasks/timeline.ts index 76a512a6fcb88..7cc90e06cb2e6 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/timeline.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/timeline.ts @@ -328,6 +328,7 @@ export const deleteTimeline = () => { export const markAsFavorite = () => { const click = ($el: Cypress.ObjectLike) => cy.wrap($el).click(); cy.get(STAR_ICON).should('be.visible').pipe(click); + cy.get(LOADING_INDICATOR).should('exist'); cy.get(LOADING_INDICATOR).should('not.exist'); }; diff --git a/x-pack/plugins/security_solution/cypress/tsconfig.json b/x-pack/plugins/security_solution/cypress/tsconfig.json index 070f577c5c2fb..fdb6b295104b1 100644 --- a/x-pack/plugins/security_solution/cypress/tsconfig.json +++ b/x-pack/plugins/security_solution/cypress/tsconfig.json @@ -26,6 +26,7 @@ { "path": "../tsconfig.json", "force": true - } + }, + "@kbn/rison" ] } diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx index 2b8c0d534228d..40ad265849c0a 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/event_details.test.tsx @@ -26,7 +26,7 @@ import { mockAlertDetailsData } from './__mocks__'; import type { TimelineEventsDetailsItem } from '../../../../common/search_strategy'; import { TimelineTabs } from '../../../../common/types/timeline'; import { useInvestigationTimeEnrichment } from '../../containers/cti/event_enrichment'; -import { useGetUserCasesPermissions } from '../../lib/kibana'; +import { useGetUserCasesPermissions, useKibana } from '../../lib/kibana'; import { defaultRowRenderers } from '../../../timelines/components/timeline/body/renderers'; jest.mock('../../../timelines/components/timeline/body/renderers', () => { @@ -43,6 +43,7 @@ jest.mock('../../../timelines/components/timeline/body/renderers', () => { jest.mock('../../lib/kibana'); const originalKibanaLib = jest.requireActual('../../lib/kibana'); +const useKibanaMock = useKibana as jest.Mocked; // Restore the useGetUserCasesPermissions so the calling functions can receive a valid permissions object // The returned permissions object will indicate that the user does not have permissions by default @@ -202,6 +203,30 @@ describe('EventDetails', () => { }); it('render osquery tab', async () => { + const { + services: { osquery }, + } = useKibanaMock(); + if (osquery) { + jest.spyOn(osquery, 'fetchAllLiveQueries').mockReturnValue({ + data: { + // @ts-expect-error - we don't need all the response details to test the functionality + data: { + items: [ + { + _id: 'testId', + _index: 'testIndex', + fields: { + action_id: ['testActionId'], + 'queries.action_id': ['testQueryActionId'], + 'queries.query': ['select * from users'], + '@timestamp': ['2022-09-08T18:16:30.256Z'], + }, + }, + ], + }, + }, + }); + } const newProps = { ...defaultProps, rawEventData: { diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/osquery_tab.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/osquery_tab.tsx index a20f0b2701a29..b8c26c4884b47 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/osquery_tab.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/osquery_tab.tsx @@ -5,24 +5,18 @@ * 2.0. */ -import { - EuiCode, - EuiEmptyPrompt, - EuiFlexGroup, - EuiFlexItem, - EuiNotificationBadge, -} from '@elastic/eui'; +import { EuiCode, EuiEmptyPrompt, EuiNotificationBadge, EuiSpacer } from '@elastic/eui'; import React, { useMemo } from 'react'; import styled from 'styled-components'; import { FormattedMessage } from '@kbn/i18n-react'; import type { Ecs } from '../../../../common/ecs'; import { PERMISSION_DENIED } from '../../../detection_engine/rule_response_actions/osquery/translations'; import { expandDottedObject } from '../../../../common/utils/expand_dotted'; -import { RESPONSE_ACTION_TYPES } from '../../../../common/detection_engine/rule_response_actions/schemas'; import { useIsExperimentalFeatureEnabled } from '../../hooks/use_experimental_features'; import { useKibana } from '../../lib/kibana'; import { EventsViewType } from './event_details'; import * as i18n from './translations'; +import type { RESPONSE_ACTION_TYPES } from '../../../../common/detection_engine/rule_response_actions/schemas/response_actions'; const TabContentWrapper = styled.div` height: 100%; @@ -30,7 +24,7 @@ const TabContentWrapper = styled.div` `; type RuleParameters = Array<{ response_actions: Array<{ - action_type_id: string; + action_type_id: RESPONSE_ACTION_TYPES.OSQUERY; params: Record; }>; }>; @@ -98,45 +92,41 @@ export const useOsqueryTab = ({ return; } - const { OsqueryResults } = osquery; const expandedEventFieldsObject = expandDottedObject( rawEventData.fields ) as ExpandedEventFieldsObject; - const parameters = expandedEventFieldsObject.kibana?.alert?.rule?.parameters; - const responseActions = parameters?.[0].response_actions; + const responseActions = + expandedEventFieldsObject?.kibana?.alert?.rule?.parameters?.[0].response_actions; - const osqueryActionsLength = responseActions?.filter( - (action: { action_type_id: string }) => action.action_type_id === RESPONSE_ACTION_TYPES.OSQUERY - )?.length; - - if (!osqueryActionsLength) { + if (!responseActions?.length) { return; } - const ruleName = expandedEventFieldsObject.kibana?.alert?.rule?.name; - const agentIds = expandedEventFieldsObject.agent?.id; + + const { OsqueryResults, fetchAllLiveQueries } = osquery; const alertId = rawEventData._id; + const { data: actionsData } = fetchAllLiveQueries({ + filterQuery: { term: { alert_ids: alertId } }, + activePage: 0, + limit: 100, + sortField: '@timestamp', + alertId, + }); + const actionItems = actionsData?.data.items || []; + + const ruleName = expandedEventFieldsObject.kibana?.alert?.rule?.name; + const agentIds = expandedEventFieldsObject.agent?.id; + return { id: EventsViewType.osqueryView, 'data-test-subj': 'osqueryViewTab', - name: ( - - - {i18n.OSQUERY_VIEW} - - - - {osqueryActionsLength} - - - + name: i18n.OSQUERY_VIEW, + append: ( + + {actionItems.length} + ), content: ( <> @@ -144,12 +134,15 @@ export const useOsqueryTab = ({ {!application?.capabilities?.osquery?.read ? ( emptyPrompt ) : ( - + <> + + + )} diff --git a/x-pack/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx b/x-pack/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx index 5f36a30779ca3..a72e0aa35f3ad 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx @@ -210,7 +210,7 @@ const useExternalAlertsInitialUrlState = () => { const getInitialUrlParamValue = useGetInitialUrlParamValue(EXTERNAL_ALERTS_URL_PARAM); - const { decodedParam: showExternalAlertsInitialUrlState } = useMemo( + const showExternalAlertsInitialUrlState = useMemo( () => getInitialUrlParamValue(), [getInitialUrlParamValue] ); @@ -218,12 +218,9 @@ const useExternalAlertsInitialUrlState = () => { useEffect(() => { // Only called on component unmount return () => { - replaceUrlParams([ - { - key: EXTERNAL_ALERTS_URL_PARAM, - value: null, - }, - ]); + replaceUrlParams({ + [EXTERNAL_ALERTS_URL_PARAM]: null, + }); }; }, [replaceUrlParams]); @@ -236,11 +233,8 @@ const useExternalAlertsInitialUrlState = () => { const useSyncExternalAlertsUrlState = (showExternalAlerts: boolean) => { const replaceUrlParams = useReplaceUrlParams(); useEffect(() => { - replaceUrlParams([ - { - key: EXTERNAL_ALERTS_URL_PARAM, - value: showExternalAlerts ? 'true' : null, - }, - ]); + replaceUrlParams({ + [EXTERNAL_ALERTS_URL_PARAM]: showExternalAlerts ? true : null, + }); }, [showExternalAlerts, replaceUrlParams]); }; diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/index.tsx b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/index.tsx index d65405cd1c48f..595d9466bfcc7 100644 --- a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/index.tsx @@ -5,291 +5,8 @@ * 2.0. */ -import { pickBy, isEmpty } from 'lodash'; -import type { Plugin } from 'unified'; -import React, { useContext, useMemo, useState, useCallback } from 'react'; -import type { RemarkTokenizer } from '@elastic/eui'; -import { - EuiSpacer, - EuiCodeBlock, - EuiModalHeader, - EuiModalHeaderTitle, - EuiModalBody, - EuiModalFooter, - EuiButton, - EuiButtonEmpty, -} from '@elastic/eui'; -import { useForm, FormProvider } from 'react-hook-form'; -import styled from 'styled-components'; -import type { EuiMarkdownEditorUiPluginEditorProps } from '@elastic/eui/src/components/markdown_editor/markdown_types'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { useKibana } from '../../../../lib/kibana'; -import { LabelField } from './label_field'; -import OsqueryLogo from './osquery_icon/osquery.svg'; -import { OsqueryFlyout } from '../../../../../detections/components/osquery/osquery_flyout'; -import { BasicAlertDataContext } from '../../../event_details/investigation_guide_view'; -import { OsqueryNotAvailablePrompt } from './not_available_prompt'; +import { plugin } from './plugin'; +import { OsqueryParser } from './parser'; +import { OsqueryRenderer } from './renderer'; -const StyledEuiButton = styled(EuiButton)` - > span > img { - margin-block-end: 0; - } -`; - -const OsqueryEditorComponent = ({ - node, - onSave, - onCancel, -}: EuiMarkdownEditorUiPluginEditorProps<{ - configuration: { - label?: string; - query: string; - ecs_mapping: { [key: string]: {} }; - }; -}>) => { - const isEditMode = node != null; - const { - osquery, - application: { - capabilities: { osquery: osqueryPermissions }, - }, - } = useKibana().services; - const formMethods = useForm<{ - label: string; - query: string; - ecs_mapping: Record; - }>({ - defaultValues: { - label: node?.configuration?.label, - query: node?.configuration?.query, - ecs_mapping: node?.configuration?.ecs_mapping, - }, - }); - - const onSubmit = useCallback( - (data) => { - onSave( - `!{osquery${JSON.stringify( - pickBy( - { - query: data.query, - label: data.label, - ecs_mapping: data.ecs_mapping, - }, - (value) => !isEmpty(value) - ) - )}}`, - { - block: true, - } - ); - }, - [onSave] - ); - - const noOsqueryPermissions = useMemo( - () => - (!osqueryPermissions.runSavedQueries || !osqueryPermissions.readSavedQueries) && - !osqueryPermissions.writeLiveQueries, - [ - osqueryPermissions.readSavedQueries, - osqueryPermissions.runSavedQueries, - osqueryPermissions.writeLiveQueries, - ] - ); - - const OsqueryActionForm = useMemo(() => { - if (osquery?.LiveQueryField) { - const { LiveQueryField } = osquery; - - return ( - - - - - - ); - } - return null; - }, [formMethods, osquery]); - - if (noOsqueryPermissions) { - return ; - } - - return ( - <> - - - {isEditMode ? ( - - ) : ( - - )} - - - - - <>{OsqueryActionForm} - - - - - {i18n.translate('xpack.securitySolution.markdown.osquery.modalCancelButtonLabel', { - defaultMessage: 'Cancel', - })} - - - {isEditMode ? ( - - ) : ( - - )} - - - - ); -}; - -const OsqueryEditor = React.memo(OsqueryEditorComponent); - -export const plugin = { - name: 'osquery', - button: { - label: 'Osquery', - iconType: 'logoOsquery', - }, - helpText: ( -
- - {'!{osquery{options}}'} - - -
- ), - editor: OsqueryEditor, -}; - -export const parser: Plugin = function () { - const Parser = this.Parser; - const tokenizers = Parser.prototype.blockTokenizers; - const methods = Parser.prototype.blockMethods; - - const tokenizeOsquery: RemarkTokenizer = function (eat, value, silent) { - if (value.startsWith('!{osquery') === false) return false; - - const nextChar = value[9]; - - if (nextChar !== '{' && nextChar !== '}') return false; // this isn't actually a osquery - - if (silent) { - return true; - } - - // is there a configuration? - const hasConfiguration = nextChar === '{'; - - let match = '!{osquery'; - let configuration = {}; - - if (hasConfiguration) { - let configurationString = ''; - - let openObjects = 0; - - for (let i = 9; i < value.length; i++) { - const char = value[i]; - if (char === '{') { - openObjects++; - configurationString += char; - } else if (char === '}') { - openObjects--; - if (openObjects === -1) { - break; - } - configurationString += char; - } else { - configurationString += char; - } - } - - match += configurationString; - try { - configuration = JSON.parse(configurationString); - } catch (e) { - const now = eat.now(); - this.file.fail(`Unable to parse osquery JSON configuration: ${e}`, { - line: now.line, - column: now.column + 9, - }); - } - } - - match += '}'; - - return eat(match)({ - type: 'osquery', - configuration, - }); - }; - - tokenizers.osquery = tokenizeOsquery; - methods.splice(methods.indexOf('text'), 0, 'osquery'); -}; - -// receives the configuration from the parser and renders -const RunOsqueryButtonRenderer = ({ - configuration, -}: { - configuration: { - label?: string; - query: string; - ecs_mapping: { [key: string]: {} }; - test: []; - }; -}) => { - const [showFlyout, setShowFlyout] = useState(false); - const { agentId, alertId } = useContext(BasicAlertDataContext); - - const handleOpen = useCallback(() => setShowFlyout(true), [setShowFlyout]); - - const handleClose = useCallback(() => setShowFlyout(false), [setShowFlyout]); - - return ( - <> - - {configuration.label ?? - i18n.translate('xpack.securitySolution.markdown.osquery.runOsqueryButtonLabel', { - defaultMessage: 'Run Osquery', - })} - - {showFlyout && ( - - )} - - ); -}; - -export { RunOsqueryButtonRenderer as renderer }; +export { plugin, OsqueryParser as parser, OsqueryRenderer as renderer }; diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/parser.ts b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/parser.ts new file mode 100644 index 0000000000000..2664c9b5c7c4c --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/parser.ts @@ -0,0 +1,76 @@ +/* + * 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 type { Plugin } from 'unified'; +import type { RemarkTokenizer } from '@elastic/eui'; + +export const OsqueryParser: Plugin = function () { + const Parser = this.Parser; + const tokenizers = Parser.prototype.blockTokenizers; + const methods = Parser.prototype.blockMethods; + + const tokenizeOsquery: RemarkTokenizer = function (eat, value, silent) { + if (value.startsWith('!{osquery') === false) return false; + + const nextChar = value[9]; + + if (nextChar !== '{' && nextChar !== '}') return false; // this isn't actually a osquery + + if (silent) { + return true; + } + + // is there a configuration? + const hasConfiguration = nextChar === '{'; + + let match = '!{osquery'; + let configuration = {}; + + if (hasConfiguration) { + let configurationString = ''; + + let openObjects = 0; + + for (let i = 9; i < value.length; i++) { + const char = value[i]; + if (char === '{') { + openObjects++; + configurationString += char; + } else if (char === '}') { + openObjects--; + if (openObjects === -1) { + break; + } + configurationString += char; + } else { + configurationString += char; + } + } + + match += configurationString; + try { + configuration = JSON.parse(configurationString); + } catch (e) { + const now = eat.now(); + this.file.fail(`Unable to parse osquery JSON configuration: ${e}`, { + line: now.line, + column: now.column + 9, + }); + } + } + + match += '}'; + + return eat(match)({ + type: 'osquery', + configuration, + }); + }; + + tokenizers.osquery = tokenizeOsquery; + methods.splice(methods.indexOf('text'), 0, 'osquery'); +}; diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/plugin.tsx b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/plugin.tsx new file mode 100644 index 0000000000000..de433c3602831 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/plugin.tsx @@ -0,0 +1,172 @@ +/* + * 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 { + EuiButton, + EuiButtonEmpty, + EuiCodeBlock, + EuiModalBody, + EuiModalFooter, + EuiModalHeader, + EuiModalHeaderTitle, + EuiSpacer, +} from '@elastic/eui'; +import type { EuiMarkdownEditorUiPluginEditorProps } from '@elastic/eui/src/components/markdown_editor/markdown_types'; +import { FormProvider, useForm } from 'react-hook-form'; +import React, { useCallback, useMemo } from 'react'; +import { isEmpty, pickBy } from 'lodash'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { i18n } from '@kbn/i18n'; +import { LabelField } from './label_field'; +import { OsqueryNotAvailablePrompt } from './not_available_prompt'; +import { useKibana } from '../../../../lib/kibana'; + +const OsqueryEditorComponent = ({ + node, + onSave, + onCancel, +}: EuiMarkdownEditorUiPluginEditorProps<{ + configuration: { + label?: string; + query: string; + ecs_mapping: { [key: string]: {} }; + }; +}>) => { + const isEditMode = node != null; + const { + osquery, + application: { + capabilities: { osquery: osqueryPermissions }, + }, + } = useKibana().services; + const formMethods = useForm<{ + label: string; + query: string; + ecs_mapping: Record; + }>({ + defaultValues: { + label: node?.configuration?.label, + query: node?.configuration?.query, + ecs_mapping: node?.configuration?.ecs_mapping, + }, + }); + + const onSubmit = useCallback( + (data) => { + onSave( + `!{osquery${JSON.stringify( + pickBy( + { + query: data.query, + label: data.label, + ecs_mapping: data.ecs_mapping, + }, + (value) => !isEmpty(value) + ) + )}}`, + { + block: true, + } + ); + }, + [onSave] + ); + + const noOsqueryPermissions = useMemo( + () => + (!osqueryPermissions.runSavedQueries || !osqueryPermissions.readSavedQueries) && + !osqueryPermissions.writeLiveQueries, + [ + osqueryPermissions.readSavedQueries, + osqueryPermissions.runSavedQueries, + osqueryPermissions.writeLiveQueries, + ] + ); + + const OsqueryActionForm = useMemo(() => { + if (osquery?.LiveQueryField) { + const { LiveQueryField } = osquery; + + return ( + + + + + + ); + } + return null; + }, [formMethods, osquery]); + + if (noOsqueryPermissions) { + return ; + } + + return ( + <> + + + {isEditMode ? ( + + ) : ( + + )} + + + + + <>{OsqueryActionForm} + + + + + {i18n.translate('xpack.securitySolution.markdown.osquery.modalCancelButtonLabel', { + defaultMessage: 'Cancel', + })} + + + {isEditMode ? ( + + ) : ( + + )} + + + + ); +}; + +const OsqueryEditor = React.memo(OsqueryEditorComponent); + +export const plugin = { + name: 'osquery', + button: { + label: 'Osquery', + iconType: 'logoOsquery', + }, + helpText: ( +
+ + {'!{osquery{options}}'} + + +
+ ), + editor: OsqueryEditor, +}; diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/renderer.tsx b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/renderer.tsx new file mode 100644 index 0000000000000..f33dec63a6b18 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/renderer.tsx @@ -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. + */ + +// receives the configuration from the parser and renders +import React, { useCallback, useContext, useMemo, useState } from 'react'; +import { reduce } from 'lodash'; +import { i18n } from '@kbn/i18n'; +import styled from 'styled-components'; +import { EuiButton } from '@elastic/eui'; +import { BasicAlertDataContext } from '../../../event_details/investigation_guide_view'; +import { expandDottedObject } from '../../../../../../common/utils/expand_dotted'; +import type { Ecs } from '../../../../../../common/ecs'; +import OsqueryLogo from './osquery_icon/osquery.svg'; +import { OsqueryFlyout } from '../../../../../detections/components/osquery/osquery_flyout'; + +const StyledEuiButton = styled(EuiButton)` + > span > img { + margin-block-end: 0; + } +`; + +export const OsqueryRenderer = ({ + configuration, +}: { + configuration: { + label?: string; + query: string; + ecs_mapping: { [key: string]: {} }; + test: []; + }; +}) => { + const [showFlyout, setShowFlyout] = useState(false); + const { agentId, alertId, data } = useContext(BasicAlertDataContext); + + const handleOpen = useCallback(() => setShowFlyout(true), [setShowFlyout]); + + const handleClose = useCallback(() => setShowFlyout(false), [setShowFlyout]); + + const ecsData = useMemo(() => { + const fieldsMap: Record = reduce( + data, + (acc, eventDetailItem) => ({ + ...acc, + [eventDetailItem.field]: eventDetailItem?.values?.[0], + }), + {} + ); + return expandDottedObject(fieldsMap) as Ecs; + }, [data]); + + return ( + <> + + {configuration.label ?? + i18n.translate('xpack.securitySolution.markdown.osquery.runOsqueryButtonLabel', { + defaultMessage: 'Run Osquery', + })} + + {showFlyout && ( + + )} + + ); +}; diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/parser.ts b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/parser.ts index 1d48cc4d56dd8..a5499f06bddf2 100644 --- a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/parser.ts +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/parser.ts @@ -7,8 +7,8 @@ import type { Plugin } from 'unified'; import type { RemarkTokenizer } from '@elastic/eui'; +import { safeDecode } from '@kbn/rison'; import { parse } from 'query-string'; -import { decodeRisonUrlState } from '../../../../utils/global_query_string/helpers'; import { ID, PREFIX } from './constants'; import * as i18n from './translations'; @@ -73,9 +73,14 @@ export const TimelineParser: Plugin = function () { try { const timelineSearch = timelineUrl.split('?'); const parseTimelineUrlSearch = parse(timelineSearch[1]) as { timeline: string }; - const { id: timelineId = '', graphEventId = '' } = decodeRisonUrlState( - parseTimelineUrlSearch.timeline ?? '' - ) ?? { id: null, graphEventId: '' }; + const decodedTimeline = safeDecode(parseTimelineUrlSearch.timeline ?? '') as { + id?: string; + graphEventId?: string; + } | null; + const { id: timelineId = '', graphEventId = '' } = decodedTimeline ?? { + id: null, + graphEventId: '', + }; if (!timelineId) { this.file.info(i18n.NO_TIMELINE_ID_FOUND, { diff --git a/x-pack/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.ts b/x-pack/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.ts index 7cbf5789df7b4..9f66e4f25e7bd 100644 --- a/x-pack/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.ts +++ b/x-pack/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.ts @@ -19,7 +19,6 @@ import type { import { calculateEndpointAuthz, getEndpointAuthzInitialState, - calculatePermissionsFromCapabilities, } from '../../../../../common/endpoint/service/authz'; import { useSecuritySolutionStartDependencies } from './security_solution_start_dependencies'; import { useIsExperimentalFeatureEnabled } from '../../../hooks/use_experimental_features'; @@ -57,11 +56,6 @@ export const useEndpointPrivileges = (): Immutable => { const [hasHostIsolationExceptionsItems, setHasHostIsolationExceptionsItems] = useState(false); - const securitySolutionPermissions = useMemo( - () => calculatePermissionsFromCapabilities(kibanaServices.application.capabilities), - [kibanaServices.application.capabilities] - ); - const privileges = useMemo(() => { const loading = !userRolesCheckDone || !user || !checkHostIsolationExceptionsDone; @@ -73,7 +67,6 @@ export const useEndpointPrivileges = (): Immutable => { fleetAuthz, userRoles, isEndpointRbacEnabled || isEndpointRbacV1Enabled, - securitySolutionPermissions, hasHostIsolationExceptionsItems ) : getEndpointAuthzInitialState()), @@ -89,7 +82,6 @@ export const useEndpointPrivileges = (): Immutable => { userRoles, isEndpointRbacEnabled, isEndpointRbacV1Enabled, - securitySolutionPermissions, hasHostIsolationExceptionsItems, ]); diff --git a/x-pack/plugins/security_solution/public/common/hooks/timeline/use_query_timeline_by_id_on_url_change.test.ts b/x-pack/plugins/security_solution/public/common/hooks/timeline/use_query_timeline_by_id_on_url_change.test.ts index a2a3b51e6f036..3966ebc6697b2 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/timeline/use_query_timeline_by_id_on_url_change.test.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/timeline/use_query_timeline_by_id_on_url_change.test.ts @@ -7,7 +7,6 @@ import { queryTimelineById } from '../../../timelines/components/open_timeline/helpers'; import { useQueryTimelineByIdOnUrlChange } from './use_query_timeline_by_id_on_url_change'; -import * as urlHelpers from '../../utils/global_query_string/helpers'; import { renderHook } from '@testing-library/react-hooks'; import { timelineDefaults } from '../../../timelines/store/timeline/defaults'; @@ -91,15 +90,11 @@ describe('queryTimelineByIdOnUrlChange', () => { describe('when decode rison fails', () => { it('should not call queryTimelineById', () => { - jest.spyOn(urlHelpers, 'decodeRisonUrlState').mockImplementationOnce(() => { - throw new Error('Unable to decode'); - }); - mockUseLocation.mockReturnValue({ search: oldTimelineRisonSearchString }); const { rerender } = renderHook(() => useQueryTimelineByIdOnUrlChange()); - mockUseLocation.mockReturnValue({ search: newTimelineRisonSearchString }); - jest.clearAllMocks(); + mockUseLocation.mockReturnValue({ search: '?foo=bar' }); + rerender(); expect(queryTimelineById).not.toBeCalled(); diff --git a/x-pack/plugins/security_solution/public/common/hooks/timeline/use_query_timeline_by_id_on_url_change.ts b/x-pack/plugins/security_solution/public/common/hooks/timeline/use_query_timeline_by_id_on_url_change.ts index c307d634d77ee..e56131cd2603c 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/timeline/use_query_timeline_by_id_on_url_change.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/timeline/use_query_timeline_by_id_on_url_change.ts @@ -10,6 +10,7 @@ import { useEffect, useMemo } from 'react'; import { useLocation } from 'react-router-dom'; import usePrevious from 'react-use/lib/usePrevious'; import { useDispatch } from 'react-redux'; +import { safeDecode } from '@kbn/rison'; import type { TimelineUrl } from '../../../timelines/store/timeline/model'; import { timelineActions, timelineSelectors } from '../../../timelines/store/timeline'; import { TimelineId, TimelineTabs } from '../../../../common/types'; @@ -20,7 +21,6 @@ import { queryTimelineById, } from '../../../timelines/components/open_timeline/helpers'; import { - decodeRisonUrlState, getParamFromQueryString, getQueryStringFromLocation, } from '../../utils/global_query_string/helpers'; @@ -51,29 +51,14 @@ export const useQueryTimelineByIdOnUrlChange = () => { urlKey: URL_PARAM_KEY.timeline, search: oldSearch ?? '', }); - const newUrlStateString = getQueryStringKeyValue({ urlKey: URL_PARAM_KEY.timeline, search }); - if (oldUrlStateString != null && newUrlStateString != null) { - let newTimeline = null; - let oldTimeline = null; - - try { - newTimeline = decodeRisonUrlState(newUrlStateString); - } catch (error) { - // do nothing as timeline is defaulted to null - } - - try { - oldTimeline = decodeRisonUrlState(oldUrlStateString); - } catch (error) { - // do nothing as timeline is defaulted to null - } - - return [oldTimeline, newTimeline]; - } - - return [null, null]; + return oldUrlStateString != null && newUrlStateString != null + ? [ + safeDecode(oldUrlStateString) as TimelineUrl | null, + safeDecode(newUrlStateString) as TimelineUrl | null, + ] + : [null, null]; }, [oldSearch, search]); const oldId = previousTimeline?.id; diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_resolve_conflict.test.tsx b/x-pack/plugins/security_solution/public/common/hooks/use_resolve_conflict.test.tsx index ef4a26e52e968..d17b9c16f9d2a 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_resolve_conflict.test.tsx +++ b/x-pack/plugins/security_solution/public/common/hooks/use_resolve_conflict.test.tsx @@ -9,7 +9,6 @@ import { renderHook } from '@testing-library/react-hooks'; import { useDeepEqualSelector } from './use_selector'; import { useKibana } from '../lib/kibana'; import { useResolveConflict } from './use_resolve_conflict'; -import * as urlHelpers from '../utils/global_query_string/helpers'; jest.mock('react-router-dom', () => { const original = jest.requireActual('react-router-dom'); @@ -127,9 +126,6 @@ describe('useResolveConflict', () => { describe('rison is unable to be decoded', () => { it('should use timeline values from redux to create the otherObjectPath', async () => { - jest.spyOn(urlHelpers, 'decodeRisonUrlState').mockImplementation(() => { - throw new Error('Unable to decode'); - }); (useLocation as jest.Mock).mockReturnValue({ pathname: 'my/cool/path', search: '?foo=bar', diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_resolve_conflict.tsx b/x-pack/plugins/security_solution/public/common/hooks/use_resolve_conflict.tsx index 6bd55a9b70b36..d0082f858ca12 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_resolve_conflict.tsx +++ b/x-pack/plugins/security_solution/public/common/hooks/use_resolve_conflict.tsx @@ -8,12 +8,12 @@ import React, { useCallback, useMemo } from 'react'; import { useLocation } from 'react-router-dom'; import { EuiSpacer } from '@elastic/eui'; +import { safeDecode, encode } from '@kbn/rison'; import { useDeepEqualSelector } from './use_selector'; import { TimelineId } from '../../../common/types/timeline'; import { timelineSelectors } from '../../timelines/store/timeline'; import type { TimelineUrl } from '../../timelines/store/timeline/model'; import { timelineDefaults } from '../../timelines/store/timeline/defaults'; -import { decodeRisonUrlState, encodeRisonUrlState } from '../utils/global_query_string/helpers'; import { useKibana } from '../lib/kibana'; import { URL_PARAM_KEY } from './use_url_state'; @@ -53,12 +53,9 @@ export const useResolveConflict = () => { activeTab, graphEventId, }; - let timelineSearch: TimelineUrl = currentTimelineState; - try { - timelineSearch = decodeRisonUrlState(timelineRison) ?? currentTimelineState; - } catch (error) { - // do nothing as it's already defaulted on line 77 - } + const timelineSearch = + (safeDecode(timelineRison ?? '') as TimelineUrl | null) ?? currentTimelineState; + // We have resolved to one object, but another object has a legacy URL alias associated with this ID/page. We should display a // callout with a warning for the user, and provide a way for them to navigate to the other object. const currentObjectId = timelineSearch?.id; @@ -68,7 +65,7 @@ export const useResolveConflict = () => { ...timelineSearch, id: newSavedObjectId, }; - const newTimelineRison = encodeRisonUrlState(newTimelineSearch); + const newTimelineRison = encode(newTimelineSearch); searchQuery.set(URL_PARAM_KEY.timeline, newTimelineRison); const newPath = `${pathname}?${searchQuery.toString()}${window.location.hash}`; diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_resolve_redirect.test.ts b/x-pack/plugins/security_solution/public/common/hooks/use_resolve_redirect.test.ts index 7e3b0f88780c4..c54259649448b 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_resolve_redirect.test.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/use_resolve_redirect.test.ts @@ -10,7 +10,6 @@ import { renderHook } from '@testing-library/react-hooks'; import { useDeepEqualSelector } from './use_selector'; import { useKibana } from '../lib/kibana'; import { useResolveRedirect } from './use_resolve_redirect'; -import * as urlHelpers from '../utils/global_query_string/helpers'; jest.mock('react-router-dom', () => { const original = jest.requireActual('react-router-dom'); @@ -101,9 +100,6 @@ describe('useResolveRedirect', () => { describe('rison is unable to be decoded', () => { it('should use timeline values from redux to create the redirect path', async () => { - jest.spyOn(urlHelpers, 'decodeRisonUrlState').mockImplementation(() => { - throw new Error('Unable to decode'); - }); (useLocation as jest.Mock).mockReturnValue({ pathname: 'my/cool/path', search: '?foo=bar', diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_resolve_redirect.ts b/x-pack/plugins/security_solution/public/common/hooks/use_resolve_redirect.ts index 2f5bf211d8906..e771995e25031 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_resolve_redirect.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/use_resolve_redirect.ts @@ -7,11 +7,11 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { useLocation } from 'react-router-dom'; +import { safeDecode, encode } from '@kbn/rison'; import { useDeepEqualSelector } from './use_selector'; import { TimelineId } from '../../../common/types/timeline'; import { timelineSelectors } from '../../timelines/store/timeline'; import { timelineDefaults } from '../../timelines/store/timeline/defaults'; -import { decodeRisonUrlState, encodeRisonUrlState } from '../utils/global_query_string/helpers'; import { useKibana } from '../lib/kibana'; import type { TimelineUrl } from '../../timelines/store/timeline/model'; import { URL_PARAM_KEY } from './use_url_state'; @@ -42,12 +42,8 @@ export const useResolveRedirect = () => { activeTab, graphEventId, }; - let timelineSearch: TimelineUrl = currentTimelineState; - try { - timelineSearch = decodeRisonUrlState(timelineRison) ?? currentTimelineState; - } catch (error) { - // do nothing as it's already defaulted on line 77 - } + const timelineSearch = + (safeDecode(timelineRison ?? '') as TimelineUrl | null) ?? currentTimelineState; if ( hasRedirected || @@ -64,7 +60,7 @@ export const useResolveRedirect = () => { ...timelineSearch, id: newObjectId, }; - const newTimelineRison = encodeRisonUrlState(newTimelineSearch); + const newTimelineRison = encode(newTimelineSearch); searchQuery.set(URL_PARAM_KEY.timeline, newTimelineRison); const newPath = `${pathname}?${searchQuery.toString()}`; spaces.ui.redirectLegacyUrl({ diff --git a/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts b/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts index f7d94a994b919..6b736e3fbb503 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts @@ -70,6 +70,7 @@ export const useKibana = jest.fn().mockReturnValue({ }, osquery: { OsqueryResults: jest.fn().mockReturnValue(null), + fetchAllLiveQueries: jest.fn().mockReturnValue({ data: { data: { items: [] } } }), }, timelines: createTGridMocks(), savedObjectsTagging: { diff --git a/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx b/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx index 196743d760bf7..2e2cdbdd3eda5 100644 --- a/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx +++ b/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx @@ -40,7 +40,7 @@ import type { ExperimentalFeatures } from '../../../../common/experimental_featu import { APP_UI_ID, APP_PATH } from '../../../../common/constants'; import { KibanaContextProvider, KibanaServices } from '../../lib/kibana'; import { getDeepLinks } from '../../../app/deep_links'; -import { fleetGetPackageListHttpMock } from '../../../management/mocks'; +import { fleetGetPackageHttpMock } from '../../../management/mocks'; const REAL_REACT_DOM_CREATE_PORTAL = ReactDOM.createPortal; @@ -373,5 +373,5 @@ const applyDefaultCoreHttpMocks = (http: AppContextTestRender['coreStart']['http // Need to mock getting the endpoint package from the fleet API because it is used as soon // as the store middleware for Endpoint list is initialized, thus mocking it here would avoid // unnecessary errors being output to the console - fleetGetPackageListHttpMock(http, { ignoreUnMockedApiRouteErrors: true }); + fleetGetPackageHttpMock(http, { ignoreUnMockedApiRouteErrors: true }); }; diff --git a/x-pack/plugins/security_solution/public/common/store/global_url_param/actions.ts b/x-pack/plugins/security_solution/public/common/store/global_url_param/actions.ts index 0b3c90e158151..bccb3418aa577 100644 --- a/x-pack/plugins/security_solution/public/common/store/global_url_param/actions.ts +++ b/x-pack/plugins/security_solution/public/common/store/global_url_param/actions.ts @@ -5,16 +5,17 @@ * 2.0. */ +import type { RisonValue } from '@kbn/rison'; import actionCreatorFactory from 'typescript-fsa'; const actionCreator = actionCreatorFactory('x-pack/security_solution/local/global_url_param'); -export const registerUrlParam = actionCreator<{ key: string; initialValue: string | null }>( +export const registerUrlParam = actionCreator<{ key: string; initialValue: RisonValue | null }>( 'REGISTER_URL_PARAM' ); export const deregisterUrlParam = actionCreator<{ key: string }>('DEREGISTER_URL_PARAM'); -export const updateUrlParam = actionCreator<{ key: string; value: string | null }>( +export const updateUrlParam = actionCreator<{ key: string; value: RisonValue | null }>( 'UPDATE_URL_PARAM' ); diff --git a/x-pack/plugins/security_solution/public/common/store/global_url_param/reducer.ts b/x-pack/plugins/security_solution/public/common/store/global_url_param/reducer.ts index 5e7d91515e9b6..47b1ffbfea076 100644 --- a/x-pack/plugins/security_solution/public/common/store/global_url_param/reducer.ts +++ b/x-pack/plugins/security_solution/public/common/store/global_url_param/reducer.ts @@ -5,10 +5,12 @@ * 2.0. */ +import type { RisonValue } from '@kbn/rison'; +import deepEqual from 'fast-deep-equal'; import { reducerWithInitialState } from 'typescript-fsa-reducers'; import { registerUrlParam, updateUrlParam, deregisterUrlParam } from './actions'; -export type GlobalUrlParam = Record; +export type GlobalUrlParam = Record; export const initialGlobalUrlParam: GlobalUrlParam = {}; @@ -34,8 +36,7 @@ export const globalUrlParamReducer = reducerWithInitialState(initialGlobalUrlPar return nextState; }) .case(updateUrlParam, (state, { key, value }) => { - // Only update the URL after the query param is registered and if the current value is different than the previous value - if (state[key] === undefined || state[key] === value) { + if (state[key] === undefined || deepEqual(state[key], value)) { return state; } diff --git a/x-pack/plugins/security_solution/public/common/utils/global_query_string/helpers.ts b/x-pack/plugins/security_solution/public/common/utils/global_query_string/helpers.ts index 0f3c1ab413fd0..a8120cd0b99cc 100644 --- a/x-pack/plugins/security_solution/public/common/utils/global_query_string/helpers.ts +++ b/x-pack/plugins/security_solution/public/common/utils/global_query_string/helpers.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { decode, encode } from '@kbn/rison'; +import type { RisonValue } from '@kbn/rison'; +import { safeDecode, encode } from '@kbn/rison'; import type { ParsedQuery } from 'query-string'; import { parse, stringify } from 'query-string'; import { url } from '@kbn/kibana-utils-plugin/public'; @@ -19,20 +20,6 @@ export const isDetectionsPages = (pageName: string) => pageName === SecurityPageName.rulesCreate || pageName === SecurityPageName.exceptions; -export const decodeRisonUrlState = (value: string | undefined): T | null => { - try { - return value ? (decode(value) as unknown as T) : null; - } catch (error) { - if (error instanceof Error && error.message.startsWith('rison decoder error')) { - return null; - } - throw error; - } -}; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const encodeRisonUrlState = (state: any) => encode(state); - export const getQueryStringFromLocation = (search: string) => search.substring(1); export const getParamFromQueryString = ( @@ -51,18 +38,19 @@ export const getParamFromQueryString = ( * It doesn't update when the URL changes. * */ -export const useGetInitialUrlParamValue = (urlParamKey: string) => { +export const useGetInitialUrlParamValue = ( + urlParamKey: string +): (() => State | null) => { // window.location.search provides the most updated representation of the url search. // It also guarantees that we don't overwrite URL param managed outside react-router. - const getInitialUrlParamValue = useCallback(() => { - const param = getParamFromQueryString( + const getInitialUrlParamValue = useCallback((): State | null => { + const rawParamValue = getParamFromQueryString( getQueryStringFromLocation(window.location.search), urlParamKey ); + const paramValue = safeDecode(rawParamValue ?? '') as State | null; - const decodedParam = decodeRisonUrlState(param ?? undefined); - - return { param, decodedParam }; + return paramValue; }, [urlParamKey]); return getInitialUrlParamValue; @@ -71,22 +59,30 @@ export const useGetInitialUrlParamValue = (urlParamKey: string) => { export const encodeQueryString = (urlParams: ParsedQuery): string => stringify(url.encodeQuery(urlParams), { sort: false, encode: false }); -export const useReplaceUrlParams = () => { +export const useReplaceUrlParams = (): ((params: Record) => void) => { const history = useHistory(); const replaceUrlParams = useCallback( - (params: Array<{ key: string; value: string | null }>) => { + (params: Record): void => { // window.location.search provides the most updated representation of the url search. // It prevents unnecessary re-renders which useLocation would create because 'replaceUrlParams' does update the location. // window.location.search also guarantees that we don't overwrite URL param managed outside react-router. const search = window.location.search; const urlParams = parse(search, { sort: false }); - params.forEach(({ key, value }) => { + Object.keys(params).forEach((key) => { + const value = params[key]; + if (value == null || value === '') { delete urlParams[key]; - } else { - urlParams[key] = value; + return; + } + + try { + urlParams[key] = encode(value); + } catch { + // eslint-disable-next-line no-console + console.error('Unable to encode url param value'); } }); diff --git a/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.test.tsx b/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.test.tsx index dede5125775c4..24fc87bf7bf61 100644 --- a/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.test.tsx @@ -130,7 +130,7 @@ describe('global query string', () => { expect(mockDispatch).toBeCalledWith( globalUrlParamActions.registerUrlParam({ key: urlParamKey, - initialValue: initialValue.toString(), + initialValue, }) ); }); @@ -140,7 +140,6 @@ describe('global query string', () => { it('dispatch updateUrlParam action', () => { const urlParamKey = 'testKey'; const value = { test: 123 }; - const encodedVaue = '(test:123)'; const globalUrlParam = { [urlParamKey]: 'oldValue', @@ -156,7 +155,7 @@ describe('global query string', () => { expect(mockDispatch).toBeCalledWith( globalUrlParamActions.updateUrlParam({ key: urlParamKey, - value: encodedVaue, + value, }) ); }); @@ -186,10 +185,12 @@ describe('global query string', () => { { ...mockGlobalState, globalUrlParam: { - testNumber: '123', - testObject: '(test:321)', + testNumber: 123, + testObject: { testKey: 321 }, + testEmptyObject: {}, + testEmptyArray: [], testNull: null, - testEmpty: '', + testEmptyString: '', }, }, SUB_PLUGINS_REDUCER, @@ -202,7 +203,7 @@ describe('global query string', () => { const { result } = renderHook(() => useGlobalQueryString(), { wrapper }); - expect(result.current).toEqual('testNumber=123&testObject=(test:321)'); + expect(result.current).toEqual(`testNumber=123&testObject=(testKey:321)`); }); }); @@ -218,7 +219,7 @@ describe('global query string', () => { renderHook(() => useSyncGlobalQueryString(), { wrapper: makeWrapper(globalUrlParam) }); expect(mockHistory.replace).toHaveBeenCalledWith({ - search: `firstKey=111&${urlParamKey}=${value}&lastKey=999`, + search: `firstKey=111&${urlParamKey}='${value}'&lastKey=999`, }); }); @@ -236,7 +237,7 @@ describe('global query string', () => { renderHook(() => useSyncGlobalQueryString(), { wrapper: makeWrapper(globalUrlParam) }); expect(mockHistory.replace).toHaveBeenCalledWith({ - search: `${urlParamKey1}=${value1}&${urlParamKey2}=${value2}`, + search: `${urlParamKey1}='${value1}'&${urlParamKey2}='${value2}'`, }); }); diff --git a/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.ts b/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.ts index 96834d39fd644..0d6f546a8b1d5 100644 --- a/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.ts +++ b/x-pack/plugins/security_solution/public/common/utils/global_query_string/index.ts @@ -9,12 +9,8 @@ import { useCallback, useEffect, useMemo } from 'react'; import { difference, isEmpty, pickBy } from 'lodash/fp'; import { useDispatch } from 'react-redux'; import usePrevious from 'react-use/lib/usePrevious'; -import { - encodeQueryString, - encodeRisonUrlState, - useGetInitialUrlParamValue, - useReplaceUrlParams, -} from './helpers'; +import { encode } from '@kbn/rison'; +import { encodeQueryString, useGetInitialUrlParamValue, useReplaceUrlParams } from './helpers'; import { useShallowEqualSelector } from '../../hooks/use_selector'; import { globalUrlParamActions, globalUrlParamSelectors } from '../../store/global_url_param'; import { useRouteSpy } from '../route/use_route_spy'; @@ -29,7 +25,7 @@ import { getLinkInfo } from '../../links'; * @param urlParamKey Must not change. * @param onInitialize Called once when initializing. It must not change. */ -export const useInitializeUrlParam = ( +export const useInitializeUrlParam = ( urlParamKey: string, /** * @param state Decoded URL param value. @@ -38,20 +34,20 @@ export const useInitializeUrlParam = ( ) => { const dispatch = useDispatch(); - const getInitialUrlParamValue = useGetInitialUrlParamValue(urlParamKey); + const getInitialUrlParamValue = useGetInitialUrlParamValue(urlParamKey); useEffect(() => { - const { param: initialValue, decodedParam: decodedInitialValue } = getInitialUrlParamValue(); + const value = getInitialUrlParamValue(); dispatch( globalUrlParamActions.registerUrlParam({ key: urlParamKey, - initialValue: initialValue ?? null, + initialValue: value, }) ); // execute consumer initialization - onInitialize(decodedInitialValue); + onInitialize(value as State); return () => { dispatch(globalUrlParamActions.deregisterUrlParam({ key: urlParamKey })); @@ -65,13 +61,12 @@ export const useInitializeUrlParam = ( * * Make sure to call `useInitializeUrlParam` before calling this function. */ -export const useUpdateUrlParam = (urlParamKey: string) => { +export const useUpdateUrlParam = (urlParamKey: string) => { const dispatch = useDispatch(); const updateUrlParam = useCallback( (value: State | null) => { - const encodedValue = value !== null ? encodeRisonUrlState(value) : null; - dispatch(globalUrlParamActions.updateUrlParam({ key: urlParamKey, value: encodedValue })); + dispatch(globalUrlParamActions.updateUrlParam({ key: urlParamKey, value })); }, [dispatch, urlParamKey] ); @@ -81,11 +76,29 @@ export const useUpdateUrlParam = (urlParamKey: string) => { export const useGlobalQueryString = (): string => { const globalUrlParam = useShallowEqualSelector(globalUrlParamSelectors.selectGlobalUrlParam); + const globalQueryString = useMemo(() => { + const encodedGlobalUrlParam: Record = {}; - const globalQueryString = useMemo( - () => encodeQueryString(pickBy((value) => !isEmpty(value), globalUrlParam)), - [globalUrlParam] - ); + if (!globalUrlParam) { + return ''; + } + + Object.keys(globalUrlParam).forEach((paramName) => { + const value = globalUrlParam[paramName]; + + if (!value || (typeof value === 'object' && isEmpty(value))) { + return; + } + + try { + encodedGlobalUrlParam[paramName] = encode(value); + } catch { + // Just ignore parameters which unable to encode + } + }); + + return encodeQueryString(pickBy((value) => !isEmpty(value), encodedGlobalUrlParam)); + }, [globalUrlParam]); return globalQueryString; }; @@ -100,29 +113,29 @@ export const useSyncGlobalQueryString = () => { const previousGlobalUrlParams = usePrevious(globalUrlParam); const replaceUrlParams = useReplaceUrlParams(); - // Url params that got deleted from GlobalUrlParams - const unregisteredKeys = useMemo( - () => difference(Object.keys(previousGlobalUrlParams ?? {}), Object.keys(globalUrlParam)), - [previousGlobalUrlParams, globalUrlParam] - ); - useEffect(() => { const linkInfo = getLinkInfo(pageName) ?? { skipUrlState: true }; - const params = Object.entries(globalUrlParam).map(([key, value]) => ({ - key, - value: linkInfo.skipUrlState ? null : value, - })); + const paramsToUpdate = { ...globalUrlParam }; + + if (linkInfo.skipUrlState) { + Object.keys(paramsToUpdate).forEach((key) => { + paramsToUpdate[key] = null; + }); + } + + // Url params that got deleted from GlobalUrlParams + const unregisteredKeys = difference( + Object.keys(previousGlobalUrlParams ?? {}), + Object.keys(globalUrlParam) + ); // Delete unregistered Url params unregisteredKeys.forEach((key) => { - params.push({ - key, - value: null, - }); + paramsToUpdate[key] = null; }); - if (params.length > 0) { - replaceUrlParams(params); + if (Object.keys(paramsToUpdate).length > 0) { + replaceUrlParams(paramsToUpdate); } - }, [globalUrlParam, pageName, unregisteredKeys, replaceUrlParams]); + }, [previousGlobalUrlParams, globalUrlParam, pageName, replaceUrlParams]); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/__mocks__/mock_rules_table_persistent_state.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/__mocks__/mock_rules_table_persistent_state.ts index 36c452b648853..2b5d6750e91fd 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/__mocks__/mock_rules_table_persistent_state.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/__mocks__/mock_rules_table_persistent_state.ts @@ -19,9 +19,7 @@ export function mockRulesTablePersistedState({ urlState: RulesTableUrlSavedState | null; storageState: RulesTableStorageSavedState | null; }): void { - (useGetInitialUrlParamValue as jest.Mock).mockReturnValue( - jest.fn().mockReturnValue({ decodedParam: urlState }) - ); + (useGetInitialUrlParamValue as jest.Mock).mockReturnValue(jest.fn().mockReturnValue(urlState)); (useKibana as jest.Mock).mockReturnValue({ services: { sessionStorage: { get: jest.fn().mockReturnValue(storageState) } }, }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/use_initialize_rules_table_saved_state.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/use_initialize_rules_table_saved_state.ts index b33908a3706b2..82ca541f8b9d5 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/use_initialize_rules_table_saved_state.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/use_initialize_rules_table_saved_state.ts @@ -62,7 +62,7 @@ export function useInitializeRulesTableSavedState(): void { } = useKibana(); useEffect(() => { - const { decodedParam: urlState } = getUrlParam(); + const urlState = getUrlParam(); const storageState = readStorageState(sessionStorage); if (!urlState && !storageState) { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/use_sync_rules_table_saved_state.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/use_sync_rules_table_saved_state.test.tsx index afb6b462d8ed4..6d3484791a3af 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/use_sync_rules_table_saved_state.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/use_sync_rules_table_saved_state.test.tsx @@ -55,12 +55,9 @@ describe('useSyncRulesTableSavedState', () => { renderHook(() => useSyncRulesTableSavedState()); - expect(replaceUrlParams).toHaveBeenCalledWith([ - { - key: URL_PARAM_KEY.rulesTable, - value: expectedUrlState, - }, - ]); + expect(replaceUrlParams).toHaveBeenCalledWith({ + [URL_PARAM_KEY.rulesTable]: expectedUrlState, + }); }; const expectStateToSyncWithStorage = ( @@ -96,7 +93,7 @@ describe('useSyncRulesTableSavedState', () => { renderHook(() => useSyncRulesTableSavedState()); - expect(replaceUrlParams).toHaveBeenCalledWith([{ key: URL_PARAM_KEY.rulesTable, value: null }]); + expect(replaceUrlParams).toHaveBeenCalledWith({ [URL_PARAM_KEY.rulesTable]: null }); expect(setStorage).not.toHaveBeenCalled(); expect(removeStorage).toHaveBeenCalledWith(RULES_TABLE_STATE_STORAGE_KEY); }); @@ -136,9 +133,7 @@ describe('useSyncRulesTableSavedState', () => { renderHook(() => useSyncRulesTableSavedState()); - expect(replaceUrlParams).toHaveBeenCalledWith([ - { key: URL_PARAM_KEY.rulesTable, value: expectedUrlState }, - ]); + expect(replaceUrlParams).toHaveBeenCalledWith({ [URL_PARAM_KEY.rulesTable]: expectedUrlState }); expect(setStorage).toHaveBeenCalledWith(RULES_TABLE_STATE_STORAGE_KEY, expectedStorageState); }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/use_sync_rules_table_saved_state.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/use_sync_rules_table_saved_state.ts index 97ee8e6f98115..b4c1b7fe2fff2 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/use_sync_rules_table_saved_state.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table/use_sync_rules_table_saved_state.ts @@ -6,10 +6,7 @@ */ import { useEffect } from 'react'; -import { - encodeRisonUrlState, - useReplaceUrlParams, -} from '../../../../../common/utils/global_query_string/helpers'; +import { useReplaceUrlParams } from '../../../../../common/utils/global_query_string/helpers'; import { useKibana } from '../../../../../common/lib/kibana'; import { URL_PARAM_KEY } from '../../../../../common/hooks/use_url_state'; import { RULES_TABLE_STATE_STORAGE_KEY } from '../constants'; @@ -76,7 +73,7 @@ export function useSyncRulesTableSavedState(): void { const hasStorageStateToSave = Object.keys(storageStateToSave).length > 0; if (!hasUrlStateToSave) { - replaceUrlParams([{ key: URL_PARAM_KEY.rulesTable, value: null }]); + replaceUrlParams({ [URL_PARAM_KEY.rulesTable]: null }); } if (!hasStorageStateToSave) { @@ -87,9 +84,7 @@ export function useSyncRulesTableSavedState(): void { return; } - replaceUrlParams([ - { key: URL_PARAM_KEY.rulesTable, value: encodeRisonUrlState(urlStateToSave) }, - ]); + replaceUrlParams({ [URL_PARAM_KEY.rulesTable]: urlStateToSave }); sessionStorage.set(RULES_TABLE_STATE_STORAGE_KEY, storageStateToSave); }, [replaceUrlParams, sessionStorage, state]); } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/osquery/osquery_investigation_guide_panel.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/osquery/osquery_investigation_guide_panel.tsx new file mode 100644 index 0000000000000..697605dbc5e5a --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/osquery/osquery_investigation_guide_panel.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React, { useCallback, useState } from 'react'; + +interface OsqueryInvestigationGuidePanelProps { + onClick: () => void; +} + +const panelCss = { + marginBottom: '16px', +}; +const flexGroupCss = { padding: `0 24px` }; + +export const OsqueryInvestigationGuidePanel = React.memo( + ({ onClick }) => { + const [hideInvestigationGuideSuggestion, setHideInvestigationGuideSuggestion] = useState(false); + + const handleClick = useCallback(() => { + onClick(); + setHideInvestigationGuideSuggestion(true); + }, [onClick]); + + if (hideInvestigationGuideSuggestion) { + return null; + } + return ( + + + + + + + + + + + + + + + + + ); + } +); + +OsqueryInvestigationGuidePanel.displayName = 'OsqueryInvestigationGuidePanel'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_form.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_form.test.tsx index 0b4c33892d569..05c886564e878 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_form.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_form.test.tsx @@ -15,6 +15,29 @@ import type { ArrayItem } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_ import { Form, useForm } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { getMockTheme } from '../../common/lib/kibana/kibana_react.mock'; +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), // use actual for all non-hook parts + useParams: () => ({ + detailName: 'testId', + }), +})); +jest.mock('../../common/lib/kibana', () => { + const original = jest.requireActual('../../common/lib/kibana'); + return { + ...original, + useToasts: jest.fn().mockReturnValue({ + addError: jest.fn(), + addSuccess: jest.fn(), + addWarning: jest.fn(), + remove: jest.fn(), + }), + }; +}); + +import * as rules from '../rule_management/logic/use_rule'; +// @ts-expect-error we don't really care about thr useRule return value +jest.spyOn(rules, 'useRule').mockReturnValue({}); + const renderWithContext = (Element: React.ReactElement) => { const mockTheme = getMockTheme({ eui: { euiColorLightestShade: '#F5F7FA' } }); @@ -38,7 +61,8 @@ describe('ResponseActionsForm', () => { const { getByTestId, queryByTestId } = renderWithContext(); expect(getByTestId('response-actions-form')); expect(getByTestId('response-actions-header')); - expect(getByTestId('response-actions-list')); + expect(getByTestId('response-actions-wrapper')); + expect(queryByTestId('response-actions-list')); expect(queryByTestId('response-actions-list-item-0')).toEqual(null); }); it('renders list of elements', async () => { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_form.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_form.tsx index aa3c36d9079b6..38dc69f25af51 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_form.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_form.tsx @@ -10,9 +10,9 @@ import { EuiCallOut, EuiSpacer } from '@elastic/eui'; import { map, reduce, upperFirst } from 'lodash'; import ReactMarkdown from 'react-markdown'; import { css } from '@emotion/react'; +import { ResponseActionsWrapper } from './response_actions_wrapper'; import { FORM_ERRORS_TITLE } from '../../detections/components/rules/rule_actions_field/translations'; import { ResponseActionsHeader } from './response_actions_header'; -import { ResponseActionsList } from './response_actions_list'; import type { ArrayItem, FormHook } from '../../shared_imports'; import { useSupportedResponseActionTypes } from './use_supported_response_action_types'; @@ -44,7 +44,7 @@ export const ResponseActionsForm = ({ } return ( - void; - addItem: () => void; - supportedResponseActionTypes: ResponseActionType[]; } const GhostFormField = () => <>; -export const ResponseActionsList = React.memo( - ({ items, removeItem, supportedResponseActionTypes, addItem }: ResponseActionsListProps) => { - const actionTypeIdRef = useRef(null); - const updateActionTypeId = useCallback((id) => { - actionTypeIdRef.current = id; - }, []); - - const context = useFormContext(); - const renderButton = useMemo(() => { - return ( - - ); - }, [addItem, updateActionTypeId, supportedResponseActionTypes]); - - useEffect(() => { - if (actionTypeIdRef.current) { - const index = items.length - 1; - const path = `responseActions[${index}].actionTypeId`; - context.setFieldValue(path, actionTypeIdRef.current); - actionTypeIdRef.current = null; - } - }, [context, items.length]); - - return ( -
- {items.map((actionItem, index) => { - return ( -
- - - - -
- ); - })} - - {renderButton} -
- ); - } -); +export const ResponseActionsList = React.memo(({ items, removeItem }) => { + const { detailName: ruleId } = useParams<{ detailName: string }>(); + const { data: rule } = useRule(ruleId); + + const osqueryNoteQueries = useMemo( + () => (rule?.note ? getOsqueryQueriesFromNote(rule.note) : []), + [rule?.note] + ); + + const context = useFormContext(); + const [formData] = useFormData(); + + const handleInvestigationGuideClick = useCallback(() => { + const values = getResponseActionsFromNote(osqueryNoteQueries, formData.responseActions); + context.updateFieldValues(values); + }, [context, formData?.responseActions, osqueryNoteQueries]); + + return ( +
+ {items.map((actionItem, index) => { + return ( +
+ + + + +
+ ); + })} + + {osqueryNoteQueries.length ? ( + + ) : null} +
+ ); +}); ResponseActionsList.displayName = 'ResponseActionsList'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_wrapper.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_wrapper.tsx new file mode 100644 index 0000000000000..39f036a1b3322 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/response_actions_wrapper.tsx @@ -0,0 +1,60 @@ +/* + * 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, { useCallback, useEffect, useRef, useMemo } from 'react'; + +import { ResponseActionsList } from './response_actions_list'; +import type { ResponseActionType } from './get_supported_response_actions'; +import { ResponseActionAddButton } from './response_action_add_button'; +import type { ArrayItem } from '../../shared_imports'; +import { useFormContext } from '../../shared_imports'; + +interface ResponseActionsWrapperProps { + items: ArrayItem[]; + removeItem: (id: number) => void; + addItem: () => void; + supportedResponseActionTypes: ResponseActionType[]; +} + +export const ResponseActionsWrapper = React.memo( + ({ items, removeItem, supportedResponseActionTypes, addItem }) => { + const actionTypeIdRef = useRef(null); + const updateActionTypeId = useCallback((id) => { + actionTypeIdRef.current = id; + }, []); + + const context = useFormContext(); + + const renderButton = useMemo(() => { + return ( + + ); + }, [addItem, updateActionTypeId, supportedResponseActionTypes]); + + useEffect(() => { + if (actionTypeIdRef.current) { + const index = items.length - 1; + const path = `responseActions[${index}].actionTypeId`; + context.setFieldValue(path, actionTypeIdRef.current); + actionTypeIdRef.current = null; + } + }, [context, items.length]); + + return ( +
+ + {renderButton} +
+ ); + } +); + +ResponseActionsWrapper.displayName = 'ResponseActionsWrapper'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/utils.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/utils.test.ts new file mode 100644 index 0000000000000..0842cce48bdef --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/utils.test.ts @@ -0,0 +1,89 @@ +/* + * 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 { getOsqueryQueriesFromNote } from './utils'; + +describe('getOsqueryQueriesFromNote', () => { + it('should transform investigation guide note into osquery queries', () => { + const note = + '!{osquery{"query":"SELECT * FROM processes where pid = {{ process.pid }};","label":"Get processes","ecs_mapping":{"process.pid":{"field":"pid"},"process.name":{"field":"name"},"process.executable":{"field":"path"},"process.args":{"field":"cmdline"},"process.working_directory":{"field":"cwd"},"user.id":{"field":"uid"},"group.id":{"field":"gid"},"process.parent.pid":{"field":"parent"},"process.pgid":{"field":"pgroup"}}}}\n\n!{osquery{"query":"select * from users;","label":"Get users"}}'; + const queries = getOsqueryQueriesFromNote(note); + const expectedQueries = [ + { + type: 'osquery', + configuration: { + query: 'SELECT * FROM processes where pid = {{ process.pid }};', + label: 'Get processes', + ecs_mapping: { + 'process.pid': { + field: 'pid', + }, + 'process.name': { + field: 'name', + }, + 'process.executable': { + field: 'path', + }, + 'process.args': { + field: 'cmdline', + }, + 'process.working_directory': { + field: 'cwd', + }, + 'user.id': { + field: 'uid', + }, + 'group.id': { + field: 'gid', + }, + 'process.parent.pid': { + field: 'parent', + }, + 'process.pgid': { + field: 'pgroup', + }, + }, + }, + position: { + start: { + line: 1, + column: 1, + offset: 0, + }, + end: { + line: 1, + column: 423, + offset: 422, + }, + indent: [], + }, + }, + { + type: 'osquery', + configuration: { + query: 'select * from users;', + label: 'Get users', + }, + position: { + start: { + line: 3, + column: 1, + offset: 424, + }, + end: { + line: 3, + column: 63, + offset: 486, + }, + indent: [], + }, + }, + ]; + + expect(queries).toEqual(expectedQueries); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/utils.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/utils.tsx new file mode 100644 index 0000000000000..21beb2bf43a42 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions/utils.tsx @@ -0,0 +1,55 @@ +/* + * 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 unified from 'unified'; +import markdown from 'remark-parse'; +import { filter, reduce } from 'lodash'; + +import type { ECSMapping } from '@kbn/osquery-io-ts-types'; +import type { RuleResponseAction } from '../../../common/detection_engine/rule_response_actions/schemas'; +import { RESPONSE_ACTION_TYPES } from '../../../common/detection_engine/rule_response_actions/schemas'; +import { OsqueryParser } from '../../common/components/markdown_editor/plugins/osquery/parser'; + +interface OsqueryNoteQuery { + configuration: { + label: string; + query: string; + ecs_mapping: ECSMapping; + }; +} + +export const getOsqueryQueriesFromNote = (note: string): OsqueryNoteQuery[] => { + const parsedAlertInvestigationGuide = unified() + .use([[markdown, {}], OsqueryParser]) + .parse(note); + return filter(parsedAlertInvestigationGuide?.children as object, ['type', 'osquery']); +}; + +export const getResponseActionsFromNote = ( + osqueryQueries: OsqueryNoteQuery[], + defaultResponseActions: RuleResponseAction[] = [] +) => { + return reduce( + osqueryQueries, + (acc: { responseActions: RuleResponseAction[] }, { configuration }: OsqueryNoteQuery) => { + const responseActionPath = 'responseActions'; + acc[responseActionPath].push({ + actionTypeId: RESPONSE_ACTION_TYPES.OSQUERY, + params: { + savedQueryId: undefined, + packId: undefined, + queries: undefined, + query: configuration.query, + ecsMapping: configuration.ecs_mapping, + }, + }); + + return acc; + }, + { responseActions: defaultResponseActions } + ); +}; diff --git a/x-pack/plugins/security_solution/public/detections/components/osquery/osquery_flyout.tsx b/x-pack/plugins/security_solution/public/detections/components/osquery/osquery_flyout.tsx index 00dbe210e7026..dc26a0b98499a 100644 --- a/x-pack/plugins/security_solution/public/detections/components/osquery/osquery_flyout.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/osquery/osquery_flyout.tsx @@ -5,9 +5,10 @@ * 2.0. */ -import React from 'react'; +import React, { useCallback } from 'react'; import styled from 'styled-components'; import { EuiFlyout, EuiFlyoutFooter, EuiFlyoutBody, EuiFlyoutHeader, EuiTitle } from '@elastic/eui'; +import { useQueryClient } from '@tanstack/react-query'; import type { Ecs } from '../../../../common/ecs'; import { useKibana } from '../../../common/lib/kibana'; import { OsqueryEventDetailsFooter } from './osquery_flyout_footer'; @@ -19,11 +20,19 @@ const OsqueryActionWrapper = styled.div` export interface OsqueryFlyoutProps { agentId?: string; - defaultValues?: {}; + defaultValues?: { + alertIds?: string[]; + query?: string; + ecs_mapping?: { [key: string]: {} }; + queryField?: boolean; + }; onClose: () => void; ecsData?: Ecs; } +// Make sure we keep this and ACTIONS_QUERY_KEY in use_all_live_queries.ts in sync. +const ACTIONS_QUERY_KEY = 'actions'; + const OsqueryFlyoutComponent: React.FC = ({ agentId, defaultValues, @@ -33,6 +42,13 @@ const OsqueryFlyoutComponent: React.FC = ({ const { services: { osquery }, } = useKibana(); + const queryClient = useQueryClient(); + + const invalidateQueries = useCallback(() => { + queryClient.invalidateQueries({ + queryKey: [ACTIONS_QUERY_KEY, { alertId: defaultValues?.alertIds?.[0] }], + }); + }, [defaultValues?.alertIds, queryClient]); if (osquery?.OsqueryAction) { return ( @@ -54,6 +70,7 @@ const OsqueryFlyoutComponent: React.FC = ({ formType="steps" defaultValues={defaultValues} ecsData={ecsData} + onSuccess={invalidateQueries} /> diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts index 1ed56a518662a..475563a0518b0 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts @@ -100,9 +100,7 @@ describe('useRuleFromTimeline', () => { jest.clearAllMocks(); appToastsMock = useAppToastsMock.create(); (useAppToasts as jest.Mock).mockReturnValue(appToastsMock); - (useGetInitialUrlParamValue as jest.Mock).mockReturnValue(() => ({ - decodedParam: timelineId, - })); + (useGetInitialUrlParamValue as jest.Mock).mockReturnValue(() => timelineId); (resolveTimeline as jest.Mock).mockResolvedValue(selectedTimeline); }); @@ -139,9 +137,7 @@ describe('useRuleFromTimeline', () => { }); }); it('if no timeline id in URL, loading: false and query not set', async () => { - (useGetInitialUrlParamValue as jest.Mock).mockReturnValue(() => ({ - decodedParam: undefined, - })); + (useGetInitialUrlParamValue as jest.Mock).mockReturnValue(() => undefined); const { result } = renderHook(() => useRuleFromTimeline(setRuleQuery)); expect(result.current.loading).toEqual(false); @@ -227,9 +223,7 @@ describe('useRuleFromTimeline', () => { }); it('Sets rule from timeline query via callback', async () => { - (useGetInitialUrlParamValue as jest.Mock).mockReturnValue(() => ({ - decodedParam: undefined, - })); + (useGetInitialUrlParamValue as jest.Mock).mockReturnValue(() => undefined); const { result } = renderHook(() => useRuleFromTimeline(setRuleQuery)); expect(result.current.loading).toEqual(false); await act(async () => { @@ -280,9 +274,7 @@ describe('useRuleFromTimeline', () => { }); it('Handles error when query is malformed', async () => { - (useGetInitialUrlParamValue as jest.Mock).mockReturnValue(() => ({ - decodedParam: undefined, - })); + (useGetInitialUrlParamValue as jest.Mock).mockReturnValue(() => undefined); const { result } = renderHook(() => useRuleFromTimeline(setRuleQuery)); expect(result.current.loading).toEqual(false); const tl = { diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx index e77fe4e92b7a3..f9793020b6f20 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx @@ -181,9 +181,7 @@ export const useRuleFromTimeline = (setRuleQuery: SetRuleQuery): RuleFromTimelin // start handle set rule from timeline id const getInitialUrlParamValue = useGetInitialUrlParamValue(RULE_FROM_TIMELINE_URL_PARAM); - const { decodedParam: timelineIdFromUrl } = useMemo(getInitialUrlParamValue, [ - getInitialUrlParamValue, - ]); + const timelineIdFromUrl = useMemo(getInitialUrlParamValue, [getInitialUrlParamValue]); const getTimelineById = useCallback( (timelineId: string) => { diff --git a/x-pack/plugins/security_solution/public/management/cypress.config.ts b/x-pack/plugins/security_solution/public/management/cypress.config.ts index 0509fbf8cffdc..6ff919ea7effe 100644 --- a/x-pack/plugins/security_solution/public/management/cypress.config.ts +++ b/x-pack/plugins/security_solution/public/management/cypress.config.ts @@ -35,8 +35,6 @@ export default defineCypressConfig({ baseUrl: 'http://localhost:5620', supportFile: 'public/management/cypress/support/e2e.ts', specPattern: 'public/management/cypress/e2e/**/*.cy.{js,jsx,ts,tsx}', - experimentalSessionAndOrigin: true, - testIsolation: 'on', experimentalRunAllSpecs: true, }, }); diff --git a/x-pack/plugins/security_solution/public/management/links.test.ts b/x-pack/plugins/security_solution/public/management/links.test.ts index b505c8a36e743..a00d03fff59d6 100644 --- a/x-pack/plugins/security_solution/public/management/links.test.ts +++ b/x-pack/plugins/security_solution/public/management/links.test.ts @@ -154,7 +154,6 @@ describe('links', () => { expect.anything(), expect.anything(), expect.anything(), - expect.anything(), false ); expect(filteredLinks).toEqual(getLinksWithout(SecurityPageName.hostIsolationExceptions)); @@ -196,7 +195,6 @@ describe('links', () => { expect.anything(), expect.anything(), expect.anything(), - expect.anything(), true ); expect(filteredLinks).toEqual(getLinksWithout()); diff --git a/x-pack/plugins/security_solution/public/management/links.ts b/x-pack/plugins/security_solution/public/management/links.ts index 49432df00aaf3..1db32eae3d5f2 100644 --- a/x-pack/plugins/security_solution/public/management/links.ts +++ b/x-pack/plugins/security_solution/public/management/links.ts @@ -13,7 +13,6 @@ import { checkArtifactHasData } from './services/exceptions_list/check_artifact_ import { calculateEndpointAuthz, getEndpointAuthzInitialState, - calculatePermissionsFromCapabilities, } from '../../common/endpoint/service/authz'; import { BLOCKLIST_PATH, @@ -243,7 +242,6 @@ export const getManagementFilteredLinks = async ( const { endpointRbacEnabled, endpointRbacV1Enabled } = ExperimentalFeaturesService.get(); const isEndpointRbacEnabled = endpointRbacEnabled || endpointRbacV1Enabled; - const endpointPermissions = calculatePermissionsFromCapabilities(core.application.capabilities); const linksToExclude: SecurityPageName[] = []; @@ -287,7 +285,6 @@ export const getManagementFilteredLinks = async ( fleetAuthz, currentUser.roles, isEndpointRbacEnabled, - endpointPermissions, hasHostIsolationExceptions ) : getEndpointAuthzInitialState(); diff --git a/x-pack/plugins/security_solution/public/management/mocks/fleet_mocks.ts b/x-pack/plugins/security_solution/public/management/mocks/fleet_mocks.ts index 1e5cc83bb0bcc..9a5274e2cdfab 100644 --- a/x-pack/plugins/security_solution/public/management/mocks/fleet_mocks.ts +++ b/x-pack/plugins/security_solution/public/management/mocks/fleet_mocks.ts @@ -12,6 +12,7 @@ import type { GetAgentStatusResponse, GetPackagePoliciesResponse, GetPackagesResponse, + GetInfoResponse, BulkGetPackagePoliciesResponse, BulkGetAgentPoliciesResponse, } from '@kbn/fleet-plugin/common'; @@ -139,6 +140,24 @@ export const fleetGetPackageListHttpMock = }, ]); +export type FleetGetPackageHttpMockInterface = ResponseProvidersInterface<{ + endpointPackage: () => GetInfoResponse; +}>; +export const fleetGetPackageHttpMock = httpHandlerMockFactory([ + { + id: 'endpointPackage', + method: 'get', + path: EPM_API_ROUTES.INFO_PATTERN_DEPRECATED, + handler() { + const generator = new EndpointDocGenerator('seed'); + + return { + item: generator.generateEpmPackageInfo(), + }; + }, + }, +]); + export type FleetGetEndpointPackagePolicyHttpMockInterface = ResponseProvidersInterface<{ endpointPackagePolicy: () => GetPolicyResponse; }>; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/mocks.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/mocks.ts index 7dfd55664acc7..39bd07d071974 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/mocks.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/mocks.ts @@ -32,12 +32,14 @@ import type { FleetGetAgentStatusHttpMockInterface, FleetGetCheckPermissionsInterface, FleetGetEndpointPackagePolicyHttpMockInterface, + FleetGetPackageHttpMockInterface, FleetGetPackageListHttpMockInterface, } from '../../mocks'; import { fleetGetAgentPolicyListHttpMock, fleetGetCheckPermissionsHttpMock, fleetGetPackageListHttpMock, + fleetGetPackageHttpMock, fleetBulkGetPackagePoliciesListHttpMock, fleetBulkGetAgentPolicyListHttpMock, fleetGetPackagePoliciesListHttpMock, @@ -125,6 +127,7 @@ export const transformsHttpMocks = httpHandlerMockFactory([ fleetGetPackageListHttpMock, + fleetGetPackageHttpMock, fleetGetAgentPolicyListHttpMock, fleetBulkGetPackagePoliciesListHttpMock, fleetBulkGetAgentPolicyListHttpMock, diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts index 79c21360c3ab2..8d7e6b0c4d10b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts @@ -6,7 +6,7 @@ */ import type { DataViewBase } from '@kbn/es-query'; -import type { GetPackagesResponse } from '@kbn/fleet-plugin/common'; +import type { GetInfoResponse } from '@kbn/fleet-plugin/common'; import type { HostInfo, Immutable, @@ -60,7 +60,7 @@ export interface EndpointState { /** the selected policy ID in the onboarding flow */ selectedPolicyId?: string; /** Endpoint package info */ - endpointPackageInfo: AsyncResourceState; + endpointPackageInfo: AsyncResourceState; /** Tracks the list of policies IDs used in Host metadata that may no longer exist */ nonExistingPolicies: PolicyIds['packagePolicy']; /** List of Package Policy Ids mapped to an associated Fleet Parent Agent Policy Id*/ diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/test_mock_utils.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/test_mock_utils.ts index 880afeb347361..e1a56417548f4 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/test_mock_utils.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/test_mock_utils.ts @@ -5,7 +5,8 @@ * 2.0. */ -import type { GetPackagesResponse } from '@kbn/fleet-plugin/common'; +import type { GetPackagesResponse, GetInfoResponse } from '@kbn/fleet-plugin/common'; +import { epmRouteService } from '@kbn/fleet-plugin/common'; import { INGEST_API_EPM_PACKAGES, INGEST_API_PACKAGE_POLICIES, @@ -63,5 +64,10 @@ export const policyListApiPathHandlers = (totalPolicies: number = 1) => { items: [generator.generateEpmPackage()], }; }, + [epmRouteService.getInfoPath('endpoint')]: (): GetInfoResponse => { + return { + item: generator.generateEpmPackageInfo(), + }; + }, }; }; diff --git a/x-pack/plugins/security_solution/public/management/services/policies/hooks.test.ts b/x-pack/plugins/security_solution/public/management/services/policies/hooks.test.ts index 8bd8c4c72efea..e2aa5e8cd8c93 100644 --- a/x-pack/plugins/security_solution/public/management/services/policies/hooks.test.ts +++ b/x-pack/plugins/security_solution/public/management/services/policies/hooks.test.ts @@ -7,7 +7,7 @@ import type { UseQueryOptions } from '@tanstack/react-query'; import type { IHttpFetchError, HttpSetup } from '@kbn/core-http-browser'; -import type { GetPackagesResponse } from '@kbn/fleet-plugin/common'; +import type { GetInfoResponse } from '@kbn/fleet-plugin/common'; import { useGetEndpointSecurityPackage } from './hooks'; import { getFakeHttpService, renderQuery } from '../../hooks/test_utils'; import { EndpointDocGenerator } from '../../../../common/endpoint/generate_data'; @@ -19,7 +19,7 @@ describe('useGetEndpointSecurityPackage hook', () => { let result: ReturnType; let fakeHttpServices: jest.Mocked; let generator: EndpointDocGenerator; - let options: UseQueryOptions | undefined; + let options: UseQueryOptions | undefined; beforeEach(() => { fakeHttpServices = getFakeHttpService(); @@ -33,7 +33,7 @@ describe('useGetEndpointSecurityPackage hook', () => { it('retrieves the endpoint package', async () => { const apiResponse = { - items: [generator.generateEpmPackage()], + item: [generator.generateEpmPackageInfo()], }; fakeHttpServices.get.mockResolvedValue(apiResponse); const onSuccessMock: jest.Mock = jest.fn(); @@ -47,7 +47,7 @@ describe('useGetEndpointSecurityPackage hook', () => { () => useGetEndpointSecurityPackage({ customQueryOptions: options }), 'isSuccess' ); - expect(result.data).toBe(apiResponse.items[0]); + expect(result.data).toBe(apiResponse.item); expect(fakeHttpServices.get).toHaveBeenCalledTimes(1); expect(onSuccessMock).toHaveBeenCalledTimes(1); }); diff --git a/x-pack/plugins/security_solution/public/management/services/policies/hooks.ts b/x-pack/plugins/security_solution/public/management/services/policies/hooks.ts index 6254120445e43..a979d79db5663 100644 --- a/x-pack/plugins/security_solution/public/management/services/policies/hooks.ts +++ b/x-pack/plugins/security_solution/public/management/services/policies/hooks.ts @@ -7,7 +7,7 @@ import type { QueryObserverResult, UseQueryOptions } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query'; import type { IHttpFetchError } from '@kbn/core-http-browser'; -import type { GetPackagesResponse } from '@kbn/fleet-plugin/common'; +import type { GetInfoResponse } from '@kbn/fleet-plugin/common'; import { useHttp } from '../../../common/lib/kibana'; import { MANAGEMENT_DEFAULT_PAGE_SIZE } from '../../common/constants'; import { sendGetEndpointSecurityPackage } from './ingest'; @@ -52,10 +52,10 @@ export function useGetEndpointSpecificPolicies( export function useGetEndpointSecurityPackage({ customQueryOptions, }: { - customQueryOptions?: UseQueryOptions; -}): QueryObserverResult { + customQueryOptions?: UseQueryOptions; +}): QueryObserverResult { const http = useHttp(); - return useQuery( + return useQuery( ['endpointPackageVersion', customQueryOptions], () => { return sendGetEndpointSecurityPackage(http); diff --git a/x-pack/plugins/security_solution/public/management/services/policies/ingest.test.ts b/x-pack/plugins/security_solution/public/management/services/policies/ingest.test.ts index d29eedd06f765..a3644ce691478 100644 --- a/x-pack/plugins/security_solution/public/management/services/policies/ingest.test.ts +++ b/x-pack/plugins/security_solution/public/management/services/policies/ingest.test.ts @@ -5,13 +5,9 @@ * 2.0. */ -import { - INGEST_API_EPM_PACKAGES, - sendGetPackagePolicy, - sendGetEndpointSecurityPackage, -} from './ingest'; +import { sendGetPackagePolicy, sendGetEndpointSecurityPackage } from './ingest'; import { httpServiceMock } from '@kbn/core/public/mocks'; -import { EPM_API_ROUTES, PACKAGE_POLICY_API_ROOT } from '@kbn/fleet-plugin/common'; +import { PACKAGE_POLICY_API_ROOT, epmRouteService } from '@kbn/fleet-plugin/common'; import { policyListApiPathHandlers } from '../../pages/policy/store/test_mock_utils'; describe('ingest service', () => { @@ -37,14 +33,11 @@ describe('ingest service', () => { }); describe('sendGetEndpointSecurityPackage()', () => { - it('should query EPM with category=security', async () => { - http.get.mockReturnValue( - Promise.resolve(policyListApiPathHandlers()[INGEST_API_EPM_PACKAGES]()) - ); + it('should query for endpoint package', async () => { + const path = epmRouteService.getInfoPath('endpoint'); + http.get.mockReturnValue(Promise.resolve(policyListApiPathHandlers()[path]())); await sendGetEndpointSecurityPackage(http); - expect(http.get).toHaveBeenCalledWith(`${EPM_API_ROUTES.LIST_PATTERN}`, { - query: { category: 'security' }, - }); + expect(http.get).toHaveBeenCalledWith(path); }); it('should throw if package is not found', async () => { diff --git a/x-pack/plugins/security_solution/public/management/services/policies/ingest.ts b/x-pack/plugins/security_solution/public/management/services/policies/ingest.ts index adfdcf3ca62a0..c6240c934ec8f 100644 --- a/x-pack/plugins/security_solution/public/management/services/policies/ingest.ts +++ b/x-pack/plugins/security_solution/public/management/services/policies/ingest.ts @@ -8,11 +8,13 @@ import type { HttpFetchOptions, HttpStart } from '@kbn/core/public'; import type { GetAgentStatusResponse, - GetPackagesResponse, GetAgentPoliciesRequest, GetAgentPoliciesResponse, GetPackagePoliciesResponse, + GetInfoResponse, } from '@kbn/fleet-plugin/common'; +import { epmRouteService } from '@kbn/fleet-plugin/common'; + import type { NewPolicyData } from '../../../../common/endpoint/types'; import type { GetPolicyResponse, UpdatePolicyResponse } from '../../pages/policy/types'; @@ -135,12 +137,10 @@ export const sendGetFleetAgentStatusForPolicy = ( */ export const sendGetEndpointSecurityPackage = async ( http: HttpStart -): Promise => { - const options = { query: { category: 'security' } }; - const securityPackages = await http.get(INGEST_API_EPM_PACKAGES, options); - const endpointPackageInfo = securityPackages.items.find( - (epmPackage) => epmPackage.name === 'endpoint' - ); +): Promise => { + const path = epmRouteService.getInfoPath('endpoint'); + const endpointPackageResponse = await http.get(path); + const endpointPackageInfo = endpointPackageResponse.item; if (!endpointPackageInfo) { throw new Error('Endpoint package was not found.'); } diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx index 970a6482065af..b21f2f1507a24 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx @@ -7,9 +7,9 @@ import React, { useEffect, useState, useCallback, useMemo } from 'react'; import { useDispatch } from 'react-redux'; +import { encode } from '@kbn/rison'; import { RULE_FROM_TIMELINE_URL_PARAM } from '../../../detections/containers/detection_engine/rules/use_rule_from_timeline'; -import { encodeRisonUrlState } from '../../../common/utils/global_query_string/helpers'; import { useNavigation } from '../../../common/lib/kibana'; import { SecurityPageName } from '../../../../common/constants'; import { useShallowEqualSelector } from '../../../common/hooks/use_selector'; @@ -283,7 +283,7 @@ export const StatefulOpenTimelineComponent = React.memo( (savedObjectId) => navigateTo({ deepLinkId: SecurityPageName.rulesCreate, - path: `?${RULE_FROM_TIMELINE_URL_PARAM}=${encodeRisonUrlState(savedObjectId)}`, + path: `?${RULE_FROM_TIMELINE_URL_PARAM}=${encode(savedObjectId)}`, }), [navigateTo] ); diff --git a/x-pack/plugins/security_solution/scripts/endpoint/agent_emulator/services/endpoint_loader.ts b/x-pack/plugins/security_solution/scripts/endpoint/agent_emulator/services/endpoint_loader.ts index b9df8251da319..4d16a0407b088 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/agent_emulator/services/endpoint_loader.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/agent_emulator/services/endpoint_loader.ts @@ -20,9 +20,9 @@ import { fetchEndpointMetadataList } from '../../common/endpoint_metadata_servic import { indexEndpointHostDocs } from '../../../../common/endpoint/data_loaders/index_endpoint_hosts'; import { setupFleetForEndpoint } from '../../../../common/endpoint/data_loaders/setup_fleet_for_endpoint'; import { enableFleetServerIfNecessary } from '../../../../common/endpoint/data_loaders/index_fleet_server'; -import { fetchEndpointPackageInfo } from '../../common/fleet_services'; import { METADATA_DATASTREAM } from '../../../../common/endpoint/constants'; import { EndpointMetadataGenerator } from '../../../../common/endpoint/data_generators/endpoint_metadata_generator'; +import { getEndpointPackageInfo } from '../../../../common/endpoint/index_data'; import { ENDPOINT_ALERTS_INDEX, ENDPOINT_EVENTS_INDEX } from '../../common/constants'; let WAS_FLEET_SETUP_DONE = false; @@ -105,7 +105,7 @@ export const loadEndpoints = async ({ WAS_FLEET_SETUP_DONE = true; } - const endpointPackage = await fetchEndpointPackageInfo(kbnClient); + const endpointPackage = await getEndpointPackageInfo(kbnClient); const realPolicies: Record = {}; let progress: LoadEndpointsProgress = { diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts index c94b66d68a5da..a8bc5fb04a8d4 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts @@ -6,12 +6,10 @@ */ import type { Client, estypes } from '@elastic/elasticsearch'; -import { AGENTS_INDEX, EPM_API_ROUTES } from '@kbn/fleet-plugin/common'; -import type { AgentStatus, GetPackagesResponse } from '@kbn/fleet-plugin/common'; +import { AGENTS_INDEX } from '@kbn/fleet-plugin/common'; +import type { AgentStatus } from '@kbn/fleet-plugin/common'; import { pick } from 'lodash'; import { ToolingLog } from '@kbn/tooling-log'; -import type { AxiosResponse } from 'axios'; -import type { KbnClient } from '@kbn/test'; import { FleetAgentGenerator } from '../../../common/endpoint/data_generators/fleet_agent_generator'; const fleetGenerator = new FleetAgentGenerator(); @@ -66,20 +64,3 @@ export const checkInFleetAgent = async ( }, }); }; - -export const fetchEndpointPackageInfo = async ( - kbnClient: KbnClient -): Promise => { - const endpointPackage = ( - (await kbnClient.request({ - path: `${EPM_API_ROUTES.LIST_PATTERN}?category=security`, - method: 'GET', - })) as AxiosResponse - ).data.items.find((epmPackage) => epmPackage.name === 'endpoint'); - - if (!endpointPackage) { - throw new Error('EPM Endpoint package was not found!'); - } - - return endpointPackage; -}; diff --git a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts index e6c26c9af4773..bf87fbb22de0a 100644 --- a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts +++ b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts @@ -41,11 +41,7 @@ import type { } from './services/fleet/endpoint_fleet_services_factory'; import { registerListsPluginEndpointExtensionPoints } from '../lists_integration'; import type { EndpointAuthz } from '../../common/endpoint/types/authz'; -import { - calculateEndpointAuthz, - calculatePermissionsFromPrivileges, - defaultEndpointPermissions, -} from '../../common/endpoint/service/authz'; +import { calculateEndpointAuthz } from '../../common/endpoint/service/authz'; import type { FeatureUsageService } from './services/feature_usage/service'; import type { ExperimentalFeatures } from '../../common/experimental_features'; import { doesArtifactHaveData } from './services'; @@ -173,18 +169,6 @@ export class EndpointAppContextService { const isPlatinumPlus = this.getLicenseService().isPlatinumPlus(); const listClient = this.getExceptionListsClient(); - let endpointPermissions = defaultEndpointPermissions(); - if (this.security) { - const checkPrivileges = this.security.authz.checkPrivilegesDynamicallyWithRequest(request); - const { privileges } = await checkPrivileges({ - kibana: [ - this.security.authz.actions.ui.get('siem', 'crud'), - this.security.authz.actions.ui.get('siem', 'show'), - ], - }); - endpointPermissions = calculatePermissionsFromPrivileges(privileges.kibana); - } - const hasExceptionsListItems = !isPlatinumPlus ? await doesArtifactHaveData(listClient, ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID) : true; @@ -194,7 +178,6 @@ export class EndpointAppContextService { fleetAuthz, userRoles, endpointRbacEnabled || endpointRbacV1Enabled, - endpointPermissions, hasExceptionsListItems ); } diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/artifact_client.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/artifact_client.test.ts index 472f191e8c7ac..5df2d67eeb582 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/artifact_client.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/artifact_client.test.ts @@ -47,6 +47,21 @@ describe('artifact_client', () => { }); }); + test('can bulk create artifacts', async () => { + const artifact = await getInternalArtifactMock('linux', 'v1'); + await artifactClient.bulkCreateArtifacts([artifact]); + expect(fleetArtifactClient.bulkCreateArtifacts).toHaveBeenCalledWith([ + { + identifier: artifact.identifier, + type: 'exceptionlist', + content: + '{"entries":[{"type":"simple","entries":[{"entries":[{"field":"some.nested.field","operator":"included","type":"exact_cased","value":"some value"}],' + + '"field":"some.parentField","type":"nested"},{"field":"some.not.nested.field","operator":"included","type":"exact_cased","value":"some value"}]},' + + '{"type":"simple","entries":[{"field":"some.other.not.nested.field","operator":"included","type":"exact_cased","value":"some other value"}]}]}', + }, + ]); + }); + test('can delete artifact', async () => { await artifactClient.deleteArtifact('endpoint-trustlist-linux-v1-sha26hash'); expect(fleetArtifactClient.listArtifacts).toHaveBeenCalledWith({ diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/artifact_client.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/artifact_client.ts index 48172a4600cd8..ed5723ddccf0e 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/artifact_client.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/artifact_client.ts @@ -18,6 +18,10 @@ export interface EndpointArtifactClientInterface { createArtifact(artifact: InternalArtifactCompleteSchema): Promise; + bulkCreateArtifacts( + artifacts: InternalArtifactCompleteSchema[] + ): Promise<{ artifacts?: InternalArtifactCompleteSchema[]; errors?: Error[] }>; + deleteArtifact(id: string): Promise; listArtifacts(options?: ListArtifactsProps): Promise>; @@ -73,6 +77,19 @@ export class EndpointArtifactClient implements EndpointArtifactClientInterface { return createdArtifact; } + async bulkCreateArtifacts( + artifacts: InternalArtifactCompleteSchema[] + ): Promise<{ artifacts?: InternalArtifactCompleteSchema[]; errors?: Error[] }> { + const optionsList = artifacts.map((artifact) => ({ + content: Buffer.from(artifact.body, 'base64').toString(), + identifier: artifact.identifier, + type: this.parseArtifactId(artifact.identifier).type, + })); + + const createdArtifacts = await this.fleetArtifacts.bulkCreateArtifacts(optionsList); + return createdArtifacts; + } + async deleteArtifact(id: string) { // Ignoring the `id` not being in the type until we can refactor the types in endpoint. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts index f4b4559e08708..86ca4787969f8 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts @@ -629,13 +629,14 @@ describe('ManifestManager', () => { ) ).resolves.toStrictEqual([]); - expect(artifactClient.createArtifact).toHaveBeenCalledTimes(2); - expect(artifactClient.createArtifact).toHaveBeenNthCalledWith(1, { - ...ARTIFACT_EXCEPTIONS_MACOS, - }); - expect(artifactClient.createArtifact).toHaveBeenNthCalledWith(2, { - ...ARTIFACT_EXCEPTIONS_WINDOWS, - }); + expect(artifactClient.bulkCreateArtifacts).toHaveBeenCalledWith([ + { + ...ARTIFACT_EXCEPTIONS_MACOS, + }, + { + ...ARTIFACT_EXCEPTIONS_WINDOWS, + }, + ]); expect( JSON.parse(context.cache.get(getArtifactId(ARTIFACT_EXCEPTIONS_MACOS))!.toString()) ).toStrictEqual(getArtifactObject(ARTIFACT_EXCEPTIONS_MACOS)); @@ -652,13 +653,9 @@ describe('ManifestManager', () => { const error = new Error(); const { body, ...incompleteArtifact } = ARTIFACT_TRUSTED_APPS_MACOS; - artifactClient.createArtifact.mockImplementation( - async (artifact: InternalArtifactCompleteSchema) => { - if (getArtifactId(artifact) === ARTIFACT_ID_EXCEPTIONS_WINDOWS) { - throw error; - } else { - return artifact; - } + artifactClient.bulkCreateArtifacts.mockImplementation( + async (artifacts: InternalArtifactCompleteSchema[]) => { + return { artifacts: [artifacts[0]], errors: [error] }; } ); @@ -672,17 +669,21 @@ describe('ManifestManager', () => { newManifest ) ).resolves.toStrictEqual([ - error, new EndpointError( `Incomplete artifact: ${ARTIFACT_ID_TRUSTED_APPS_MACOS}`, ARTIFACTS_BY_ID[ARTIFACT_ID_TRUSTED_APPS_MACOS] ), + error, ]); - expect(artifactClient.createArtifact).toHaveBeenCalledTimes(2); - expect(artifactClient.createArtifact).toHaveBeenNthCalledWith(1, { - ...ARTIFACT_EXCEPTIONS_MACOS, - }); + expect(artifactClient.bulkCreateArtifacts).toHaveBeenCalledWith([ + { + ...ARTIFACT_EXCEPTIONS_MACOS, + }, + { + ...ARTIFACT_EXCEPTIONS_WINDOWS, + }, + ]); expect( JSON.parse(context.cache.get(getArtifactId(ARTIFACT_EXCEPTIONS_MACOS))!.toString()) ).toStrictEqual(getArtifactObject(ARTIFACT_EXCEPTIONS_MACOS)); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts index c3960f4e32e3c..b6c1eeb49e9d5 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts @@ -8,12 +8,8 @@ import pMap from 'p-map'; import semver from 'semver'; import type LRU from 'lru-cache'; -import { isEqual, isEmpty } from 'lodash'; -import { - type Logger, - type SavedObjectsClientContract, - SavedObjectsErrorHelpers, -} from '@kbn/core/server'; +import { isEqual, isEmpty, keyBy } from 'lodash'; +import { type Logger, type SavedObjectsClientContract } from '@kbn/core/server'; import { ENDPOINT_EVENT_FILTERS_LIST_ID, ENDPOINT_TRUSTED_APPS_LIST_ID, @@ -334,34 +330,6 @@ export class ManifestManager { return { defaultArtifacts, policySpecificArtifacts }; } - /** - * Writes new artifact SO. - * - * @param artifact An InternalArtifactCompleteSchema representing the artifact. - * @returns {Promise<[Error | null, InternalArtifactCompleteSchema | undefined]>} An array with the error if encountered or null and the generated artifact or null. - */ - protected async pushArtifact( - artifact: InternalArtifactCompleteSchema - ): Promise<[Error | null, InternalArtifactCompleteSchema | undefined]> { - const artifactId = getArtifactId(artifact); - let fleetArtifact; - try { - // Write the artifact SO - fleetArtifact = await this.artifactClient.createArtifact(artifact); - - // Cache the compressed body of the artifact - this.cache.set(artifactId, Buffer.from(artifact.body, 'base64')); - } catch (err) { - if (SavedObjectsErrorHelpers.isConflictError(err)) { - this.logger.debug(`Tried to create artifact ${artifactId}, but it already exists.`); - } else { - return [err, undefined]; - } - } - - return [null, fleetArtifact]; - } - /** * Writes new artifact SOs. * @@ -374,18 +342,40 @@ export class ManifestManager { newManifest: Manifest ): Promise { const errors: Error[] = []; + + const artifactsToCreate: InternalArtifactCompleteSchema[] = []; + for (const artifact of artifacts) { if (internalArtifactCompleteSchema.is(artifact)) { - const [err, fleetArtifact] = await this.pushArtifact(artifact); - if (err) { - errors.push(err); - } else if (fleetArtifact) { - newManifest.replaceArtifact(fleetArtifact); - } + artifactsToCreate.push(artifact); } else { errors.push(new EndpointError(`Incomplete artifact: ${getArtifactId(artifact)}`, artifact)); } } + + if (artifactsToCreate.length === 0) { + return errors; + } + + const { artifacts: fleetArtifacts, errors: createErrors } = + await this.artifactClient.bulkCreateArtifacts(artifactsToCreate); + + if (createErrors) { + errors.push(...createErrors); + } + + if (fleetArtifacts) { + const fleetArtfactsByIdentifier = keyBy(fleetArtifacts, 'identifier'); + artifactsToCreate.forEach((artifact) => { + const fleetArtifact = fleetArtfactsByIdentifier[artifact.identifier]; + if (!fleetArtifact) return; + const artifactId = getArtifactId(artifact); + // Cache the compressed body of the artifact + this.cache.set(artifactId, Buffer.from(artifact.body, 'base64')); + newManifest.replaceArtifact(fleetArtifact); + }); + } + return errors; } diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/mocks.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/mocks.ts index 3e6446595d800..fbb45c38cac30 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/mocks.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/mocks.ts @@ -45,6 +45,12 @@ export const createEndpointArtifactClientMock = ( const response = await endpointArtifactClient.createArtifact(...args); return response; }), + bulkCreateArtifacts: jest.fn(async (...args) => { + const fleetArtifactClient = new FleetArtifactsClient(esClient, 'endpoint'); + const endpointArtifactClient = new EndpointArtifactClient(fleetArtifactClient); + const response = await endpointArtifactClient.bulkCreateArtifacts(...args); + return response; + }), listArtifacts: jest.fn((...args) => endpointArtifactClientMocked.listArtifacts(...args)), getArtifact: jest.fn((...args) => endpointArtifactClientMocked.getArtifact(...args)), deleteArtifact: jest.fn((...args) => endpointArtifactClientMocked.deleteArtifact(...args)), diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.test.ts new file mode 100644 index 0000000000000..b848c26b9e1e6 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.test.ts @@ -0,0 +1,103 @@ +/* + * 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 { scheduleNotificationResponseActions } from './schedule_notification_response_actions'; +import { RESPONSE_ACTION_TYPES } from '../../../../common/detection_engine/rule_response_actions/schemas'; + +describe('ScheduleNotificationResponseActions', () => { + const signalOne = { agent: { id: 'agent-id-1' }, _id: 'alert-id-1', user: { id: 'S-1-5-20' } }; + const signalTwo = { agent: { id: 'agent-id-2' }, _id: 'alert-id-2' }; + const signals = [signalOne, signalTwo]; + const defaultQueryParams = { + ecsMapping: { testField: { field: 'testField', value: 'testValue' } }, + savedQueryId: 'testSavedQueryId', + query: undefined, + queries: [], + packId: undefined, + }; + const defaultPackParams = { + packId: 'testPackId', + queries: [], + query: undefined, + ecsMapping: { testField: { field: 'testField', value: 'testValue' } }, + savedQueryId: undefined, + }; + const defaultQueries = { + ecs_mapping: undefined, + platform: 'windows', + version: '1.0.0', + snapshot: true, + removed: false, + }; + + const defaultResultParams = { + agent_ids: ['agent-id-1', 'agent-id-2'], + alert_ids: ['alert-id-1', 'alert-id-2'], + }; + const defaultQueryResultParams = { + ...defaultResultParams, + ecs_mapping: { testField: { field: 'testField', value: 'testValue' } }, + ecsMapping: undefined, + saved_query_id: 'testSavedQueryId', + savedQueryId: undefined, + queries: [], + }; + const defaultPackResultParams = { + ...defaultResultParams, + query: undefined, + saved_query_id: undefined, + ecs_mapping: { testField: { field: 'testField', value: 'testValue' } }, + }; + + const simpleQuery = 'select * from uptime'; + it('should handle osquery response actions with query', async () => { + const osqueryActionMock = jest.fn(); + + const responseActions = [ + { + actionTypeId: RESPONSE_ACTION_TYPES.OSQUERY, + params: { + ...defaultQueryParams, + query: simpleQuery, + }, + }, + ]; + scheduleNotificationResponseActions({ signals, responseActions }, osqueryActionMock); + + expect(osqueryActionMock).toHaveBeenCalledWith({ + ...defaultQueryResultParams, + query: simpleQuery, + }); + // + }); + it('should handle osquery response actions with packs', async () => { + const osqueryActionMock = jest.fn(); + + const responseActions = [ + { + actionTypeId: RESPONSE_ACTION_TYPES.OSQUERY, + params: { + ...defaultPackParams, + queries: [ + { + ...defaultQueries, + id: 'query-1', + query: simpleQuery, + }, + ], + packId: 'testPackId', + }, + }, + ]; + scheduleNotificationResponseActions({ signals, responseActions }, osqueryActionMock); + + expect(osqueryActionMock).toHaveBeenCalledWith({ + ...defaultPackResultParams, + queries: [{ ...defaultQueries, id: 'query-1', query: simpleQuery }], + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts index 3e344fe0c5cfa..238f06a3d4b59 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { map, uniq } from 'lodash'; +import type { Ecs } from '@kbn/ecs'; +import { uniq, reduce, some, each } from 'lodash'; import type { RuleResponseAction } from '../../../../common/detection_engine/rule_response_actions/schemas'; import { RESPONSE_ACTION_TYPES } from '../../../../common/detection_engine/rule_response_actions/schemas'; import type { SetupPlugins } from '../../../plugin_contract'; @@ -15,31 +16,68 @@ interface ScheduleNotificationActions { responseActions: RuleResponseAction[]; } -interface IAlert { - agent: { - id: string; - }; +interface AlertsWithAgentType { + alerts: Ecs[]; + agents: string[]; + alertIds: string[]; } +const CONTAINS_DYNAMIC_PARAMETER_REGEX = /\{{([^}]+)\}}/g; // when there are 2 opening and 2 closing curly brackets (including brackets) export const scheduleNotificationResponseActions = ( { signals, responseActions }: ScheduleNotificationActions, osqueryCreateAction?: SetupPlugins['osquery']['osqueryCreateAction'] ) => { - const filteredAlerts = (signals as IAlert[]).filter((alert) => alert.agent?.id); - const agentIds = uniq(filteredAlerts.map((alert: IAlert) => alert.agent?.id)); - const alertIds = map(filteredAlerts, '_id'); + const filteredAlerts = (signals as Ecs[]).filter((alert) => alert.agent?.id); - responseActions.forEach((responseAction) => { + const { alerts, agents, alertIds }: AlertsWithAgentType = reduce( + filteredAlerts, + (acc, alert) => { + const agentId = alert.agent?.id; + if (agentId !== undefined) { + return { + alerts: [...acc.alerts, alert], + agents: [...acc.agents, agentId], + alertIds: [...acc.alertIds, (alert as unknown as { _id: string })._id], + }; + } + return acc; + }, + { alerts: [], agents: [], alertIds: [] } as AlertsWithAgentType + ); + const agentIds = uniq(agents); + + each(responseActions, (responseAction) => { if (responseAction.actionTypeId === RESPONSE_ACTION_TYPES.OSQUERY && osqueryCreateAction) { + const temporaryQueries = responseAction.params.queries?.length + ? responseAction.params.queries + : [{ query: responseAction.params.query }]; + const containsDynamicQueries = some(temporaryQueries, (query) => { + return query.query ? CONTAINS_DYNAMIC_PARAMETER_REGEX.test(query.query) : false; + }); const { savedQueryId, packId, queries, ecsMapping, ...rest } = responseAction.params; - return osqueryCreateAction({ - ...rest, - queries, - ecs_mapping: ecsMapping, - saved_query_id: savedQueryId, - agent_ids: agentIds, - alert_ids: alertIds, + if (!containsDynamicQueries) { + return osqueryCreateAction({ + ...rest, + queries, + ecs_mapping: ecsMapping, + saved_query_id: savedQueryId, + agent_ids: agentIds, + alert_ids: alertIds, + }); + } + each(alerts, (alert) => { + return osqueryCreateAction( + { + ...rest, + queries, + ecs_mapping: ecsMapping, + saved_query_id: savedQueryId, + agent_ids: alert.agent?.id ? [alert.agent.id] : [], + alert_ids: [(alert as unknown as { _id: string })._id], + }, + alert + ); }); } }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.test.ts index 6f08defd91ab8..bb341d7e54230 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.test.ts @@ -16,6 +16,7 @@ import { enrichSignalThreatMatches, groupAndMergeSignalMatches, getSignalMatchesFromThreatList, + MAX_NUMBER_OF_SIGNAL_MATCHES, } from './enrich_signal_threat_matches'; import { getNamedQueryMock, getSignalHitMock } from './enrich_signal_threat_matches.mock'; import type { GetMatchedThreats, ThreatListItem, ThreatMatchNamedQuery } from './types'; @@ -802,7 +803,7 @@ describe('getSignalMatchesFromThreatList', () => { expect(signalMatches).toEqual([]); }); - it('return signal mathces from threat indicators', () => { + it('return signal matches from threat indicators', () => { const signalMatches = getSignalMatchesFromThreatList([ getThreatListItemMock({ _id: 'threatId', @@ -848,7 +849,7 @@ describe('getSignalMatchesFromThreatList', () => { ]); }); - it('merge signal mathces if different threat indicators matched the same signal', () => { + it('merge signal matches if different threat indicators matched the same signal', () => { const matchedQuery = [ encodeThreatMatchNamedQuery( getNamedQueryMock({ @@ -893,4 +894,26 @@ describe('getSignalMatchesFromThreatList', () => { }, ]); }); + + it('limits number of signal matches to MAX_NUMBER_OF_SIGNAL_MATCHES', () => { + const threatList = Array.from(Array(2000), (index) => + getThreatListItemMock({ + _id: `threatId-${index}`, + matched_queries: [ + encodeThreatMatchNamedQuery( + getNamedQueryMock({ + id: 'signalId1', + index: 'source_index', + value: 'threat.indicator.domain', + field: 'event.domain', + }) + ), + ], + }) + ); + + const signalMatches = getSignalMatchesFromThreatList(threatList); + + expect(signalMatches[0].queries).toHaveLength(MAX_NUMBER_OF_SIGNAL_MATCHES); + }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.ts index 1d8d68bd92d0d..e0b9d4fb6dee6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.ts @@ -18,6 +18,8 @@ import type { } from './types'; import { extractNamedQueries } from './utils'; +export const MAX_NUMBER_OF_SIGNAL_MATCHES = 1000; + export const getSignalMatchesFromThreatList = ( threatList: ThreatListItem[] = [] ): SignalMatch[] => { @@ -34,6 +36,15 @@ export const getSignalMatchesFromThreatList = ( signalMap[signalId] = []; } + // creating map of signal with large number of threats could lead to out of memory Kibana crash + // large number of threats also can cause signals bulk create failure due too large payload (413) + // large number of threats significantly slower alert details page render + // so, its number is limited to MAX_NUMBER_OF_SIGNAL_MATCHES + // more details https://github.com/elastic/kibana/issues/143595#issuecomment-1335433592 + if (signalMap[signalId].length >= MAX_NUMBER_OF_SIGNAL_MATCHES) { + return; + } + signalMap[signalId].push({ id: threatHit._id, index: threatHit._index, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_threat_list.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_threat_list.ts index c075f95a9dc98..c2ee1fee3c75a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_threat_list.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_threat_list.ts @@ -20,6 +20,8 @@ import type { */ export const INDICATOR_PER_PAGE = 1000; +const MAX_NUMBER_OF_THREATS = 10 * 1000; + export const getThreatList = async ({ esClient, index, @@ -123,7 +125,9 @@ export const getAllThreatListHits = async ( allThreatListHits = allThreatListHits.concat(threatList.hits.hits); - while (threatList.hits.hits.length !== 0) { + // to prevent loading in memory large number of results, that could lead to out of memory Kibana crash, + // number of indicators is limited to MAX_NUMBER_OF_THREATS + while (threatList.hits.hits.length !== 0 && allThreatListHits.length < MAX_NUMBER_OF_THREATS) { threatList = await getThreatList({ ...params, searchAfter: threatList.hits.hits[threatList.hits.hits.length - 1].sort, diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json index cc876b06cc773..ced495e35fbe7 100644 --- a/x-pack/plugins/security_solution/tsconfig.json +++ b/x-pack/plugins/security_solution/tsconfig.json @@ -125,6 +125,7 @@ "@kbn/core-status-common-internal", "@kbn/repo-info", "@kbn/storybook", + "@kbn/ecs", "@kbn/cypress-config", "@kbn/controls-plugin", "@kbn/shared-ux-utility", diff --git a/x-pack/plugins/spaces/public/nav_control/__snapshots__/nav_control_popover.test.tsx.snap b/x-pack/plugins/spaces/public/nav_control/__snapshots__/nav_control_popover.test.tsx.snap index 38a36d5b3657b..ea194bafa3d3c 100644 --- a/x-pack/plugins/spaces/public/nav_control/__snapshots__/nav_control_popover.test.tsx.snap +++ b/x-pack/plugins/spaces/public/nav_control/__snapshots__/nav_control_popover.test.tsx.snap @@ -15,6 +15,7 @@ exports[`NavControlPopover renders without crashing 1`] = ` title="loading spaces navigation" >

{ }); } + private getAlignedLoadingSpinner() { + return ; + } + private getActiveSpaceButton = () => { const { activeSpace } = this.state; if (!activeSpace) { - return this.getButton(, 'loading spaces navigation'); + return this.getButton(this.getAlignedLoadingSpinner(), 'loading spaces navigation'); } return this.getButton( - }> + , (activeSpace as Space).name diff --git a/x-pack/plugins/synthetics/common/constants/ui.ts b/x-pack/plugins/synthetics/common/constants/ui.ts index ad1c8b83736de..08752f08d231b 100644 --- a/x-pack/plugins/synthetics/common/constants/ui.ts +++ b/x-pack/plugins/synthetics/common/constants/ui.ts @@ -37,7 +37,7 @@ export const TEST_RUN_DETAILS_ROUTE = '/monitor/:monitorId/test-run/:checkGroupI export const MAPPING_ERROR_ROUTE = '/mapping-error'; -export const ERROR_DETAILS_ROUTE = '/error-details/:errorStateId'; +export const ERROR_DETAILS_ROUTE = '/monitor/:monitorId/errors/:errorStateId'; export enum STATUS { UP = 'up', diff --git a/x-pack/plugins/synthetics/e2e/fixtures/es_archiver/synthetics_data/data.json.gz b/x-pack/plugins/synthetics/e2e/fixtures/es_archiver/synthetics_data/data.json.gz new file mode 100644 index 0000000000000..f45419e4ada6d Binary files /dev/null and b/x-pack/plugins/synthetics/e2e/fixtures/es_archiver/synthetics_data/data.json.gz differ diff --git a/x-pack/plugins/synthetics/e2e/helpers/record_video.ts b/x-pack/plugins/synthetics/e2e/helpers/record_video.ts index d3b47b3104507..fc208cab66bea 100644 --- a/x-pack/plugins/synthetics/e2e/helpers/record_video.ts +++ b/x-pack/plugins/synthetics/e2e/helpers/record_video.ts @@ -14,12 +14,15 @@ const SYNTHETICS_RUNNER = Symbol.for('SYNTHETICS_RUNNER'); // @ts-ignore export const runner: Runner = global[SYNTHETICS_RUNNER]; -export const recordVideo = (page: Page) => { +export const recordVideo = (page: Page, postfix = '') => { after(async () => { try { const videoFilePath = await page.video()?.path(); const pathToVideo = videoFilePath?.replace('.journeys/videos/', '').replace('.webm', ''); - const newVideoPath = videoFilePath?.replace(pathToVideo!, runner.currentJourney!.name); + const newVideoPath = videoFilePath?.replace( + pathToVideo!, + runner.currentJourney!.name + `-${postfix}` + ); fs.renameSync(videoFilePath!, newVideoPath!); } catch (e) { // eslint-disable-next-line no-console diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/add_monitor.journey.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/add_monitor.journey.ts index 79bca822e7627..4fa5c32bb0eb2 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/synthetics/add_monitor.journey.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/add_monitor.journey.ts @@ -184,7 +184,7 @@ const createMonitorJourney = ({ }); step(`edit ${monitorName}`, async () => { - await syntheticsApp.navigateToEditMonitor(); + await syntheticsApp.navigateToEditMonitor(monitorName); await syntheticsApp.findByText(monitorListDetails.location); const hasFailure = await syntheticsApp.findEditMonitorConfiguration( monitorEditDetails, @@ -215,7 +215,7 @@ const createMonitorJourney = ({ Object.values(configuration).forEach((config) => { createMonitorJourney({ monitorType: config.monitorType, - monitorName: `${config.monitorConfig.name} monitor`, + monitorName: config.monitorConfig.name, monitorConfig: config.monitorConfig, monitorListDetails: config.monitorListDetails, monitorEditDetails: config.monitorEditDetails as Array<[string, string]>, diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/alert_rules/default_status_alert.journey.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/alert_rules/default_status_alert.journey.ts index 4976af8effd0b..f9a3744f577a8 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/synthetics/alert_rules/default_status_alert.journey.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/alert_rules/default_status_alert.journey.ts @@ -111,9 +111,13 @@ journey(`DefaultStatusAlert`, async ({ page, params }) => { }); await retry.tryForTime(2 * 60 * 1000, async () => { await page.click(byTestId('querySubmitButton')); - const text = await page.textContent(`${byTestId('dataGridRowCell')} .euiLink`, { - timeout: 5 * 1000, - }); + expect( + await page.isVisible(`text=1 Alert`, { + timeout: 10 * 1000, + }) + ).toBe(true); + + const text = await page.textContent(`${byTestId('dataGridRowCell')} .euiLink`); expect(text).toBe(reasonMessage); expect(await page.isVisible(`text=1 Alert`)).toBe(true); diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/data_retention.journey.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/data_retention.journey.ts new file mode 100644 index 0000000000000..28f1c6cdd622f --- /dev/null +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/data_retention.journey.ts @@ -0,0 +1,108 @@ +/* + * 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 { journey, step, expect, Page } from '@elastic/synthetics'; +import { assertText, byTestId } from '@kbn/observability-plugin/e2e/utils'; +import { RetryService } from '@kbn/ftr-common-functional-services'; +import { recordVideo } from '../../helpers/record_video'; +import { syntheticsAppPageProvider } from '../../page_objects/synthetics/synthetics_app'; + +let page1: Page; +journey(`DataRetentionPage`, async ({ page, params }) => { + page.setDefaultTimeout(60 * 1000); + recordVideo(page); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + + const getService = params.getService; + const retry: RetryService = getService('retry'); + + step('Go to monitor-management', async () => { + await syntheticsApp.navigateToMonitorManagement(true); + }); + + step('validate data retention tab', async () => { + await page.click('text=Settings'); + expect(page.url()).toBe('http://localhost:5620/app/synthetics/settings/alerting'); + await page.click('text=Data retention'); + expect(page.url()).toBe('http://localhost:5620/app/synthetics/settings/data-retention'); + await page.click('text=Synthetics data is configured by managed index lifecycle policies'); + + await page.click('text=0 Bytes'); + await page.click('text=365 days + rollover'); + await page.click('text=14 days + rollover'); + await page.click(':nth-match(:text("14 days + rollover"), 2)'); + await page.click(':nth-match(:text("365 days + rollover"), 2)'); + await page.click(':nth-match(:text("365 days + rollover"), 3)'); + await page.click(':nth-match(:text("365 days + rollover"), 4)'); + await page.click('tbody div:has-text("synthetics(opens in a new tab or window)")'); + }); + + step('validate data sizes', async () => { + const allChecks = await page.textContent(`tr:has-text("All Checks") span:has-text("KB")`); + const browserChecks = await page.textContent( + `tr:has-text("Browser Checks") span:has-text("KB")` + ); + const networkChecks = await page.textContent( + `tr:has-text("Browser Network Requests") span:has-text("KB")` + ); + const screenshotChecks = await page.textContent( + `tr:has-text("Browser Screenshots") span:has-text("KB")` + ); + expect(Number(allChecks?.split('KB')[0])).toBeGreaterThan(450); + expect(Number(browserChecks?.split('KB')[0])).toBeGreaterThan(50); + expect(Number(networkChecks?.split('KB')[0])).toBeGreaterThan(300); + expect(Number(screenshotChecks?.split('KB')[0])).toBeGreaterThan(25); + }); + + step('it can click through for policy', async () => { + [page1] = await Promise.all([ + page.waitForEvent('popup'), + page.click( + 'tbody div:has-text("synthetics-synthetics.browser-default_policy(opens in a new tab or window)")' + ), + ]); + recordVideo(page1, 'data_retention_policy_change'); + await page1.setDefaultTimeout(60 * 1000); + await page1.click('text=Edit policy synthetics-synthetics.browser-default_policy'); + await page1.click('text=Save as new policy'); + }); + + step('newly created policy is reflected in settings', async () => { + await page1.fill( + byTestId('policyNameField'), + 'synthetics-synthetics.browser-default_policy-copy' + ); + await page1.fill(byTestId('delete-selectedMinimumAge'), '10000'); + + await page1.click(byTestId('savePolicyButton')); + + await page1.click('text=Include managed system policies'); + + await page1.fill(byTestId('ilmSearchBar'), 'copy'); + + await retry.tryForTime(30 * 1000, async () => { + await page1.click(byTestId('addPolicyToTemplate'), { clickCount: 2, timeout: 5000 }); + expect(await page1.isVisible(byTestId('confirmModalConfirmButton'), { timeout: 5000 })).toBe( + true + ); + }); + + await page1.click(byTestId('comboBoxToggleListButton')); + await page1.fill(byTestId('comboBoxSearchInput'), 'synthetics-browser'); + + await page1.click('button[title="synthetics-browser"]'); + + await page1.click(byTestId('confirmModalConfirmButton')); + + await page.reload(); + + await page.click('tbody div:has-text("synthetics(opens in a new tab or window)")'); + await page1.close(); + + await assertText({ page, text: '10000 days + rollover' }); + }); +}); diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/index.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/index.ts index 07ff0371e16b7..0d0f3ef9637af 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/synthetics/index.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/index.ts @@ -18,3 +18,4 @@ export * from './alerting_default.journey'; export * from './global_parameters.journey'; export * from './detail_flyout'; export * from './alert_rules/default_status_alert.journey'; +export * from './data_retention.journey'; diff --git a/x-pack/plugins/synthetics/e2e/journeys/uptime/alerts/status_alert_flyouts_in_alerting_app.ts b/x-pack/plugins/synthetics/e2e/journeys/uptime/alerts/status_alert_flyouts_in_alerting_app.ts index 5f301606f5c53..c6d3454182a7b 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/uptime/alerts/status_alert_flyouts_in_alerting_app.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/uptime/alerts/status_alert_flyouts_in_alerting_app.ts @@ -62,8 +62,10 @@ journey('StatusFlyoutInAlertingApp', async ({ page, params }) => { await assertText({ page, text: 'browser' }); await assertText({ page, text: 'http' }); - const suggestionItem = await page.$(byTestId('autoCompleteSuggestionText')); - expect(await suggestionItem?.textContent()).toBe('"browser" '); + await retry.tryForTime(30 * 1000, async () => { + const suggestionItem = await page.$(byTestId('autoCompleteSuggestionText')); + expect(await suggestionItem?.textContent()).toBe('"browser" '); + }); await page.click(byTestId('euiFlyoutCloseButton')); await page.click(byTestId('confirmModalConfirmButton')); diff --git a/x-pack/plugins/synthetics/e2e/page_objects/synthetics/synthetics_app.tsx b/x-pack/plugins/synthetics/e2e/page_objects/synthetics/synthetics_app.tsx index d81cf109c0978..ae0db8ceb8760 100644 --- a/x-pack/plugins/synthetics/e2e/page_objects/synthetics/synthetics_app.tsx +++ b/x-pack/plugins/synthetics/e2e/page_objects/synthetics/synthetics_app.tsx @@ -93,7 +93,10 @@ export function syntheticsAppPageProvider({ page, kibanaUrl }: { page: Page; kib isSuccessful = true; break; } - await page.click(this.byTestId('euiCollapsedItemActionsButton'), { delay: 800 }); + await page.click(this.byTestId('euiCollapsedItemActionsButton'), { + delay: 800, + force: true, + }); await page.click(`.euiContextMenuPanel ${this.byTestId('syntheticsMonitorDeleteAction')}`, { delay: 800, }); @@ -106,9 +109,12 @@ export function syntheticsAppPageProvider({ page, kibanaUrl }: { page: Page; kib return isSuccessful; }, - async navigateToEditMonitor() { + async navigateToEditMonitor(monitorName: string) { + await this.adjustRows(); await page.waitForSelector('text=Showing'); - await this.clickByTestSubj('euiCollapsedItemActionsButton'); + await page.click( + `tr:has-text("${monitorName}") [data-test-subj="euiCollapsedItemActionsButton"]` + ); await page.click(`.euiContextMenuPanel ${this.byTestId('syntheticsMonitorEditAction')}`, { timeout: 2 * 60 * 1000, delay: 800, @@ -168,6 +174,12 @@ export function syntheticsAppPageProvider({ page, kibanaUrl }: { page: Page; kib await page.fill('[data-test-subj=codeEditorContainer] textarea', value); }, + async adjustRows() { + await page.click('[data-test-subj="tablePaginationPopoverButton"]'); + await page.click('text="100 rows"'); + await page.waitForTimeout(3e3); + }, + async createBasicHTTPMonitorDetails({ name, url, diff --git a/x-pack/plugins/synthetics/e2e/synthetics_run.ts b/x-pack/plugins/synthetics/e2e/synthetics_run.ts index 6dde22296d4c4..dd37b8dc87352 100644 --- a/x-pack/plugins/synthetics/e2e/synthetics_run.ts +++ b/x-pack/plugins/synthetics/e2e/synthetics_run.ts @@ -25,7 +25,11 @@ async function runE2ETests({ readConfigFile }: FtrConfigProviderContext) { await syntheticsRunner.setup(); const fixturesDir = path.join(__dirname, '../e2e/fixtures/es_archiver/'); - await syntheticsRunner.loadTestData(fixturesDir, ['full_heartbeat', 'browser']); + await syntheticsRunner.loadTestData(fixturesDir, [ + 'synthetics_data', + 'full_heartbeat', + 'browser', + ]); await syntheticsRunner.loadTestFiles(async () => { require('./journeys'); diff --git a/x-pack/plugins/synthetics/kibana.json b/x-pack/plugins/synthetics/kibana.json index e3a0111fda77a..32bfa61698f98 100644 --- a/x-pack/plugins/synthetics/kibana.json +++ b/x-pack/plugins/synthetics/kibana.json @@ -28,7 +28,7 @@ "server": true, "ui": true, "version": "8.0.0", - "requiredBundles": ["unifiedSearch", "fleet", "kibanaReact", "kibanaUtils", "ml", "observability", "indexLifecycleManagement"], + "requiredBundles": ["data","unifiedSearch", "fleet", "kibanaReact", "kibanaUtils", "ml", "observability", "indexLifecycleManagement"], "owner": { "name": "Uptime", "githubTeam": "uptime" diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/panel_with_title.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/panel_with_title.tsx new file mode 100644 index 0000000000000..9bc1cc480bc81 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/panel_with_title.tsx @@ -0,0 +1,30 @@ +/* + * 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, useEuiTheme, EuiPanelProps } from '@elastic/eui'; +import React from 'react'; + +export const PanelWithTitle: React.FC<{ title?: string } & EuiPanelProps> = ({ + title, + hasBorder = true, + hasShadow = false, + children, + ...props +}) => { + const { euiTheme } = useEuiTheme(); + + return ( + + {title && ( + +

{title}

+ + )} + {children} + + ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/links/step_details_link.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/links/step_details_link.tsx new file mode 100644 index 0000000000000..078e9d924fbbe --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/links/step_details_link.tsx @@ -0,0 +1,38 @@ +/* + * 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 { EuiButtonIcon } from '@elastic/eui'; +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { useSelectedLocation } from '../../monitor_details/hooks/use_selected_location'; +import { useSyntheticsSettingsContext } from '../../../contexts'; + +export const StepDetailsLinkIcon = ({ + stepIndex, + checkGroup, +}: { + checkGroup: string; + stepIndex?: number; +}) => { + const { basePath } = useSyntheticsSettingsContext(); + const selectedLocation = useSelectedLocation(); + + return ( + + ); +}; + +const VIEW_DETAILS = i18n.translate('xpack.synthetics.monitor.step.viewStepDetails', { + defaultMessage: 'View step details', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/links/test_details_link.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/links/test_details_link.tsx index be3a5d7b01c99..2516018f7f139 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/links/test_details_link.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/links/test_details_link.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { EuiLink, EuiText, useEuiTheme } from '@elastic/eui'; +import { useSelectedLocation } from '../../monitor_details/hooks/use_selected_location'; import { Ping } from '../../../../../../common/runtime_types'; import { useSyntheticsSettingsContext } from '../../../contexts'; import { useKibanaDateFormat } from '../../../../../hooks/use_kibana_date_format'; @@ -23,6 +24,7 @@ export const TestDetailsLink = ({ }) => { const { euiTheme } = useEuiTheme(); const { basePath } = useSyntheticsSettingsContext(); + const selectedLocation = useSelectedLocation(); const format = useKibanaDateFormat(); const timestampText = ( @@ -33,9 +35,12 @@ export const TestDetailsLink = ({ return isBrowserMonitor ? ( {timestampText} @@ -43,3 +48,22 @@ export const TestDetailsLink = ({ timestampText ); }; + +export const getTestRunDetailLink = ({ + monitorId, + basePath, + checkGroup, + locationId, +}: { + monitorId: string; + checkGroup: string; + basePath?: string; + locationId?: string; +}) => { + const testRunUrl = `/monitor/${monitorId}/test-run/${checkGroup}?locationId=${locationId}`; + if (basePath) { + return `${basePath}/app/synthetics${testRunUrl}`; + } else { + return testRunUrl; + } +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/browser_steps_list.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/browser_steps_list.tsx index a241988cedc7a..4c18e968ef2b3 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/browser_steps_list.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/browser_steps_list.tsx @@ -7,17 +7,11 @@ import { i18n } from '@kbn/i18n'; import React, { CSSProperties } from 'react'; -import { - EuiBasicTable, - EuiBasicTableColumn, - EuiButtonIcon, - EuiText, - useEuiTheme, -} from '@elastic/eui'; +import { EuiBasicTable, EuiBasicTableColumn, EuiText, useEuiTheme } from '@elastic/eui'; import { EuiThemeComputed } from '@elastic/eui/src/services/theme/types'; +import { StepDetailsLinkIcon } from '../links/step_details_link'; import { JourneyStepScreenshotContainer } from '../screenshot/journey_step_screenshot_container'; -import { useSyntheticsSettingsContext } from '../../../contexts/synthetics_settings_context'; import { JourneyStep } from '../../../../../../common/runtime_types'; import { StatusBadge, parseBadgeStatus, getTextColorForMonitorStatus } from './status_badge'; @@ -46,8 +40,6 @@ export const BrowserStepsList = ({ const stepEnds: JourneyStep[] = steps.filter(isStepEnd); const stepLabels = stepEnds.map((stepEnd) => stepEnd?.synthetics?.step?.name ?? ''); - const { basePath } = useSyntheticsSettingsContext(); - const columns: Array> = [ ...(showStepNumber ? [ @@ -125,13 +117,9 @@ export const BrowserStepsList = ({ name: '', mobileOptions: { show: false }, render: (_val: string, item) => ( - ), }, @@ -201,7 +189,3 @@ const STEP_NAME = i18n.translate('xpack.synthetics.monitor.stepName.label', { const STEP_DURATION = i18n.translate('xpack.synthetics.monitor.step.duration.label', { defaultMessage: 'Duration', }); - -const VIEW_DETAILS = i18n.translate('xpack.synthetics.monitor.step.viewDetails', { - defaultMessage: 'View Details', -}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_duration.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_duration.tsx new file mode 100644 index 0000000000000..9b65149be3ad0 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_duration.tsx @@ -0,0 +1,28 @@ +/* + * 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 { EuiDescriptionList } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import moment from 'moment'; +import { useErrorFailedTests } from '../hooks/use_last_error_state'; + +export const ErrorDuration: React.FC = () => { + const { failedTests } = useErrorFailedTests(); + + const state = failedTests?.[0]?.state; + + const duration = state ? moment().diff(moment(state?.started_at), 'minutes') : 0; + + return ( + + ); +}; + +const ERROR_DURATION = i18n.translate('xpack.synthetics.errorDetails.errorDuration', { + defaultMessage: 'Error duration', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_started_at.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_started_at.tsx new file mode 100644 index 0000000000000..a6c3efb161711 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_started_at.tsx @@ -0,0 +1,30 @@ +/* + * 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, { ReactElement } from 'react'; +import { EuiDescriptionList, EuiLoadingContent } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { useErrorFailedTests } from '../hooks/use_last_error_state'; +import { useFormatTestRunAt } from '../../../utils/monitor_test_result/test_time_formats'; + +export const ErrorStartedAt: React.FC = () => { + const { failedTests } = useErrorFailedTests(); + + const state = failedTests?.[0]?.state; + + let startedAt: string | ReactElement = useFormatTestRunAt(state?.started_at); + + if (!startedAt) { + startedAt = ; + } + + return ; +}; + +const ERROR_DURATION = i18n.translate('xpack.synthetics.errorDetails.startedAt', { + defaultMessage: 'Started at', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_timeline.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_timeline.tsx new file mode 100644 index 0000000000000..30461842e963f --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_timeline.tsx @@ -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. + */ +import React from 'react'; +import { MonitorFailedTests } from '../../monitor_details/monitor_errors/failed_tests'; + +export const ErrorTimeline = () => { + return ; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/failed_tests_list.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/failed_tests_list.tsx new file mode 100644 index 0000000000000..9cf644153470a --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/failed_tests_list.tsx @@ -0,0 +1,125 @@ +/* + * 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'; +import React, { MouseEvent, useState } from 'react'; +import { EuiBasicTable, EuiLink, EuiSpacer, EuiText } from '@elastic/eui'; +import { useHistory, useParams } from 'react-router-dom'; +import { useKibanaDateFormat } from '../../../../../hooks/use_kibana_date_format'; +import { Ping } from '../../../../../../common/runtime_types'; +import { + formatTestDuration, + formatTestRunAt, +} from '../../../utils/monitor_test_result/test_time_formats'; +import { useSyntheticsSettingsContext } from '../../../contexts'; + +export const FailedTestsList = ({ + failedTests, + loading, +}: { + failedTests: Ping[]; + loading?: boolean; +}) => { + const [pageIndex, setPageIndex] = useState(0); + const [pageSize, setPageSize] = useState(5); + const [sortField, setSortField] = useState('@timestamp'); + const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc'); + + const { monitorId } = useParams<{ monitorId: string }>(); + + const items = failedTests.slice(pageIndex * pageSize, pageIndex * pageSize + pageSize); + + const { basePath } = useSyntheticsSettingsContext(); + + const history = useHistory(); + + const format = useKibanaDateFormat(); + + const columns = [ + { + field: '@timestamp', + name: TIMESTAMP_LABEL, + sortable: true, + render: (value: string, item: Ping) => { + return ( + + {formatTestRunAt(value, format)} + + ); + }, + }, + { + field: 'monitor.duration.us', + name: MONITOR_DURATION_LABEL, + align: 'right' as const, + render: (value: number) => {formatTestDuration(value)}, + }, + ]; + + const pagination = { + pageIndex, + pageSize, + totalItemCount: failedTests.length, + pageSizeOptions: [3, 5, 8], + }; + + const getRowProps = (item: Ping) => { + const { state } = item; + if (state?.id) { + return { + 'data-test-subj': `row-${state.id}`, + onClick: (evt: MouseEvent) => { + history.push(`/monitor/${monitorId}/test-run/${item.monitor.check_group}`); + }, + }; + } + }; + + return ( +
+ + { + const { index: pIndex, size: pSize } = page; + + const { field: sField, direction: sDirection } = sort; + + setPageIndex(pIndex!); + setPageSize(pSize!); + setSortField(sField!); + setSortDirection(sDirection!); + }} + rowProps={getRowProps} + /> +
+ ); +}; + +const ERRORS_LIST_LABEL = i18n.translate('xpack.synthetics.errorsList.label', { + defaultMessage: 'Errors list', +}); + +const MONITOR_DURATION_LABEL = i18n.translate('xpack.synthetics.testDuration.label', { + defaultMessage: 'Test duration', +}); + +const TIMESTAMP_LABEL = i18n.translate('xpack.synthetics.timestamp.label', { + defaultMessage: '@timestamp', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/resolved_at.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/resolved_at.tsx new file mode 100644 index 0000000000000..75b1f9a31690b --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/resolved_at.tsx @@ -0,0 +1,30 @@ +/* + * 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, { ReactElement } from 'react'; +import { EuiDescriptionList } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { useErrorFailedTests } from '../hooks/use_last_error_state'; +import { useFormatTestRunAt } from '../../../utils/monitor_test_result/test_time_formats'; + +export const ResolvedAt: React.FC = () => { + const { failedTests } = useErrorFailedTests(); + + const state = failedTests?.[0]?.state; + + let endsAt: string | ReactElement = useFormatTestRunAt(state?.ends ?? ''); + + if (!endsAt) { + endsAt = 'N/A'; + } + + return ; +}; + +const ERROR_DURATION = i18n.translate('xpack.synthetics.errorDetails.resolvedAt', { + defaultMessage: 'Resolved at', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/error_details_page.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/error_details_page.tsx index 01fbd377a04c9..c9d11d25defe2 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/error_details_page.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/error_details_page.tsx @@ -5,13 +5,83 @@ * 2.0. */ -import { EuiLoadingLogo } from '@elastic/eui'; import React from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import { StepDurationPanel } from '../monitor_details/monitor_summary/step_duration_panel'; +import { useFormatTestRunAt } from '../../utils/monitor_test_result/test_time_formats'; +import { LastTestRunComponent } from '../monitor_details/monitor_summary/last_test_run'; +import { MonitorDetailsPanel } from '../monitor_details/monitor_summary/monitor_details_panel'; +import { useStepDetails } from './hooks/use_step_details'; +import { StepDetails } from '../test_run_details/components/step_details'; +import { PanelWithTitle } from '../common/components/panel_with_title'; +import { useErrorFailedTests } from './hooks/use_error_failed_tests'; +import { useJourneySteps } from '../monitor_details/hooks/use_journey_steps'; +import { FailedTestsList } from './components/failed_tests_list'; +import { ErrorTimeline } from './components/error_timeline'; +import { useErrorDetailsBreadcrumbs } from './hooks/use_error_details_breadcrumbs'; +import { StepImage } from '../step_details_page/step_screenshot/step_image'; export function ErrorDetailsPage() { + const { failedTests, loading } = useErrorFailedTests(); + + const checkGroupId = failedTests?.[0]?.monitor.check_group ?? ''; + + const { + data, + isFailed, + failedStep, + stepLabels, + loading: stepsLoading, + } = useJourneySteps(checkGroupId); + + const lastTestRun = failedTests?.[0]; + + const startedAt = useFormatTestRunAt(lastTestRun?.state?.started_at); + + useErrorDetailsBreadcrumbs([{ text: startedAt }]); + + const stepDetails = useStepDetails({ checkGroup: lastTestRun?.monitor.check_group }); + return (
- TODO: + + + + + + + + + + + + + + + + + {data?.details?.journey && failedStep && ( + + )} + + + + + + + +
); } diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_details_breadcrumbs.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_details_breadcrumbs.ts new file mode 100644 index 0000000000000..61cef2b818615 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_details_breadcrumbs.ts @@ -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 { i18n } from '@kbn/i18n'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useTestRunDetailsBreadcrumbs } from '../../test_run_details/hooks/use_test_run_details_breadcrumbs'; +import { useSelectedMonitor } from '../../monitor_details/hooks/use_selected_monitor'; +import { ConfigKey } from '../../../../../../common/runtime_types'; +import { PLUGIN } from '../../../../../../common/constants/plugin'; + +export const useErrorDetailsBreadcrumbs = ( + extraCrumbs?: Array<{ text: string; href?: string }> +) => { + const kibana = useKibana(); + const appPath = kibana.services.application?.getUrlForApp(PLUGIN.SYNTHETICS_PLUGIN_ID) ?? ''; + + const { monitor } = useSelectedMonitor(); + + const errorsBreadcrumbs = [ + { + text: ERRORS_CRUMB, + href: `${appPath}/monitor/${monitor?.[ConfigKey.CONFIG_ID]}/errors`, + }, + ...(extraCrumbs ?? []), + ]; + + useTestRunDetailsBreadcrumbs(errorsBreadcrumbs); +}; + +const ERRORS_CRUMB = i18n.translate('xpack.synthetics.monitorsPage.errors', { + defaultMessage: 'Errors', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_failed_tests.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_failed_tests.tsx new file mode 100644 index 0000000000000..241c410038276 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_failed_tests.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useEsSearch } from '@kbn/observability-plugin/public'; +import { useParams } from 'react-router-dom'; +import { useMemo } from 'react'; +import { Ping } from '../../../../../../common/runtime_types'; +import { + EXCLUDE_RUN_ONCE_FILTER, + SUMMARY_FILTER, +} from '../../../../../../common/constants/client_defaults'; +import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants'; +import { useSyntheticsRefreshContext } from '../../../contexts'; +import { useGetUrlParams } from '../../../hooks'; + +export function useErrorFailedTests() { + const { lastRefresh } = useSyntheticsRefreshContext(); + + const { errorStateId, monitorId } = useParams<{ errorStateId: string; monitorId: string }>(); + + const { dateRangeStart, dateRangeEnd } = useGetUrlParams(); + + const { data, loading } = useEsSearch( + { + index: SYNTHETICS_INDEX_PATTERN, + body: { + size: 10000, + query: { + bool: { + filter: [ + SUMMARY_FILTER, + EXCLUDE_RUN_ONCE_FILTER, + { + term: { + 'state.id': errorStateId, + }, + }, + { + term: { + config_id: monitorId, + }, + }, + ], + }, + }, + sort: [{ '@timestamp': 'desc' }], + }, + }, + [lastRefresh, monitorId, dateRangeStart, dateRangeEnd], + { name: 'getMonitorErrorFailedTests' } + ); + + return useMemo(() => { + const failedTests = + data?.hits.hits?.map((doc) => { + return doc._source as Ping; + }) ?? []; + + return { + failedTests, + loading, + }; + }, [data, loading]); +} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_last_error_state.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_last_error_state.tsx new file mode 100644 index 0000000000000..c0f100a3441ca --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_last_error_state.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useParams } from 'react-router-dom'; +import { useMemo } from 'react'; +import { useReduxEsSearch } from '../../../hooks/use_redux_es_search'; +import { Ping } from '../../../../../../common/runtime_types'; +import { + EXCLUDE_RUN_ONCE_FILTER, + SUMMARY_FILTER, +} from '../../../../../../common/constants/client_defaults'; +import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants'; +import { useSyntheticsRefreshContext } from '../../../contexts'; +import { useGetUrlParams } from '../../../hooks'; + +export function useErrorFailedTests() { + const { lastRefresh } = useSyntheticsRefreshContext(); + + const { errorStateId, monitorId } = useParams<{ errorStateId: string; monitorId: string }>(); + + const { dateRangeStart, dateRangeEnd } = useGetUrlParams(); + + const { data, loading } = useReduxEsSearch( + { + index: SYNTHETICS_INDEX_PATTERN, + body: { + size: 1000, + query: { + bool: { + filter: [ + SUMMARY_FILTER, + EXCLUDE_RUN_ONCE_FILTER, + { + term: { + 'state.id': errorStateId, + }, + }, + { + term: { + config_id: monitorId, + }, + }, + ], + }, + }, + sort: [{ '@timestamp': 'desc' }], + }, + }, + [lastRefresh, monitorId, dateRangeStart, dateRangeEnd], + { name: 'getMonitorErrorFailedTests' } + ); + + return useMemo(() => { + const failedTests = + data?.hits.hits?.map((doc) => { + return doc._source as Ping; + }) ?? []; + + return { + failedTests, + loading, + }; + }, [data, loading]); +} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_step_details.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_step_details.ts new file mode 100644 index 0000000000000..17111cabc0b78 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_step_details.ts @@ -0,0 +1,28 @@ +/* + * 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 { useJourneySteps } from '../../monitor_details/hooks/use_journey_steps'; + +export const useStepDetails = ({ checkGroup }: { checkGroup: string }) => { + const [stepIndex, setStepIndex] = React.useState(1); + + const { data: stepsData, loading: stepsLoading, stepEnds } = useJourneySteps(checkGroup); + + const step = stepEnds.find((stepN) => stepN.synthetics?.step?.index === stepIndex); + + const totalSteps = stepsLoading ? 1 : stepEnds.length; + + return { + step, + stepIndex, + setStepIndex, + totalSteps, + stepsData, + loading: stepsLoading, + }; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/route_config.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/route_config.tsx new file mode 100644 index 0000000000000..fe2608fea7256 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/route_config.tsx @@ -0,0 +1,48 @@ +/* + * 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'; +import { useHistory } from 'react-router-dom'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React from 'react'; +import { ResolvedAt } from './components/resolved_at'; +import { ErrorStartedAt } from './components/error_started_at'; +import { ErrorDetailsPage } from './error_details_page'; +import { ErrorDuration } from './components/error_duration'; +import { MonitorDetailsLocation } from '../monitor_details/monitor_details_location'; +import { ERROR_DETAILS_ROUTE } from '../../../../../common/constants'; +import { RouteProps } from '../../routes'; + +export const getErrorDetailsRouteConfig = ( + history: ReturnType, + syntheticsPath: string, + baseTitle: string +) => { + return { + title: i18n.translate('xpack.synthetics.errorDetailsRoute.title', { + defaultMessage: 'Error details | {baseTitle}', + values: { baseTitle }, + }), + path: ERROR_DETAILS_ROUTE, + component: ErrorDetailsPage, + dataTestSubj: 'syntheticsMonitorEditPage', + pageHeader: { + pageTitle: ( + + ), + rightSideItems: [ + , + , + , + , + ], + }, + } as RouteProps; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/monitor_details_portal.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/monitor_details_portal.tsx index 94ff55a5295bd..13461fb3dcc5a 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/monitor_details_portal.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/monitor_details_portal.tsx @@ -9,26 +9,35 @@ import React from 'react'; import { useHistory } from 'react-router-dom'; import { EuiLink, EuiIcon } from '@elastic/eui'; import { InPortal } from 'react-reverse-portal'; +import { useSelectedLocation } from '../monitor_details/hooks/use_selected_location'; import { MonitorDetailsLinkPortalNode } from './portals'; -export const MonitorDetailsLinkPortal = ({ - name, - configId, -}: { +interface Props { name: string; configId: string; -}) => { + locationId?: string; +} + +export const MonitorDetailsLinkPortal = ({ name, configId, locationId }: Props) => { return ( - + ); }; -export const MonitorDetailsLink = ({ name, configId }: { name: string; configId: string }) => { +export const MonitorDetailsLink = ({ name, configId, locationId }: Props) => { + const selectedLocation = useSelectedLocation(); + + let locId = locationId; + + if (selectedLocation?.id && !locationId) { + locId = selectedLocation.id; + } + const history = useHistory(); const href = history.createHref({ - pathname: `monitor/${configId}`, + pathname: locId ? `monitor/${configId}?locationId=${locId}` : `monitor/${configId}`, }); return ( diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_journey_steps.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_journey_steps.tsx index f8fc989c3cdc3..6fb0bf83801a3 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_journey_steps.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_journey_steps.tsx @@ -31,18 +31,23 @@ export const useJourneySteps = (checkGroup?: string, lastRefresh?: number) => { step.synthetics?.step?.status === 'failed' || step.synthetics?.step?.status === 'skipped' ) ?? false; + const failedStep = data?.steps.find((step) => step.synthetics?.step?.status === 'failed'); + const stepEnds: JourneyStep[] = (data?.steps ?? []).filter(isStepEnd); const stepLabels = stepEnds.map((stepEnd) => stepEnd?.synthetics?.step?.name ?? ''); + const currentStep = stepIndex + ? data?.steps.find((step) => step.synthetics?.step?.index === Number(stepIndex)) + : undefined; + return { data: data as SyntheticsJourneyApiResponse, loading: loading ?? false, isFailed, stepEnds, stepLabels, - currentStep: stepIndex - ? data?.steps.find((step) => step.synthetics?.step?.index === Number(stepIndex)) - : undefined, + currentStep, + failedStep, }; }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_latest_ping.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_latest_ping.tsx index 2c989121d5ad9..04d825ce73720 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_latest_ping.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_latest_ping.tsx @@ -8,6 +8,7 @@ import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { ConfigKey } from '../../../../../../common/runtime_types'; +import { useSyntheticsRefreshContext } from '../../../contexts'; import { getMonitorLastRunAction, selectLastRunMetadata } from '../../../state'; import { useSelectedLocation } from './use_selected_location'; import { useSelectedMonitor } from './use_selected_monitor'; @@ -19,6 +20,7 @@ interface UseMonitorLatestPingParams { export const useMonitorLatestPing = (params?: UseMonitorLatestPingParams) => { const dispatch = useDispatch(); + const { lastRefresh } = useSyntheticsRefreshContext(); const { monitor } = useSelectedMonitor(); const location = useSelectedLocation(); @@ -41,7 +43,7 @@ export const useMonitorLatestPing = (params?: UseMonitorLatestPingParams) => { if (monitorId && locationLabel && !isUpToDate) { dispatch(getMonitorLastRunAction.get({ monitorId, locationId: locationLabel })); } - }, [dispatch, monitorId, locationLabel, isUpToDate]); + }, [dispatch, monitorId, locationLabel, isUpToDate, lastRefresh]); if (!monitorId || !locationLabel) { return { loading, latestPing: undefined }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_location.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_location.tsx index eb93b713b9cf7..d41b086010482 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_location.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_location.tsx @@ -11,6 +11,7 @@ import { EuiHealth, EuiIcon, EuiLink, + EuiLoadingContent, EuiPopover, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -120,7 +121,11 @@ export const MonitorDetailsLocation: React.FC = () => { ]); if (!selectedLocation || !monitor) { - return null; + return ( + }]} + /> + ); } return ; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/errors_list.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/errors_list.tsx index 12443d7896c04..48f6ea76b12ed 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/errors_list.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/errors_list.tsx @@ -8,7 +8,8 @@ import { i18n } from '@kbn/i18n'; import React, { MouseEvent, useMemo, useState } from 'react'; import { EuiBasicTable, EuiLink, EuiSpacer, EuiText } from '@elastic/eui'; -import { useHistory } from 'react-router-dom'; +import { useHistory, useParams } from 'react-router-dom'; +import { useSelectedLocation } from '../hooks/use_selected_location'; import { useKibanaDateFormat } from '../../../../../hooks/use_kibana_date_format'; import { Ping } from '../../../../../../common/runtime_types'; import { useErrorFailedStep } from '../hooks/use_error_failed_step'; @@ -27,6 +28,8 @@ export const ErrorsList = () => { const { errorStates, loading } = useMonitorErrors(); + const { monitorId } = useParams<{ monitorId: string }>(); + const items = errorStates.slice(pageIndex * pageSize, pageIndex * pageSize + pageSize); const checkGroups = useMemo(() => { @@ -45,6 +48,8 @@ export const ErrorsList = () => { const format = useKibanaDateFormat(); + const selectedLocation = useSelectedLocation(); + const columns = [ { field: '@timestamp', @@ -52,7 +57,14 @@ export const ErrorsList = () => { sortable: true, render: (value: string, item: Ping) => { return ( - + {formatTestRunAt(item.state!.started_at, format)} ); @@ -99,7 +111,9 @@ export const ErrorsList = () => { height: '85px', 'data-test-subj': `row-${state.id}`, onClick: (evt: MouseEvent) => { - history.push(`/error-details/${state.id}`); + history.push( + `/monitor/${monitorId}/errors/${state.id}?locationId=${selectedLocation?.id}` + ); }, }; } @@ -136,6 +150,20 @@ export const ErrorsList = () => { ); }; +export const getErrorDetailsUrl = ({ + basePath, + monitorId, + stateId, + locationId, +}: { + stateId: string; + basePath: string; + monitorId: string; + locationId: string; +}) => { + return `${basePath}/app/synthetics/monitor/${monitorId}/errors/${stateId}?locationId=${locationId}`; +}; + const ERRORS_LIST_LABEL = i18n.translate('xpack.synthetics.errorsList.label', { defaultMessage: 'Errors list', }); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/failed_tests.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/failed_tests.tsx index c801036e78fd5..b45428f292c24 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/failed_tests.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/failed_tests.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useParams } from 'react-router-dom'; import { useMonitorQueryId } from '../hooks/use_monitor_query_id'; import { ClientPluginsStart } from '../../../../../plugin'; @@ -17,7 +18,9 @@ export const MonitorFailedTests = ({ time }: { time: { to: string; from: string const monitorId = useMonitorQueryId(); - if (!monitorId) { + const { errorStateId } = useParams<{ errorStateId: string }>(); + + if (!monitorId && !errorStateId) { return null; } @@ -31,7 +34,7 @@ export const MonitorFailedTests = ({ time }: { time: { to: string; from: string { time, reportDefinitions: { - 'monitor.id': [monitorId], + ...(monitorId ? { 'monitor.id': [monitorId] } : { 'state.id': [errorStateId] }), }, dataType: 'synthetics', selectedMetricField: 'failed_tests', diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/monitor_searchable_list.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/monitor_searchable_list.tsx index 7f08cfcbd59bd..caafd24a87335 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/monitor_searchable_list.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/monitor_searchable_list.tsx @@ -22,11 +22,15 @@ import { useMonitorName } from './use_monitor_name'; import { AddMonitorLink } from '../../common/links/add_monitor'; import { useSyntheticsSettingsContext } from '../../../contexts'; +type MonitorOption = EuiSelectableOption & { + locationIds?: string[]; +}; + export const MonitorSearchableList = ({ closePopover }: { closePopover: () => void }) => { const history = useHistory(); const recentlyViewed = useRecentlyViewedMonitors(); - const [options, setOptions] = useState([]); + const [options, setOptions] = useState([]); const [searchValue, setSearchValue] = useState(''); const selectedLocation = useSelectedLocation(); @@ -36,14 +40,19 @@ export const MonitorSearchableList = ({ closePopover }: { closePopover: () => vo const { values, loading } = useMonitorName({ search: searchValue }); useEffect(() => { - const newOptions: EuiSelectableOption[] = []; + const newOptions: MonitorOption[] = []; if (recentlyViewed.length > 0 && !searchValue) { const otherMonitors = values.filter((value) => recentlyViewed.every((recent) => recent.key !== value.key) - ); + ) as MonitorOption[]; if (otherMonitors.length > 0) { - newOptions.push({ key: 'monitors', label: OTHER_MONITORS, isGroupLabel: true }); + newOptions.push({ + key: 'monitors', + label: OTHER_MONITORS, + isGroupLabel: true, + locationIds: [], + }); } setOptions([...recentlyViewed, ...newOptions, ...otherMonitors]); @@ -52,8 +61,15 @@ export const MonitorSearchableList = ({ closePopover }: { closePopover: () => vo } }, [recentlyViewed, searchValue, values]); + const getLocationId = (option: MonitorOption) => { + if (option.locationIds?.includes(selectedLocation?.id ?? '')) { + return selectedLocation?.id; + } + return option.locationIds?.[0]; + }; + return ( - searchable isLoading={loading} searchProps={{ @@ -67,7 +83,7 @@ export const MonitorSearchableList = ({ closePopover }: { closePopover: () => vo setOptions(selectedOptions); const option = selectedOptions.find((opt) => opt.checked === 'on'); if (option) { - history.push(`/monitor/${option.key}?locationId=${selectedLocation?.id}`); + history.push(`/monitor/${option.key}?locationId=${getLocationId(option)}`); } closePopover(); }} @@ -77,7 +93,9 @@ export const MonitorSearchableList = ({ closePopover }: { closePopover: () => vo }} renderOption={(option, search) => ( {option.label} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_monitor_name.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_monitor_name.ts index cb097b0f99342..497d2d64d1c6a 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_monitor_name.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_monitor_name.ts @@ -28,6 +28,7 @@ export const useMonitorName = ({ search = '' }: { search?: string }) => { const values = monitors.map((monitor) => ({ label: monitor.attributes.name as string, key: monitor.id, + locationIds: monitor.attributes.locations.map((location) => location.id), })); return { values: values.filter((val) => val.key !== monitorId), loading }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.test.tsx index 8c5922f4acc7a..e1e0e288cf4a1 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.test.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; import { useRecentlyViewedMonitors } from './use_recently_viewed_monitors'; import { mockCore, WrappedHelper } from '../../../utils/testing'; import { syntheticsMonitorType } from '../../../../../../common/types/saved_objects'; @@ -19,6 +20,7 @@ const resultData = { attributes: { name: 'Test Monitor', + locations: [], }, }, }, @@ -68,16 +70,19 @@ describe('useRecentlyViewedMonitors', () => { await waitForNextUpdate(); - expect(result.current).toEqual([ - { - isGroupLabel: true, - key: 'recently_viewed', - label: 'Recently viewed', - }, - { - key: 'c9322230-2a11-11ed-962b-d3e7eeedf9d1', - label: 'Test Monitor', - }, - ]); + await waitFor(() => { + expect(result.current).toEqual([ + { + isGroupLabel: true, + key: 'recently_viewed', + label: 'Recently viewed', + }, + { + key: 'c9322230-2a11-11ed-962b-d3e7eeedf9d1', + label: 'Test Monitor', + locationIds: [], + }, + ]); + }); }); }); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.ts index 64f7a60c28c7a..569b5f14539f4 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.ts @@ -61,6 +61,7 @@ export const useRecentlyViewedMonitors = () => { .map(({ saved_object: monitor }) => ({ key: monitor.id, label: (monitor.attributes as MonitorFields).name, + locationIds: (monitor.attributes as MonitorFields).locations.map((location) => location.id), })); }, [monitorId, recentlyViewed]); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/last_test_run.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/last_test_run.tsx index ef5d3bd535a54..b3aa2e129dc81 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/last_test_run.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/last_test_run.tsx @@ -22,11 +22,14 @@ import { import { i18n } from '@kbn/i18n'; import { useParams } from 'react-router-dom'; +import { useSelectedLocation } from '../hooks/use_selected_location'; +import { getErrorDetailsUrl } from '../monitor_errors/errors_list'; import { ConfigKey, DataStream, EncryptedSyntheticsSavedMonitor, Ping, + SyntheticsJourneyApiResponse, } from '../../../../../../common/runtime_types'; import { formatTestRunAt } from '../../../utils/monitor_test_result/test_time_formats'; @@ -41,10 +44,8 @@ import { useSelectedMonitor } from '../hooks/use_selected_monitor'; import { useMonitorLatestPing } from '../hooks/use_monitor_latest_ping'; export const LastTestRun = () => { - const { euiTheme } = useEuiTheme(); const { latestPing, loading: pingsLoading } = useMonitorLatestPing(); const { lastRefresh } = useSyntheticsRefreshContext(); - const { monitor } = useSelectedMonitor(); const { data: stepsData, loading: stepsLoading } = useJourneySteps( latestPing?.monitor?.check_group, @@ -53,6 +54,35 @@ export const LastTestRun = () => { const loading = stepsLoading || pingsLoading; + return ( + + ); +}; + +export const LastTestRunComponent = ({ + latestPing, + loading, + stepsData, + stepsLoading, + isErrorDetails = false, +}: { + stepsLoading: boolean; + latestPing?: Ping; + loading: boolean; + stepsData: SyntheticsJourneyApiResponse; + isErrorDetails?: boolean; +}) => { + const { monitor } = useSelectedMonitor(); + const { euiTheme } = useEuiTheme(); + + const selectedLocation = useSelectedLocation(); + const { basePath } = useSyntheticsSettingsContext(); + return ( @@ -69,11 +99,24 @@ export const LastTestRun = () => { color="danger" iconType="alert" > - - {i18n.translate('xpack.synthetics.monitorDetails.summary.viewErrorDetails', { - defaultMessage: 'View error details', - })} - + {isErrorDetails ? ( + <> + ) : ( + + {i18n.translate('xpack.synthetics.monitorDetails.summary.viewErrorDetails', { + defaultMessage: 'View error details', + })} + + )} ) : null} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/step_duration_panel.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/step_duration_panel.tsx index b60be67942e4a..c84bfb4e0978b 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/step_duration_panel.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/step_duration_panel.tsx @@ -18,7 +18,13 @@ import { ClientPluginsStart } from '../../../../../plugin'; import { useSelectedLocation } from '../hooks/use_selected_location'; import { useAbsoluteDate } from '../../../hooks'; -export const StepDurationPanel = ({ legendPosition }: { legendPosition?: Position }) => { +export const StepDurationPanel = ({ + legendPosition, + doBreakdown = true, +}: { + legendPosition?: Position; + doBreakdown?: boolean; +}) => { const { observability } = useKibana().services; const time = useAbsoluteDate({ from: 'now-24h/h', to: 'now' }); @@ -40,12 +46,18 @@ export const StepDurationPanel = ({ legendPosition }: { legendPosition?: Positio return null; } + const label = !doBreakdown + ? MONITOR_DURATION + : isBrowser + ? DURATION_BY_STEP_LABEL + : DURATION_BY_LOCATION; + return ( -

{isBrowser ? DURATION_BY_STEP_LABEL : DURATION_BY_LOCATION}

+

{label}

@@ -60,19 +72,23 @@ export const StepDurationPanel = ({ legendPosition }: { legendPosition?: Positio customHeight={'300px'} reportType={ReportTypes.KPI} legendPosition={legendPosition} + legendIsVisible={doBreakdown} attributes={[ { time, - name: DURATION_BY_STEP_LABEL, + name: label, reportDefinitions: { 'monitor.id': [monitorId], 'observer.geo.name': [selectedLocation?.label], }, - selectedMetricField: isBrowser ? 'synthetics.step.duration.us' : 'monitor.duration.us', + selectedMetricField: + isBrowser && doBreakdown ? 'synthetics.step.duration.us' : 'monitor.duration.us', dataType: 'synthetics', - breakdown: isBrowser ? 'synthetics.step.name.keyword' : 'observer.geo.name', - operationType: 'last_value', + operationType: doBreakdown ? 'last_value' : 'average', seriesType: 'area_stacked', + ...(doBreakdown + ? { breakdown: isBrowser ? 'synthetics.step.name.keyword' : 'observer.geo.name' } + : {}), }, ]} /> @@ -88,6 +104,10 @@ const DURATION_BY_LOCATION = i18n.translate('xpack.synthetics.detailsPanel.durat defaultMessage: 'Duration by location', }); +const MONITOR_DURATION = i18n.translate('xpack.synthetics.detailsPanel.monitorDuration', { + defaultMessage: 'Monitor duration', +}); + const LAST_24H_LABEL = i18n.translate('xpack.synthetics.detailsPanel.last24Hours', { defaultMessage: 'Last 24 hours', }); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/test_runs_table.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/test_runs_table.tsx index 91bce9f49afa8..10afca302befe 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/test_runs_table.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/test_runs_table.tsx @@ -22,8 +22,9 @@ import { Criteria } from '@elastic/eui/src/components/basic_table/basic_table'; import { EuiTableSortingType } from '@elastic/eui/src/components/basic_table/table_types'; import { useHistory, useParams } from 'react-router-dom'; +import { useSelectedLocation } from '../hooks/use_selected_location'; import { MONITOR_TYPES } from '../../../../../../common/constants'; -import { TestDetailsLink } from '../../common/links/test_details_link'; +import { getTestRunDetailLink, TestDetailsLink } from '../../common/links/test_details_link'; import { ConfigKey, DataStream, Ping } from '../../../../../../common/runtime_types'; import { formatTestDuration } from '../../../utils/monitor_test_result/test_time_formats'; import { useSyntheticsSettingsContext } from '../../../contexts/synthetics_settings_context'; @@ -141,6 +142,8 @@ export const TestRunsTable = ({ paginable = true, from, to }: TestRunsTableProps }, ]; + const selectedLocation = useSelectedLocation(); + const getRowProps = (item: Ping) => { if (item.monitor.type !== MONITOR_TYPES.BROWSER) { return {}; @@ -156,7 +159,13 @@ export const TestRunsTable = ({ paginable = true, from, to }: TestRunsTableProps targetElem.tagName !== 'path' && !targetElem.parentElement?.classList.contains('euiLink') ) { - history.push(`/monitor/${monitorId}/test-run/${item.monitor.check_group}`); + history.push( + getTestRunDetailLink({ + monitorId, + checkGroup: item.monitor.check_group, + locationId: selectedLocation?.id, + }) + ); } }, }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_breadcrumbs.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_breadcrumbs.ts index 7454edfb32c1c..70065d99dadbf 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_breadcrumbs.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_breadcrumbs.ts @@ -17,7 +17,7 @@ export const useMonitorListBreadcrumbs = (extraCrumbs?: Array<{ text: string; hr useBreadcrumbs([ { text: MONITOR_MANAGEMENT_CRUMB, - href: `${appPath}/${MONITORS_ROUTE}`, + href: `${appPath}${MONITORS_ROUTE}`, }, ...(extraCrumbs ?? []), ]); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/data_retention.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/data_retention.tsx index a15ed8292508a..c636dbe565d37 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/data_retention.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/data_retention.tsx @@ -35,7 +35,7 @@ export const DataRetentionTab = () => { }), }, { - field: 'name', + field: 'policy.name', name: i18n.translate('xpack.synthetics.settingsRoute.table.policy', { defaultMessage: 'Policy', }), diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/hooks/use_get_ilm_policies.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/hooks/use_get_ilm_policies.ts index 216fb283b5883..bae80b567d339 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/hooks/use_get_ilm_policies.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/hooks/use_get_ilm_policies.ts @@ -16,23 +16,42 @@ const policyLabels = [ label: i18n.translate('xpack.synthetics.settingsRoute.allChecks', { defaultMessage: 'All Checks', }), + indexTemplate: 'synthetics', }, { name: 'synthetics-synthetics.browser-default_policy', label: i18n.translate('xpack.synthetics.settingsRoute.browserChecks', { defaultMessage: 'Browser Checks', }), + indexTemplate: 'synthetics-browser', }, { name: 'synthetics-synthetics.browser_network-default_policy', label: i18n.translate('xpack.synthetics.settingsRoute.browserNetworkRequests', { defaultMessage: 'Browser Network Requests', }), + indexTemplate: 'synthetics-browser.network', + }, + { + name: 'synthetics-synthetics.browser_screenshot-default_policy', + label: 'Browser Screenshots', + indexTemplate: 'synthetics-browser.screenshot', + }, + { + name: 'synthetics-synthetics.http-default_policy', + label: 'HTTP Pings', + indexTemplate: 'synthetics-http', + }, + { + name: 'synthetics-synthetics.icmp-default_policy', + label: 'ICMP Pings', + indexTemplate: 'synthetics-icmp', + }, + { + name: 'synthetics-synthetics.tcp-default_policy', + label: 'TCP Pings', + indexTemplate: 'synthetics-tcp', }, - { name: 'synthetics-synthetics.browser_screenshot-default_policy', label: 'Browser Screenshots' }, - { name: 'synthetics-synthetics.http-default_policy', label: 'HTTP Pings' }, - { name: 'synthetics-synthetics.icmp-default_policy', label: 'ICMP Pings' }, - { name: 'synthetics-synthetics.tcp-default_policy', label: 'TCP Pings' }, ]; export const useGetIlmPolicies = () => { @@ -44,11 +63,16 @@ export const useGetIlmPolicies = () => { return getIndicesData(); }, []); - const syntheticsILMPolicies = data?.filter(({ name }) => name.includes('synthetics')) ?? []; + const syntheticsILMPolicies = + data?.filter(({ indexTemplates }) => + indexTemplates?.some((indTemp) => indTemp.includes('synthetics')) + ) ?? []; return { - data: policyLabels.map(({ name, label }) => { - const policy = syntheticsILMPolicies.find((p) => p.name === name); + data: policyLabels.map(({ name, label, indexTemplate }) => { + const policy = syntheticsILMPolicies.find((p) => + p.indexTemplates?.some((indTemp) => indTemp.includes(indexTemplate)) + ); const policyIndices = sizeData?.data?.filter((d) => policy?.indices?.includes(d.index!)); let totalSize = diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/policy_link.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/policy_link.tsx index a1c7840d003b2..62833e1519fe9 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/policy_link.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/policy_link.tsx @@ -22,14 +22,18 @@ export const PolicyLink = ({ name }: { name: string }) => { const { data } = useFetcher(async () => { return ilmLocator?.getLocation({ page: 'policy_edit', policyName: name }); - }, []); + }, [name]); if (!data) { return ; } return ( - + {name} ); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/data_formatting.test.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/common/network_data/data_formatting.test.ts similarity index 88% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/data_formatting.test.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/common/network_data/data_formatting.test.ts index aea92647dfe60..814785ed6fe6b 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/data_formatting.test.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/common/network_data/data_formatting.test.ts @@ -12,18 +12,12 @@ import { getSeriesAndDomain, getSidebarItems, } from './data_formatting'; -import { - NetworkItems, - MimeType, - FriendlyFlyoutLabels, - FriendlyTimingLabels, - Timings, - Metadata, -} from './types'; -import { WaterfallDataEntry } from '../../waterfall/types'; -import { mockMoment } from '../../../../../../utils/formatting/test_helpers'; +import { MimeType, FriendlyFlyoutLabels, FriendlyTimingLabels, Timings, Metadata } from './types'; +import { WaterfallDataEntry } from './types'; +import { mockMoment } from '../../../../utils/formatting/test_helpers'; +import { NetworkEvent } from '../../../../../../../common/runtime_types'; -export const networkItems: NetworkItems = [ +export const networkItems: NetworkEvent[] = [ { timestamp: '2021-01-05T19:22:28.928Z', method: 'GET', @@ -83,7 +77,7 @@ export const networkItems: NetworkItems = [ }, ]; -export const networkItemsWithoutFullTimings: NetworkItems = [ +export const networkItemsWithoutFullTimings: NetworkEvent[] = [ networkItems[0], { timestamp: '2021-01-05T19:22:28.928Z', @@ -108,7 +102,7 @@ export const networkItemsWithoutFullTimings: NetworkItems = [ }, ]; -export const networkItemsWithoutAnyTimings: NetworkItems = [ +export const networkItemsWithoutAnyTimings: NetworkEvent[] = [ { timestamp: '2021-01-05T19:22:28.928Z', method: 'GET', @@ -132,7 +126,7 @@ export const networkItemsWithoutAnyTimings: NetworkItems = [ }, ]; -export const networkItemsWithoutTimingsObject: NetworkItems = [ +export const networkItemsWithoutTimingsObject: NetworkEvent[] = [ { timestamp: '2021-01-05T19:22:28.928Z', method: 'GET', @@ -144,7 +138,7 @@ export const networkItemsWithoutTimingsObject: NetworkItems = [ }, ]; -export const networkItemsWithUncommonMimeType: NetworkItems = [ +export const networkItemsWithUncommonMimeType: NetworkEvent[] = [ { timestamp: '2021-01-05T19:22:28.928Z', method: 'GET', @@ -168,6 +162,30 @@ export const networkItemsWithUncommonMimeType: NetworkItems = [ }, ]; +export const networkItemsWithUnknownMimeType: NetworkEvent[] = [ + { + timestamp: '2021-01-05T19:22:28.928Z', + method: 'GET', + url: 'https://unpkg.com/director@1.2.8/build/director.js', + status: 200, + mimeType: 'application/x-unknown', + requestSentTime: 18098833.537, + loadEndTime: 18098977.648000002, + timings: { + blocked: 84.54599999822676, + receive: 3.068000001803739, + queueing: 3.69700000010198, + proxy: -1, + total: 144.1110000014305, + wait: 52.56100000042352, + connect: -1, + send: 0.2390000008745119, + ssl: -1, + dns: -1, + }, + }, +]; + describe('getConnectingTime', () => { it('returns `connect` value if `ssl` is undefined', () => { expect(getConnectingTime(10)).toBe(10); @@ -193,20 +211,21 @@ describe('getConnectingTime', () => { describe('Palettes', () => { it('A colour palette comprising timing and mime type colours is correctly generated', () => { expect(colourPalette).toEqual({ - blocked: '#dcd4c4', - connect: '#da8b45', - dns: '#54b399', - font: '#aa6556', - html: '#f3b3a6', + blocked: '#b0c9e0', + connect: '#c8b8dc', + dns: '#aad9cc', + font: '#d36086', + html: '#6092c0', + image: '#ca8eae', media: '#d6bf57', - other: '#e7664c', - receive: '#54b399', - script: '#9170b8', - send: '#d36086', - ssl: '#edc5a2', - stylesheet: '#ca8eae', - wait: '#b0c9e0', - xhr: '#e7664c', + other: '#b9a888', + receive: '#ebdfab', + script: '#da8b45', + send: '#f3b3a6', + ssl: '#e5c7d7', + stylesheet: '#9170b8', + wait: '#e7664c', + xhr: '#54b399', }); }); }); @@ -222,12 +241,12 @@ describe('getSeriesAndDomain', () => { Array [ Object { "config": Object { - "colour": "#dcd4c4", + "colour": "#b0c9e0", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#dcd4c4", + "colour": "#b0c9e0", "value": "Queued / Blocked: 0.854ms", }, }, @@ -237,12 +256,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#54b399", + "colour": "#aad9cc", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#54b399", + "colour": "#aad9cc", "value": "DNS: 3.560ms", }, }, @@ -252,12 +271,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#da8b45", + "colour": "#c8b8dc", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#da8b45", + "colour": "#c8b8dc", "value": "Connecting: 25.721ms", }, }, @@ -267,12 +286,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#edc5a2", + "colour": "#e5c7d7", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#edc5a2", + "colour": "#e5c7d7", "value": "TLS: 55.387ms", }, }, @@ -282,12 +301,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#d36086", + "colour": "#f3b3a6", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#d36086", + "colour": "#f3b3a6", "value": "Sending request: 0.360ms", }, }, @@ -297,12 +316,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#b0c9e0", + "colour": "#e7664c", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#b0c9e0", + "colour": "#e7664c", "value": "Waiting (TTFB): 34.578ms", }, }, @@ -312,12 +331,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#ca8eae", + "colour": "#9170b8", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#ca8eae", + "colour": "#9170b8", "value": "Content downloading (CSS): 0.552ms", }, }, @@ -327,12 +346,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#dcd4c4", + "colour": "#b0c9e0", "id": 1, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#dcd4c4", + "colour": "#b0c9e0", "value": "Queued / Blocked: 84.546ms", }, }, @@ -342,12 +361,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#d36086", + "colour": "#f3b3a6", "id": 1, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#d36086", + "colour": "#f3b3a6", "value": "Sending request: 0.239ms", }, }, @@ -357,12 +376,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#b0c9e0", + "colour": "#e7664c", "id": 1, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#b0c9e0", + "colour": "#e7664c", "value": "Waiting (TTFB): 52.561ms", }, }, @@ -372,12 +391,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#9170b8", + "colour": "#da8b45", "id": 1, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#9170b8", + "colour": "#da8b45", "value": "Content downloading (JS): 3.068ms", }, }, @@ -395,12 +414,12 @@ describe('getSeriesAndDomain', () => { Array [ Object { "config": Object { - "colour": "#dcd4c4", + "colour": "#b0c9e0", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#dcd4c4", + "colour": "#b0c9e0", "value": "Queued / Blocked: 0.854ms", }, }, @@ -410,12 +429,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#54b399", + "colour": "#aad9cc", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#54b399", + "colour": "#aad9cc", "value": "DNS: 3.560ms", }, }, @@ -425,12 +444,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#da8b45", + "colour": "#c8b8dc", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#da8b45", + "colour": "#c8b8dc", "value": "Connecting: 25.721ms", }, }, @@ -440,12 +459,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#edc5a2", + "colour": "#e5c7d7", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#edc5a2", + "colour": "#e5c7d7", "value": "TLS: 55.387ms", }, }, @@ -455,12 +474,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#d36086", + "colour": "#f3b3a6", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#d36086", + "colour": "#f3b3a6", "value": "Sending request: 0.360ms", }, }, @@ -470,12 +489,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#b0c9e0", + "colour": "#e7664c", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#b0c9e0", + "colour": "#e7664c", "value": "Waiting (TTFB): 34.578ms", }, }, @@ -485,12 +504,12 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#ca8eae", + "colour": "#9170b8", "id": 0, "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#ca8eae", + "colour": "#9170b8", "value": "Content downloading (CSS): 0.552ms", }, }, @@ -500,11 +519,11 @@ describe('getSeriesAndDomain', () => { }, Object { "config": Object { - "colour": "#9170b8", + "colour": "#da8b45", "isHighlighted": true, "showTooltip": true, "tooltipProps": Object { - "colour": "#9170b8", + "colour": "#da8b45", "value": "Content downloading (JS): 2.793ms", }, }, @@ -634,20 +653,20 @@ describe('getSeriesAndDomain', () => { }); it('handles formatting when mime type is not mapped to a specific mime type bucket', () => { - const { series } = getSeriesAndDomain(networkItemsWithUncommonMimeType); + const { series } = getSeriesAndDomain(networkItemsWithUnknownMimeType); /* verify that raw mime type appears in the tooltip config and that * the colour is mapped to mime type other */ - const contentDownloadedingConfigItem = series.find((item: WaterfallDataEntry) => { + const contentDownloadingConfigItem = series.find((item: WaterfallDataEntry) => { const { tooltipProps } = item.config; if (tooltipProps && typeof tooltipProps.value === 'string') { return ( - tooltipProps.value.includes('application/x-javascript') && + tooltipProps.value.includes('application/x-unknown') && tooltipProps.colour === colourPalette[MimeType.Other] ); } return false; }); - expect(contentDownloadedingConfigItem).toBeDefined(); + expect(contentDownloadingConfigItem).toBeDefined(); }); it.each([ diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/data_formatting.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/common/network_data/data_formatting.ts similarity index 81% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/data_formatting.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/common/network_data/data_formatting.ts index 8b7a29af3030e..c35152a563833 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/data_formatting.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/common/network_data/data_formatting.ts @@ -8,27 +8,26 @@ import { euiPaletteColorBlind } from '@elastic/eui'; import moment from 'moment'; -import { NetworkEvent } from '../../../../../../../../../common/runtime_types'; +import { NetworkEvent } from '../../../../../../../common/runtime_types'; +import { WaterfallData, WaterfallMetadata } from './types'; import { - NetworkItems, - NetworkItem, FriendlyFlyoutLabels, - FriendlyTimingLabels, FriendlyMimetypeLabels, + FriendlyTimingLabels, + ItemMatcher, + LegendItem, + Metadata, MimeType, MimeTypesMap, - Timings, - Metadata, + SidebarItem, TIMING_ORDER, - SidebarItems, - LegendItems, + Timings, } from './types'; -import { WaterfallData, WaterfallMetadata } from '../../waterfall'; -export const extractItems = (data: NetworkEvent[]): NetworkItems => { +export const extractItems = (data: NetworkEvent[]): NetworkEvent[] => { // NOTE: This happens client side as the "payload" property is mapped // in such a way it can't be queried (or sorted on) via ES. - return data.sort((a: NetworkItem, b: NetworkItem) => { + return data.sort((a: NetworkEvent, b: NetworkEvent) => { return a.requestSentTime - b.requestSentTime; }); }; @@ -59,19 +58,15 @@ const getFriendlyTooltipValue = ({ return `${label}: ${formatValueForDisplay(value)}ms`; }; export const isHighlightedItem = ( - item: NetworkItem, - query?: string, - activeFilters: string[] = [] + item: NetworkEvent, + queryMatcher?: ItemMatcher, + filterMatcher?: ItemMatcher ) => { - if (!query && activeFilters?.length === 0) { + if (!queryMatcher && !filterMatcher) { return true; } - const matchQuery = query ? item.url?.includes(query) : true; - const matchFilters = - activeFilters.length > 0 ? activeFilters.includes(MimeTypesMap[item.mimeType!]) : true; - - return !!(matchQuery && matchFilters); + return (queryMatcher?.(item) ?? true) && (filterMatcher?.(item) ?? true); }; const getFriendlyMetadataValue = ({ value, postFix }: { value?: number; postFix?: string }) => { @@ -97,13 +92,45 @@ export const getConnectingTime = (connect?: number, ssl?: number) => { } }; +export const getQueryMatcher = (query?: string): ItemMatcher => { + if (!query) { + return (item: NetworkEvent) => true; + } + + const regExp = new RegExp(query, 'i'); + + return (item: NetworkEvent) => { + return (item.url?.search(regExp) ?? -1) > -1; + }; +}; + +export const getFilterMatcher = (filters: string[] | undefined): ItemMatcher => { + if (!filters?.length) { + return (item: NetworkEvent) => true; + } + + const filtersByMimeType = filters.reduce((acc, cur) => { + acc.set(cur as MimeType, true); + + return acc; + }, new Map()); + + return (item: NetworkEvent) => { + const resolvedMimeType = item.mimeType + ? MimeTypesMap[item.mimeType] ?? MimeType.Other + : MimeType.Other; + + return filtersByMimeType.has(resolvedMimeType); + }; +}; + export const getSeriesAndDomain = ( - items: NetworkItems, + items: NetworkEvent[], onlyHighlighted = false, query?: string, activeFilters?: string[] ) => { - const getValueForOffset = (item: NetworkItem) => { + const getValueForOffset = (item: NetworkEvent) => { return item.requestSentTime; }; // The earliest point in time a request is sent or started. This will become our notion of "0". @@ -124,12 +151,14 @@ export const getSeriesAndDomain = ( const metadata: WaterfallMetadata = []; let totalHighlightedRequests = 0; + const queryMatcher = getQueryMatcher(query); + const filterMatcher = getFilterMatcher(activeFilters); items.forEach((item, index) => { const mimeTypeColour = getColourForMimeType(item.mimeType); const offsetValue = getValueForOffset(item); let currentOffset = offsetValue - zeroOffset; metadata.push(formatMetadata({ item, index, requestStart: currentOffset })); - const isHighlighted = isHighlightedItem(item, query, activeFilters); + const isHighlighted = isHighlightedItem(item, queryMatcher, filterMatcher); if (isHighlighted) { totalHighlightedRequests++; } @@ -234,7 +263,7 @@ const formatMetadata = ({ index, requestStart, }: { - item: NetworkItem; + item: NetworkEvent; index: number; requestStart: number; }) => { @@ -331,13 +360,15 @@ const formatMetadata = ({ }; export const getSidebarItems = ( - items: NetworkItems, + items: NetworkEvent[], onlyHighlighted: boolean, query: string, activeFilters: string[] -): SidebarItems => { +): SidebarItem[] => { + const queryMatcher = getQueryMatcher(query); + const filterMatcher = getFilterMatcher(activeFilters); const sideBarItems = items.map((item, index) => { - const isHighlighted = isHighlightedItem(item, query, activeFilters); + const isHighlighted = isHighlightedItem(item, queryMatcher, filterMatcher); const offsetIndex = index + 1; const { url, status, method } = item; return { url, status, method, isHighlighted, offsetIndex, index }; @@ -348,8 +379,8 @@ export const getSidebarItems = ( return sideBarItems; }; -export const getLegendItems = (): LegendItems => { - let timingItems: LegendItems = []; +export const getLegendItems = (): LegendItem[] => { + let timingItems: LegendItem[] = []; Object.values(Timings).forEach((timing) => { // The "receive" timing is mapped to a mime type colour, so we don't need to show this in the legend if (timing === Timings.Receive) { @@ -357,15 +388,15 @@ export const getLegendItems = (): LegendItems => { } timingItems = [ ...timingItems, - { name: FriendlyTimingLabels[timing], colour: TIMING_PALETTE[timing] }, + { name: FriendlyTimingLabels[timing], color: TIMING_PALETTE[timing] }, ]; }); - let mimeTypeItems: LegendItems = []; + let mimeTypeItems: LegendItem[] = []; Object.values(MimeType).forEach((mimeType) => { mimeTypeItems = [ ...mimeTypeItems, - { name: FriendlyMimetypeLabels[mimeType], colour: MIME_TYPE_PALETTE[mimeType] }, + { name: FriendlyMimetypeLabels[mimeType], color: MIME_TYPE_PALETTE[mimeType] }, ]; }); @@ -383,25 +414,25 @@ const buildTimingPalette = (): TimingColourPalette => { const palette = Object.values(Timings).reduce>((acc, value) => { switch (value) { case Timings.Blocked: - acc[value] = SAFE_PALETTE[16]; + acc[value] = SAFE_PALETTE[11]; break; case Timings.Dns: - acc[value] = SAFE_PALETTE[0]; + acc[value] = SAFE_PALETTE[10]; break; case Timings.Connect: - acc[value] = SAFE_PALETTE[7]; + acc[value] = SAFE_PALETTE[13]; break; case Timings.Ssl: - acc[value] = SAFE_PALETTE[17]; + acc[value] = SAFE_PALETTE[14]; break; case Timings.Send: - acc[value] = SAFE_PALETTE[2]; + acc[value] = SAFE_PALETTE[19]; break; case Timings.Wait: - acc[value] = SAFE_PALETTE[11]; + acc[value] = SAFE_PALETTE[9]; break; case Timings.Receive: - acc[value] = SAFE_PALETTE[0]; + acc[value] = SAFE_PALETTE[15]; break; } return acc; @@ -421,23 +452,28 @@ const buildMimeTypePalette = (): MimeTypeColourPalette => { const palette = Object.values(MimeType).reduce>((acc, value) => { switch (value) { case MimeType.Html: - acc[value] = SAFE_PALETTE[19]; + acc[value] = SAFE_PALETTE[1]; break; case MimeType.Script: - acc[value] = SAFE_PALETTE[3]; + acc[value] = SAFE_PALETTE[7]; break; case MimeType.Stylesheet: + acc[value] = SAFE_PALETTE[3]; + break; + case MimeType.Image: acc[value] = SAFE_PALETTE[4]; break; case MimeType.Media: acc[value] = SAFE_PALETTE[5]; break; case MimeType.Font: - acc[value] = SAFE_PALETTE[8]; + acc[value] = SAFE_PALETTE[2]; break; case MimeType.XHR: + acc[value] = SAFE_PALETTE[0]; + break; case MimeType.Other: - acc[value] = SAFE_PALETTE[9]; + acc[value] = SAFE_PALETTE[6]; break; } return acc; @@ -454,3 +490,10 @@ export const colourPalette: ColourPalette = { ...TIMING_PALETTE, ...MIME_TYPE_PA export const formatTooltipHeading = (index: number, fullText: string): string => isNaN(index) ? fullText : `${index}. ${fullText}`; + +export const formatMillisecond = (ms: number) => { + if (ms < 1000) { + return `${ms.toFixed(0)} ms`; + } + return `${(ms / 1000).toFixed(1)} s`; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/types.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/common/network_data/types.ts similarity index 73% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/types.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/common/network_data/types.ts index ad4c635f31d3b..78076be872dbb 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/types.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/common/network_data/types.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { NetworkEvent } from '../../../../../../../../../common/runtime_types'; +import { NetworkEvent } from '../../../../../../../common/runtime_types'; export enum Timings { Blocked = 'blocked', @@ -152,6 +152,7 @@ export enum MimeType { Script = 'script', Stylesheet = 'stylesheet', Media = 'media', + Image = 'image', Font = 'font', XHR = 'xhr', Other = 'other', @@ -176,6 +177,12 @@ export const FriendlyMimetypeLabels = { defaultMessage: 'CSS', } ), + [MimeType.Image]: i18n.translate( + 'xpack.synthetics.synthetics.waterfallChart.labels.mimeTypes.image', + { + defaultMessage: 'Image', + } + ), [MimeType.Media]: i18n.translate( 'xpack.synthetics.synthetics.waterfallChart.labels.mimeTypes.media', { @@ -207,18 +214,21 @@ export const FriendlyMimetypeLabels = { export const MimeTypesMap: Record = { 'text/html': MimeType.Html, 'application/javascript': MimeType.Script, + 'application/x-javascript': MimeType.Script, 'text/javascript': MimeType.Script, 'text/css': MimeType.Stylesheet, + // Images - 'image/apng': MimeType.Media, - 'image/bmp': MimeType.Media, - 'image/gif': MimeType.Media, - 'image/x-icon': MimeType.Media, - 'image/jpeg': MimeType.Media, - 'image/png': MimeType.Media, - 'image/svg+xml': MimeType.Media, - 'image/tiff': MimeType.Media, - 'image/webp': MimeType.Media, + 'image/apng': MimeType.Image, + 'image/bmp': MimeType.Image, + 'image/gif': MimeType.Image, + 'image/x-icon': MimeType.Image, + 'image/jpeg': MimeType.Image, + 'image/png': MimeType.Image, + 'image/svg+xml': MimeType.Image, + 'image/tiff': MimeType.Image, + 'image/webp': MimeType.Image, + // Common audio / video formats 'audio/wave': MimeType.Media, 'audio/wav': MimeType.Media, @@ -230,6 +240,7 @@ export const MimeTypesMap: Record = { 'audio/ogg': MimeType.Media, 'video/ogg': MimeType.Media, 'application/ogg': MimeType.Media, + // Fonts 'font/otf': MimeType.Font, 'font/ttf': MimeType.Font, @@ -245,18 +256,85 @@ export const MimeTypesMap: Record = { 'application/json': MimeType.XHR, }; -export type NetworkItem = NetworkEvent; -export type NetworkItems = NetworkItem[]; - -export type SidebarItem = Pick & { +export type SidebarItem = Pick & { isHighlighted: boolean; index: number; offsetIndex: number; }; -export type SidebarItems = SidebarItem[]; export interface LegendItem { name: string; - colour: string; + color: string; +} + +export type ItemMatcher = (item: NetworkEvent) => boolean; + +export const MIME_FILTERS = [ + { + label: FriendlyMimetypeLabels[MimeType.Html], + mimeType: MimeType.Html, + }, + { + label: FriendlyMimetypeLabels[MimeType.Stylesheet], + mimeType: MimeType.Stylesheet, + }, + { + label: FriendlyMimetypeLabels[MimeType.Font], + mimeType: MimeType.Font, + }, + { + label: FriendlyMimetypeLabels[MimeType.Script], + mimeType: MimeType.Script, + }, + { + label: FriendlyMimetypeLabels[MimeType.Image], + mimeType: MimeType.Image, + }, + { + label: FriendlyMimetypeLabels[MimeType.Media], + mimeType: MimeType.Media, + }, + { + label: FriendlyMimetypeLabels[MimeType.XHR], + mimeType: MimeType.XHR, + }, + { + label: FriendlyMimetypeLabels[MimeType.Other], + mimeType: MimeType.Other, + }, +]; + +interface PlotProperties { + x: number; + y: number; + y0: number; } -export type LegendItems = LegendItem[]; + +export interface WaterfallDataSeriesConfigProperties { + tooltipProps?: Record; + showTooltip: boolean; +} + +export interface WaterfallMetadataItem { + name: string; + value?: string; +} + +export interface WaterfallMetadataEntry { + x: number; + url: string; + requestHeaders?: WaterfallMetadataItem[]; + responseHeaders?: WaterfallMetadataItem[]; + certificates?: WaterfallMetadataItem[]; + details: WaterfallMetadataItem[]; +} + +export type WaterfallDataEntry = PlotProperties & { + config: WaterfallDataSeriesConfigProperties & Record; +}; + +export type WaterfallMetadata = WaterfallMetadataEntry[]; + +export type WaterfallData = WaterfallDataEntry[]; + +export type RenderItem = (item: I, index: number) => JSX.Element; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_filter.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_filter.test.tsx deleted file mode 100644 index a564d751b3647..0000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_filter.test.tsx +++ /dev/null @@ -1,151 +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, { useState } from 'react'; -import { act, fireEvent } from '@testing-library/react'; -import 'jest-canvas-mock'; -import { MIME_FILTERS, WaterfallFilter } from './waterfall_filter'; -import { - FILTER_REQUESTS_LABEL, - FILTER_COLLAPSE_REQUESTS_LABEL, - FILTER_POPOVER_OPEN_LABEL, -} from '../../waterfall/components/translations'; -import { render } from '../../../../../../utils/testing'; - -describe('waterfall filter', () => { - jest.useFakeTimers(); - - it('renders correctly', () => { - const { getByLabelText, getByTitle } = render( - - ); - - fireEvent.click(getByLabelText(FILTER_POPOVER_OPEN_LABEL)); - - MIME_FILTERS.forEach((filter) => { - expect(getByTitle(filter.label)); - }); - }); - - it('filter icon changes color on active/inactive filters', () => { - const Component = () => { - const [activeFilters, setActiveFilters] = useState([]); - - return ( - - ); - }; - const { getByLabelText, getByTitle } = render(); - - fireEvent.click(getByLabelText(FILTER_POPOVER_OPEN_LABEL)); - - fireEvent.click(getByTitle('XHR')); - - expect(getByLabelText(FILTER_POPOVER_OPEN_LABEL).className).toMatchInlineSnapshot( - `"euiButtonIcon euiButtonIcon--xSmall css-1q7ycil-euiButtonIcon-empty-primary-hoverStyles"` - ); - - // toggle it back to inactive - fireEvent.click(getByTitle('XHR')); - - expect(getByLabelText(FILTER_POPOVER_OPEN_LABEL).className).toMatchInlineSnapshot( - `"euiButtonIcon euiButtonIcon--xSmall css-o2mzw-euiButtonIcon-empty-text-hoverStyles"` - ); - }); - - it('search input is working properly', () => { - const setQuery = jest.fn(); - - const Component = () => { - return ( - - ); - }; - const { getByLabelText } = render(); - - const testText = 'js'; - - fireEvent.change(getByLabelText(FILTER_REQUESTS_LABEL), { target: { value: testText } }); - - // inout has debounce effect so hence the timer - act(() => { - jest.advanceTimersByTime(300); - }); - - expect(setQuery).toHaveBeenCalledWith(testText); - }); - - it('resets checkbox when filters are removed', () => { - const Component = () => { - const [onlyHighlighted, setOnlyHighlighted] = useState(false); - const [query, setQuery] = useState(''); - const [activeFilters, setActiveFilters] = useState([]); - return ( - - ); - }; - const { getByLabelText, getByTitle } = render(); - const input = getByLabelText(FILTER_REQUESTS_LABEL); - // apply filters - const testText = 'js'; - fireEvent.change(input, { target: { value: testText } }); - fireEvent.click(getByLabelText(FILTER_POPOVER_OPEN_LABEL)); - const filterGroupButton = getByTitle('XHR'); - fireEvent.click(filterGroupButton); - - // input has debounce effect so hence the timer - act(() => { - jest.advanceTimersByTime(300); - }); - - const collapseCheckbox = getByLabelText(FILTER_COLLAPSE_REQUESTS_LABEL) as HTMLInputElement; - expect(collapseCheckbox).not.toBeDisabled(); - fireEvent.click(collapseCheckbox); - expect(collapseCheckbox).toBeChecked(); - - // remove filters - fireEvent.change(input, { target: { value: '' } }); - fireEvent.click(filterGroupButton); - - // input has debounce effect so hence the timer - act(() => { - jest.advanceTimersByTime(300); - }); - - // expect the checkbox to reset to disabled and unchecked - expect(collapseCheckbox).not.toBeChecked(); - expect(collapseCheckbox).toBeDisabled(); - }); -}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_filter.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_filter.tsx deleted file mode 100644 index 5531dafd4542b..0000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_filter.tsx +++ /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 React, { Dispatch, SetStateAction, useEffect, useState } from 'react'; -import { - EuiButtonIcon, - EuiCheckbox, - EuiFieldSearch, - EuiFilterButton, - EuiFilterGroup, - EuiFlexGroup, - EuiFlexItem, - EuiPopover, - EuiSpacer, -} from '@elastic/eui'; -import useDebounce from 'react-use/lib/useDebounce'; -import { METRIC_TYPE, useUiTracker } from '@kbn/observability-plugin/public'; -import { - FILTER_REQUESTS_LABEL, - FILTER_SCREENREADER_LABEL, - FILTER_REMOVE_SCREENREADER_LABEL, - FILTER_POPOVER_OPEN_LABEL, - FILTER_COLLAPSE_REQUESTS_LABEL, -} from '../../waterfall/components/translations'; -import { MimeType, FriendlyMimetypeLabels } from './types'; - -interface Props { - query: string; - activeFilters: string[]; - setActiveFilters: Dispatch>; - setQuery: (val: string) => void; - onlyHighlighted: boolean; - setOnlyHighlighted: (val: boolean) => void; -} - -export const MIME_FILTERS = [ - { - label: FriendlyMimetypeLabels[MimeType.XHR], - mimeType: MimeType.XHR, - }, - { - label: FriendlyMimetypeLabels[MimeType.Html], - mimeType: MimeType.Html, - }, - { - label: FriendlyMimetypeLabels[MimeType.Script], - mimeType: MimeType.Script, - }, - { - label: FriendlyMimetypeLabels[MimeType.Stylesheet], - mimeType: MimeType.Stylesheet, - }, - { - label: FriendlyMimetypeLabels[MimeType.Font], - mimeType: MimeType.Font, - }, - { - label: FriendlyMimetypeLabels[MimeType.Media], - mimeType: MimeType.Media, - }, - { - label: FriendlyMimetypeLabels[MimeType.Other], - mimeType: MimeType.Other, - }, -]; - -export const WaterfallFilter = ({ - query, - setQuery, - activeFilters, - setActiveFilters, - onlyHighlighted, - setOnlyHighlighted, -}: Props) => { - const [value, setValue] = useState(query); - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - - const trackMetric = useUiTracker({ app: 'uptime' }); - - const toggleFilters = (val: string) => { - setActiveFilters((prevState) => - prevState.includes(val) ? prevState.filter((filter) => filter !== val) : [...prevState, val] - ); - }; - useDebounce( - () => { - setQuery(value); - }, - 250, - [value] - ); - - /* reset checkbox when there is no query or active filters - * this prevents the checkbox from being checked in a disabled state */ - useEffect(() => { - if (!(query || activeFilters.length > 0)) { - setOnlyHighlighted(false); - } - }, [activeFilters.length, setOnlyHighlighted, query]); - - // indicates use of the query input box - useEffect(() => { - if (query) { - trackMetric({ metric: 'waterfall_filter_input_changed', metricType: METRIC_TYPE.CLICK }); - } - }, [query, trackMetric]); - - // indicates the collapse to show only highlighted checkbox has been clicked - useEffect(() => { - if (onlyHighlighted) { - trackMetric({ - metric: 'waterfall_filter_collapse_checked', - metricType: METRIC_TYPE.CLICK, - }); - } - }, [onlyHighlighted, trackMetric]); - - // indicates filters have been applied or changed - useEffect(() => { - if (activeFilters.length > 0) { - trackMetric({ - metric: `waterfall_filters_applied_changed`, - metricType: METRIC_TYPE.CLICK, - }); - } - }, [activeFilters, trackMetric]); - - return ( - - - { - setValue(evt.target.value); - }} - value={value} - /> - - - setIsPopoverOpen((prevState) => !prevState)} - color={activeFilters.length > 0 ? 'primary' : 'text'} - isSelected={activeFilters.length > 0} - /> - } - isOpen={isPopoverOpen} - closePopover={() => setIsPopoverOpen(false)} - anchorPosition="rightCenter" - > - - {MIME_FILTERS.map(({ label, mimeType }) => ( - toggleFilters(mimeType)} - key={label} - withNext={true} - aria-label={`${ - activeFilters.includes(mimeType) - ? FILTER_REMOVE_SCREENREADER_LABEL - : FILTER_SCREENREADER_LABEL - } ${label}`} - > - {label} - - ))} - - - 0)} - id="onlyHighlighted" - label={FILTER_COLLAPSE_REQUESTS_LABEL} - checked={onlyHighlighted} - onChange={(e) => { - setOnlyHighlighted(e.target.checked); - }} - /> - - - - ); -}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/legend.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/legend.tsx deleted file mode 100644 index 3fdfe2c65f0ad..0000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/legend.tsx +++ /dev/null @@ -1,33 +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 { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { euiStyled } from '@kbn/kibana-react-plugin/common'; -import { IWaterfallContext } from '../context/waterfall_chart'; -import { WaterfallChartProps } from './waterfall_chart'; - -interface LegendProps { - items: Required['legendItems']; - render: Required['renderLegendItem']; -} - -const StyledFlexItem = euiStyled(EuiFlexItem)` - margin-right: ${(props) => props.theme.eui.euiSizeM}; - max-width: 7%; - min-width: 160px; -`; - -export const Legend: React.FC = ({ items, render }) => { - return ( - - {items.map((item, index) => ( - {render(item, index)} - ))} - - ); -}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/network_requests_total.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/network_requests_total.test.tsx deleted file mode 100644 index e332be22d3da1..0000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/network_requests_total.test.tsx +++ /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 React from 'react'; -import { NetworkRequestsTotal } from './network_requests_total'; -import { render } from '../../../../../../utils/testing'; - -describe('NetworkRequestsTotal', () => { - it('message in case total is greater than fetched', () => { - const { getByText } = render( - - ); - - expect(getByText('First 1000/1100 network requests')).toBeInTheDocument(); - expect(getByText('Info')).toBeInTheDocument(); - }); - - it('message in case total is equal to fetched requests', () => { - const { getByText } = render( - - ); - - expect(getByText('500 network requests')).toBeInTheDocument(); - }); - - it('does not show highlighted item message when showHighlightedNetworkEvents is false', () => { - const { queryByText } = render( - - ); - - expect(queryByText(/match the filter/)).not.toBeInTheDocument(); - }); - - it('does not show highlighted item message when highlightedNetworkEvents is less than 0', () => { - const { queryByText } = render( - - ); - - expect(queryByText(/match the filter/)).not.toBeInTheDocument(); - }); - - it('show highlighted item message when highlightedNetworkEvents is greater than 0 and showHighlightedNetworkEvents is true', () => { - const { getByText } = render( - - ); - - expect(getByText(/\(20 match the filter\)/)).toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/network_requests_total.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/network_requests_total.tsx deleted file mode 100644 index 4fac0b3cd00d2..0000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/network_requests_total.tsx +++ /dev/null @@ -1,69 +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 { FormattedMessage } from '@kbn/i18n-react'; -import { i18n } from '@kbn/i18n'; -import { EuiIconTip } from '@elastic/eui'; -import { NetworkRequestsTotalStyle } from './styles'; - -interface Props { - totalNetworkRequests: number; - fetchedNetworkRequests: number; - highlightedNetworkRequests: number; - showHighlightedNetworkRequests?: boolean; -} - -export const NetworkRequestsTotal = ({ - totalNetworkRequests, - fetchedNetworkRequests, - highlightedNetworkRequests, - showHighlightedNetworkRequests, -}: Props) => { - return ( - - - fetchedNetworkRequests ? ( - - ) : ( - totalNetworkRequests - ), - }} - />{' '} - {showHighlightedNetworkRequests && highlightedNetworkRequests >= 0 && ( - - )} - - {totalNetworkRequests > fetchedNetworkRequests && ( - - )} - - ); -}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/styles.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/styles.ts deleted file mode 100644 index a48ce1f7c09b5..0000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/styles.ts +++ /dev/null @@ -1,181 +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 { FunctionComponent } from 'react'; -import { StyledComponent } from 'styled-components'; -import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiText, EuiPanelProps } from '@elastic/eui'; -import { rgba } from 'polished'; -import { euiStyled, EuiTheme } from '@kbn/kibana-react-plugin/common'; -import { FIXED_AXIS_HEIGHT } from './constants'; - -interface WaterfallChartOuterContainerProps { - height?: string; -} - -const StyledScrollDiv = euiStyled.div` - &::-webkit-scrollbar { - height: ${({ theme }) => theme.eui.euiScrollBar}; - width: ${({ theme }) => theme.eui.euiScrollBar}; - } - &::-webkit-scrollbar-thumb { - background-clip: content-box; - background-color: ${({ theme }) => rgba(theme.eui.euiColorDarkShade, 0.5)}; - border: ${({ theme }) => theme.eui.euiScrollBarCorner} solid transparent; - } - &::-webkit-scrollbar-corner, - &::-webkit-scrollbar-track { - background-color: transparent; - } -`; - -export const WaterfallChartOuterContainer = euiStyled( - StyledScrollDiv -)` - height: ${(props) => (props.height ? `${props.height}` : 'auto')}; - overflow-y: ${(props) => (props.height ? 'scroll' : 'visible')}; - overflow-x: hidden; -`; - -export const WaterfallChartFixedTopContainer = euiStyled(StyledScrollDiv)` - position: sticky; - top: 0; - z-index: ${(props) => props.theme.eui.euiZLevel4}; - overflow-y: scroll; - overflow-x: hidden; -`; - -export const WaterfallChartAxisOnlyContainer = euiStyled(EuiFlexItem)` - margin-left: -16px; -`; - -export const WaterfallChartTopContainer = euiStyled(EuiFlexGroup)` -`; - -export const WaterfallChartFixedTopContainerSidebarCover: StyledComponent< - FunctionComponent, - EuiTheme -> = euiStyled(EuiPanel)` - height: 100%; - border-radius: 0 !important; - border: none; -`; // NOTE: border-radius !important is here as the "border" prop isn't working - -export const WaterfallChartFilterContainer = euiStyled.div` - && { - padding: 16px; - z-index: ${(props) => props.theme.eui.euiZLevel5}; - border-bottom: 0.3px solid ${(props) => props.theme.eui.euiColorLightShade}; - } -`; // NOTE: border-radius !important is here as the "border" prop isn't working - -export const WaterfallChartFixedAxisContainer = euiStyled.div` - z-index: ${(props) => props.theme.eui.euiZLevel4}; - height: 100%; - &&& { - .echAnnotation__icon { - top: 8px; - } - } -`; - -interface WaterfallChartSidebarContainer { - height: number; -} - -export const WaterfallChartSidebarWrapper = euiStyled(EuiFlexItem)` - z-index: ${(props) => props.theme.eui.euiZLevel5}; - min-width: 0; -`; // NOTE: min-width: 0 ensures flexbox and no-wrap children can co-exist - -export const WaterfallChartSidebarContainer = euiStyled.div` - height: ${(props) => `${props.height}px`}; - overflow-y: hidden; - overflow-x: hidden; -`; - -export const WaterfallChartSidebarContainerInnerPanel: StyledComponent< - FunctionComponent, - EuiTheme -> = euiStyled(EuiPanel)` - border: 0; - height: 100%; -`; - -export const WaterfallChartSidebarContainerFlexGroup = euiStyled(EuiFlexGroup)` - height: 100%; -`; - -// Ensures flex items honour no-wrap of children, rather than trying to extend to the full width of children. -export const WaterfallChartSidebarFlexItem = euiStyled(EuiFlexItem)` - min-width: 0; - padding-right: ${(props) => props.theme.eui.euiSizeS}; - justify-content: space-around; -`; - -export const SideBarItemHighlighter = euiStyled(EuiFlexItem)<{ isHighlighted: boolean }>` - opacity: ${(props) => (props.isHighlighted ? 1 : 0.4)}; - height: 100%; - .euiButtonEmpty { - height: ${FIXED_AXIS_HEIGHT}px; - font-size:${({ theme }) => theme.eui.euiFontSizeM}; - } -`; - -interface WaterfallChartChartContainer { - height: number; - chartIndex: number; -} - -export const WaterfallChartChartContainer = euiStyled.div` - width: 100%; - height: ${(props) => `${props.height + FIXED_AXIS_HEIGHT + 4}px`}; - margin-top: -${FIXED_AXIS_HEIGHT + 4}px; - z-index: ${(props) => Math.round(props.theme.eui.euiZLevel3 / (props.chartIndex + 1))}; - background-color: ${(props) => props.theme.eui.euiColorEmptyShade}; - - &&& { - .echCanvasRenderer { - height: calc(100% + 0px) !important; - } - } -`; - -export const WaterfallChartLegendContainer = euiStyled.div` - position: sticky; - bottom: 0; - z-index: ${(props) => props.theme.eui.euiZLevel5}; - background-color: ${(props) => props.theme.eui.euiColorLightestShade}; - padding: ${(props) => props.theme.eui.euiSizeXS}; - font-size: ${(props) => props.theme.eui.euiFontSizeXS}; - box-shadow: 0px -1px 4px 0px ${(props) => props.theme.eui.euiColorLightShade}; -`; // NOTE: EuiShadowColor is a little too dark to work with the background-color - -export const WaterfallTooltipResponsiveMaxWidth = euiStyled.div` - margin-top: 16px; - max-width: 90vw; -`; - -export const WaterfallChartTooltip = euiStyled(WaterfallTooltipResponsiveMaxWidth)` - background-color: ${(props) => props.theme.eui.euiColorDarkestShade}; - border-radius: ${(props) => props.theme.eui.euiBorderRadius}; - color: ${(props) => props.theme.eui.euiColorLightestShade}; - padding: ${(props) => props.theme.eui.euiSizeS}; - .euiToolTip__arrow { - background-color: ${(props) => props.theme.eui.euiColorDarkestShade}; - } -`; - -export const NetworkRequestsTotalStyle = euiStyled(EuiText)` - line-height: 28px; - padding: 0 ${(props) => props.theme.eui.euiSizeM}; - border-bottom: 0.3px solid ${(props) => props.theme.eui.euiColorLightShade}; - z-index: ${(props) => props.theme.eui.euiZLevel5}; -`; - -export const RelativeContainer = euiStyled.div` - position: relative; -`; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall.test.tsx deleted file mode 100644 index c1937764214e4..0000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall.test.tsx +++ /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 React from 'react'; -import { WaterfallChart } from './waterfall_chart'; -import { renderLegendItem } from '../../step_detail/waterfall/waterfall_chart_wrapper'; - -import 'jest-canvas-mock'; -import { waitFor } from '@testing-library/dom'; -import { render } from '../../../../../../utils/testing'; - -describe('waterfall', () => { - it('sets the correct height in case of full height', () => { - const Component = () => { - return ( -
- `${Number(d).toFixed(0)} ms`} - domain={{ - max: 3371, - min: 0, - }} - barStyleAccessor={(datum) => { - return datum.datum.config.colour; - }} - renderSidebarItem={undefined} - renderLegendItem={renderLegendItem} - fullHeight={true} - /> -
- ); - }; - - const { getByTestId } = render(); - - const chartWrapper = getByTestId('waterfallOuterContainer'); - - waitFor(() => { - expect(chartWrapper).toHaveStyleRule('height', 'calc(100vh - 62px)'); - }); - }); -}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_chart.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_chart.tsx deleted file mode 100644 index 8e69e57616bff..0000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_chart.tsx +++ /dev/null @@ -1,156 +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, { useEffect, useRef, useState } from 'react'; -import { EuiFlexGroup } from '@elastic/eui'; -import { TickFormatter, DomainRange, BarStyleAccessor } from '@elastic/charts'; -import useWindowSize from 'react-use/lib/useWindowSize'; -import { useWaterfallContext } from '../context/waterfall_chart'; -import { - WaterfallChartOuterContainer, - WaterfallChartFixedTopContainer, - WaterfallChartFixedTopContainerSidebarCover, - WaterfallChartSidebarWrapper, - WaterfallChartTopContainer, - RelativeContainer, - WaterfallChartFilterContainer, - WaterfallChartAxisOnlyContainer, - WaterfallChartLegendContainer, -} from './styles'; -import { CHART_LEGEND_PADDING, MAIN_GROW_SIZE, SIDEBAR_GROW_SIZE } from './constants'; -import { Sidebar } from './sidebar'; -import { Legend } from './legend'; -import { useBarCharts } from './use_bar_charts'; -import { WaterfallBarChart } from './waterfall_bar_chart'; -import { WaterfallChartFixedAxis } from './waterfall_chart_fixed_axis'; -import { NetworkRequestsTotal } from './network_requests_total'; - -export type RenderItem = ( - item: I, - index: number, - onClick?: (event: any) => void -) => JSX.Element; -export type RenderElement = () => JSX.Element; - -export interface WaterfallChartProps { - tickFormat: TickFormatter; - domain: DomainRange; - barStyleAccessor: BarStyleAccessor; - renderSidebarItem?: RenderItem; - renderLegendItem?: RenderItem; - renderFilter?: RenderElement; - renderFlyout?: RenderElement; - maxHeight?: string; - fullHeight?: boolean; -} - -export const WaterfallChart = ({ - tickFormat, - domain, - barStyleAccessor, - renderSidebarItem, - renderLegendItem, - renderFilter, - renderFlyout, - maxHeight = '800px', - fullHeight = false, -}: WaterfallChartProps) => { - const { - data, - showOnlyHighlightedNetworkRequests, - sidebarItems, - legendItems, - totalNetworkRequests, - highlightedNetworkRequests, - fetchedNetworkRequests, - } = useWaterfallContext(); - - const { width } = useWindowSize(); - - const chartWrapperDivRef = useRef(null); - const legendDivRef = useRef(null); - - const [height, setHeight] = useState(maxHeight); - - const shouldRenderSidebar = !!(sidebarItems && renderSidebarItem); - const shouldRenderLegend = !!(legendItems && legendItems.length > 0 && renderLegendItem); - - useEffect(() => { - if (fullHeight && chartWrapperDivRef.current && legendDivRef.current) { - const chartOffset = chartWrapperDivRef.current.getBoundingClientRect().top; - const legendOffset = legendDivRef.current.getBoundingClientRect().height; - setHeight(`calc(190vh - ${chartOffset + CHART_LEGEND_PADDING + legendOffset}px)`); - } - }, [chartWrapperDivRef, fullHeight, legendDivRef, width]); - - const chartsToDisplay = useBarCharts({ data }); - - return ( - - - - {shouldRenderSidebar && ( - - - - {renderFilter && ( - {renderFilter()} - )} - - )} - - - - - - - - - {shouldRenderSidebar && } - - - {chartsToDisplay.map((chartData, ind) => ( - - ))} - - - - {shouldRenderLegend && ( - - - - )} - {renderFlyout && renderFlyout()} - - ); -}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/index.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/index.tsx deleted file mode 100644 index b83cb630aaa79..0000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/index.tsx +++ /dev/null @@ -1,18 +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. - */ - -export type { RenderItem, WaterfallChartProps } from './components/waterfall_chart'; -export { WaterfallChart } from './components/waterfall_chart'; -export { WaterfallProvider, useWaterfallContext } from './context/waterfall_chart'; -export { MiddleTruncatedText } from './components/middle_truncated_text'; -export { useFlyout } from './components/use_flyout'; -export type { - WaterfallData, - WaterfallDataEntry, - WaterfallMetadata, - WaterfallMetadataEntry, -} from './types'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/types.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/types.ts deleted file mode 100644 index f1775a6fd1892..0000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/types.ts +++ /dev/null @@ -1,41 +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. - */ - -interface PlotProperties { - x: number; - y: number; - y0: number; -} - -export interface WaterfallDataSeriesConfigProperties { - tooltipProps?: Record; - showTooltip: boolean; -} - -export interface WaterfallMetadataItem { - name: string; - value?: string; -} - -export interface WaterfallMetadataEntry { - x: number; - url: string; - requestHeaders?: WaterfallMetadataItem[]; - responseHeaders?: WaterfallMetadataItem[]; - certificates?: WaterfallMetadataItem[]; - details: WaterfallMetadataItem[]; -} - -export type WaterfallDataEntry = PlotProperties & { - config: WaterfallDataSeriesConfigProperties & Record; -}; - -export type WaterfallMetadata = WaterfallMetadataEntry[]; - -export type WaterfallData = WaterfallDataEntry[]; - -export type RenderItem = (item: I, index: number) => JSX.Element; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/hooks/use_network_timings.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/hooks/use_network_timings.ts index 911e5a54f05f7..ed43a38113af9 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/hooks/use_network_timings.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/hooks/use_network_timings.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { useParams } from 'react-router-dom'; +import { i18n } from '@kbn/i18n'; import { useEsSearch } from '@kbn/observability-plugin/public'; import { NETWORK_TIMINGS_FIELDS, @@ -18,8 +20,6 @@ import { SYNTHETICS_TOTAL_TIMINGS, SYNTHETICS_WAIT_TIMINGS, } from '@kbn/observability-plugin/common'; -import { useParams } from 'react-router-dom'; -import { i18n } from '@kbn/i18n'; export const useStepFilters = (prevCheckGroupId?: string) => { const { checkGroupId, stepIndex } = useParams<{ checkGroupId: string; stepIndex: string }>(); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/hooks/use_object_metrics.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/hooks/use_object_metrics.ts index 4de7a6692f0a6..fd19ec7675ec6 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/hooks/use_object_metrics.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/hooks/use_object_metrics.ts @@ -7,11 +7,7 @@ import { useSelector } from 'react-redux'; import { useParams } from 'react-router-dom'; -import { MIME_FILTERS } from '../components/network_waterfall/step_detail/waterfall/waterfall_filter'; -import { - MimeType, - MimeTypesMap, -} from '../components/network_waterfall/step_detail/waterfall/types'; +import { MIME_FILTERS, MimeType, MimeTypesMap } from '../common/network_data/types'; import { networkEventsSelector } from '../../../state/network_events/selectors'; export const useObjectMetrics = () => { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_detail_page.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_detail_page.tsx index 780f150d8bf4c..e76718c61e617 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_detail_page.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_detail_page.tsx @@ -8,22 +8,15 @@ import React from 'react'; import { useParams } from 'react-router-dom'; import { useTrackPageview } from '@kbn/observability-plugin/public'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiHorizontalRule, - EuiPanel, - EuiLoadingSpinner, - EuiSpacer, -} from '@elastic/eui'; -import { BreakdownLegend } from './components/timings_breakdown/breakdown_legend'; -import { WaterfallChartContainer } from './components/network_waterfall/step_detail/waterfall/waterfall_chart_container'; -import { ObjectWeightList } from './components/object_weight_list'; -import { NetworkTimingsDonut } from './components/network_timings_donut'; -import { StepMetrics } from './components/step_metrics'; +import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiLoadingSpinner, EuiSpacer } from '@elastic/eui'; +import { BreakdownLegend } from './step_timing_breakdown/breakdown_legend'; +import { WaterfallChartContainer } from './step_waterfall_chart/waterfall/waterfall_chart_container'; +import { ObjectWeightList } from './step_objects/object_weight_list'; +import { NetworkTimingsDonut } from './step_timing_breakdown/network_timings_donut'; +import { StepMetrics } from './step_metrics/step_metrics'; import { NetworkTimingsBreakdown } from './network_timings_breakdown'; -import { ObjectCountList } from './components/object_count_list'; -import { StepImage } from './components/step_image'; +import { ObjectCountList } from './step_objects/object_count_list'; +import { StepImage } from './step_screenshot/step_image'; import { useJourneySteps } from '../monitor_details/hooks/use_journey_steps'; import { MonitorDetailsLinkPortal } from '../monitor_add_edit/monitor_details_portal'; @@ -108,15 +101,15 @@ export const StepDetailPage = () => {
- + + + {data && ( -
- -
+ )} ); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/definitions_popover.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_metrics/definitions_popover.tsx similarity index 100% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/definitions_popover.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_metrics/definitions_popover.tsx diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/labels.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_metrics/labels.ts similarity index 100% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/labels.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_metrics/labels.ts diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/step_metrics.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_metrics/step_metrics.tsx similarity index 100% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/step_metrics.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_metrics/step_metrics.tsx diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/color_palette.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_objects/color_palette.tsx similarity index 96% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/color_palette.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_objects/color_palette.tsx index be6bc97a1fcae..23a53c2518ba6 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/color_palette.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_objects/color_palette.tsx @@ -9,7 +9,7 @@ import React, { useState, useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiText, EuiLoadingContent } from '@elastic/eui'; import { useTheme } from '@kbn/observability-plugin/public'; import styled from 'styled-components'; -import { colourPalette } from './network_waterfall/step_detail/waterfall/data_formatting'; +import { colourPalette } from '../common/network_data/data_formatting'; export const ColorPalette = ({ label, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/object_count_list.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_objects/object_count_list.tsx similarity index 94% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/object_count_list.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_objects/object_count_list.tsx index dbd21773a0e77..bbfec1d56fc2f 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/object_count_list.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_objects/object_count_list.tsx @@ -5,8 +5,8 @@ * 2.0. */ +import React, { Fragment } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; -import React from 'react'; import { i18n } from '@kbn/i18n'; import { ColorPalette } from './color_palette'; import { useObjectMetrics } from '../hooks/use_object_metrics'; @@ -31,7 +31,7 @@ export const ObjectCountList = () => {
{objectMetrics.items.map(({ label, mimeType, percent, count }) => ( - <> + { loading={objectMetrics.loading} /> - + ))}
diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/object_weight_list.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_objects/object_weight_list.tsx similarity index 94% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/object_weight_list.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_objects/object_weight_list.tsx index 6fd10b6545196..c787fcc0711ba 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/object_weight_list.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_objects/object_weight_list.tsx @@ -5,8 +5,8 @@ * 2.0. */ +import React, { Fragment } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; -import React from 'react'; import { i18n } from '@kbn/i18n'; import { ColorPalette } from './color_palette'; import { useObjectMetrics } from '../hooks/use_object_metrics'; @@ -32,7 +32,7 @@ export const ObjectWeightList = () => {
{objectMetrics.items.map(({ label, mimeType, weightPercent, weight }) => ( - <> + { loading={objectMetrics.loading} /> {' '} - + ))}
diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/screenshot/last_successful_screenshot.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/last_successful_screenshot.tsx similarity index 70% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/screenshot/last_successful_screenshot.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/last_successful_screenshot.tsx index 3874d29197d3c..a3abaa6b8b8de 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/screenshot/last_successful_screenshot.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/last_successful_screenshot.tsx @@ -9,19 +9,25 @@ import { useFetcher } from '@kbn/observability-plugin/public'; import { EuiSpacer } from '@elastic/eui'; import React from 'react'; import { useParams } from 'react-router-dom'; -import { fetchLastSuccessfulCheck } from '../../../../state'; -import { JourneyStep } from '../../../../../../../common/runtime_types'; -import { EmptyImage } from '../../../common/screenshot/empty_image'; -import { JourneyStepScreenshotContainer } from '../../../common/screenshot/journey_step_screenshot_container'; +import { fetchLastSuccessfulCheck } from '../../../state'; +import { JourneyStep } from '../../../../../../common/runtime_types'; +import { EmptyImage } from '../../common/screenshot/empty_image'; +import { JourneyStepScreenshotContainer } from '../../common/screenshot/journey_step_screenshot_container'; -export const LastSuccessfulScreenshot = ({ step }: { step: JourneyStep }) => { - const { stepIndex } = useParams<{ checkGroupId: string; stepIndex: string }>(); +export const LastSuccessfulScreenshot = ({ + step, + stepIndex: stepInd, +}: { + step: JourneyStep; + stepIndex?: number; +}) => { + const { stepIndex } = useParams<{ checkGroupId: string; stepIndex?: string }>(); const { data, loading } = useFetcher(() => { return fetchLastSuccessfulCheck({ timestamp: step['@timestamp'], monitorId: step.monitor.id, - stepIndex: Number(stepIndex), + stepIndex: Number(stepIndex ?? stepInd), location: step.observer?.geo?.name, }); }, [step._id, step['@timestamp']]); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/screenshot/screenshot_link.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/screenshot_link.tsx similarity index 90% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/screenshot/screenshot_link.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/screenshot_link.tsx index 803c1fcc53121..1ad619735e03d 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/screenshot/screenshot_link.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/screenshot_link.tsx @@ -8,8 +8,8 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; -import { ReactRouterEuiLink } from '../../../common/react_router_helpers'; -import { Ping } from '../../../../../../../common/runtime_types'; +import { ReactRouterEuiLink } from '../../common/react_router_helpers'; +import { Ping } from '../../../../../../common/runtime_types'; const LabelLink = euiStyled.div` margin-bottom: ${(props) => props.theme.eui.euiSizeXS}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/step_image.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/step_image.tsx similarity index 93% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/step_image.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/step_image.tsx index a08ba79444ccb..161b41f5bac18 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/step_image.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/step_image.tsx @@ -8,7 +8,7 @@ import React, { useState } from 'react'; import { EuiButtonGroup, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { LastSuccessfulScreenshot } from './screenshot/last_successful_screenshot'; +import { LastSuccessfulScreenshot } from './last_successful_screenshot'; import { JourneyStep } from '../../../../../../common/runtime_types'; import { JourneyStepScreenshotContainer } from '../../common/screenshot/journey_step_screenshot_container'; @@ -58,7 +58,7 @@ export const StepImage = ({ asThumbnail={false} /> ) : ( - + )} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/screenshot/step_screenshot_display.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/step_screenshot_display.test.tsx similarity index 92% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/screenshot/step_screenshot_display.test.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/step_screenshot_display.test.tsx index 7a275527de3c6..5848f78d95ea7 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/screenshot/step_screenshot_display.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/step_screenshot_display.test.tsx @@ -8,9 +8,9 @@ import React from 'react'; import { StepScreenshotDisplay } from './step_screenshot_display'; import * as observabilityPublic from '@kbn/observability-plugin/public'; -import { mockRef } from '../../../../utils/testing/__mocks__/screenshot_ref.mock'; -import { render } from '../../../../utils/testing'; -import '../../../../utils/testing/__mocks__/use_composite_image.mock'; +import { mockRef } from '../../../utils/testing/__mocks__/screenshot_ref.mock'; +import { render } from '../../../utils/testing'; +import '../../../utils/testing/__mocks__/use_composite_image.mock'; jest.mock('@kbn/observability-plugin/public'); jest.mock('react-use/lib/useIntersection', () => () => ({ diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/screenshot/step_screenshot_display.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/step_screenshot_display.tsx similarity index 96% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/screenshot/step_screenshot_display.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/step_screenshot_display.tsx index 1dbfe9595cc44..75c144190bce7 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/screenshot/step_screenshot_display.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_screenshot/step_screenshot_display.tsx @@ -19,17 +19,17 @@ import { FormattedMessage } from '@kbn/i18n-react'; import React, { useEffect, useMemo, useRef, useState, FC } from 'react'; import useIntersection from 'react-use/lib/useIntersection'; import { useFetcher } from '@kbn/observability-plugin/public'; -import { getJourneyScreenshot } from '../../../../state'; -import { useCompositeImage } from '../../../../hooks'; +import { getJourneyScreenshot } from '../../../state'; +import { useCompositeImage } from '../../../hooks'; import { useSyntheticsRefreshContext, useSyntheticsSettingsContext, useSyntheticsThemeContext, -} from '../../../../contexts'; +} from '../../../contexts'; import { isScreenshotRef as isAScreenshotRef, ScreenshotRefImageData, -} from '../../../../../../../common/runtime_types'; +} from '../../../../../../common/runtime_types'; interface StepScreenshotDisplayProps { isFullScreenshot: boolean; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/timings_breakdown/breakdown_legend.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_timing_breakdown/breakdown_legend.tsx similarity index 77% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/timings_breakdown/breakdown_legend.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_timing_breakdown/breakdown_legend.tsx index 323bd98a4f758..46c81f98198bc 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/timings_breakdown/breakdown_legend.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_timing_breakdown/breakdown_legend.tsx @@ -5,11 +5,12 @@ * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiHealth, EuiSpacer, EuiText } from '@elastic/eui'; import React from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiHealth, EuiSpacer, EuiText } from '@elastic/eui'; import { useTheme } from '@kbn/observability-plugin/public'; -import { formatMillisecond } from '../network_timings_donut'; -import { useNetworkTimings } from '../../hooks/use_network_timings'; + +import { formatMillisecond } from '../common/network_data/data_formatting'; +import { useNetworkTimings } from '../hooks/use_network_timings'; export const BreakdownLegend = () => { const networkTimings = useNetworkTimings(); @@ -21,7 +22,7 @@ export const BreakdownLegend = () => { {networkTimings.timingsWithLabels.map(({ label, value }, index) => ( - + )[`euiColorVis${index + 1}`]} @@ -30,7 +31,9 @@ export const BreakdownLegend = () => { - {formatMillisecond(value)} + + {formatMillisecond(value)} + ))} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_timings_donut.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_timing_breakdown/network_timings_donut.tsx similarity index 91% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_timings_donut.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_timing_breakdown/network_timings_donut.tsx index 62e5219c68105..439cc300afe4f 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_timings_donut.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_timing_breakdown/network_timings_donut.tsx @@ -5,20 +5,21 @@ * 2.0. */ +import React from 'react'; +import { i18n } from '@kbn/i18n'; import { Chart, - Partition, - Settings, - PartitionLayout, Datum, LIGHT_THEME, PartialTheme, + Partition, + PartitionLayout, + Settings, } from '@elastic/charts'; -import React from 'react'; +import { EuiLoadingSpinner, EuiSpacer, EuiTitle } from '@elastic/eui'; import { useTheme } from '@kbn/observability-plugin/public'; +import { formatMillisecond } from '../common/network_data/data_formatting'; -import { EuiLoadingSpinner, EuiSpacer, EuiTitle } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import { useNetworkTimings } from '../hooks/use_network_timings'; const themeOverrides: PartialTheme = { @@ -78,12 +79,5 @@ export const NetworkTimingsDonut = () => { }; const TIMINGS_BREAKDOWN = i18n.translate('xpack.synthetics.stepDetailsRoute.timingsBreakdown', { - defaultMessage: 'Timings breakdown', + defaultMessage: 'Timing breakdown', }); - -export const formatMillisecond = (ms: number) => { - if (ms < 1000) { - return `${ms.toFixed(0)} ms`; - } - return `${(ms / 1000).toFixed(1)} s`; -}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/translations.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/labels.ts similarity index 100% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/translations.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/labels.ts diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/step_detail_container.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/step_detail_container.tsx similarity index 95% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/step_detail_container.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/step_detail_container.tsx index 3035bebf95879..c1a60433b0922 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/step_detail_container.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/step_detail_container.tsx @@ -8,7 +8,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiText, EuiLoadingSpinner } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { useStepDetailPage } from '../../../hooks/use_step_detail_page'; +import { useStepDetailPage } from '../hooks/use_step_detail_page'; import { useMonitorBreadcrumb } from './use_monitor_breadcrumb'; import { WaterfallChartContainer } from './waterfall/waterfall_chart_container'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/step_page_nav.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/step_page_nav.tsx similarity index 100% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/step_page_nav.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/step_page_nav.tsx diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/step_page_title.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/step_page_title.tsx similarity index 100% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/step_page_title.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/step_page_title.tsx diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/use_monitor_breadcrumb.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_monitor_breadcrumb.tsx similarity index 87% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/use_monitor_breadcrumb.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_monitor_breadcrumb.tsx index e30039280b307..499647d16b0a0 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/use_monitor_breadcrumb.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_monitor_breadcrumb.tsx @@ -8,10 +8,10 @@ import moment from 'moment'; import { i18n } from '@kbn/i18n'; import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { getShortTimeStamp } from '../../../../../utils/monitor_test_result/timestamp'; -import { PLUGIN } from '../../../../../../../../common/constants/plugin'; -import { useBreadcrumbs } from '../../../../../hooks'; -import { SyntheticsJourneyApiResponse } from '../../../../../../../../common/runtime_types'; +import { getShortTimeStamp } from '../../../utils/monitor_test_result/timestamp'; +import { PLUGIN } from '../../../../../../common/constants/plugin'; +import { useBreadcrumbs } from '../../../hooks'; +import { SyntheticsJourneyApiResponse } from '../../../../../../common/runtime_types'; interface ActiveStep { monitor: { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/use_monitor_breadcrumbs.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_monitor_breadcrumbs.test.tsx similarity index 96% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/use_monitor_breadcrumbs.test.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_monitor_breadcrumbs.test.tsx index 416b5c3ca10c6..4473ba72f510f 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/use_monitor_breadcrumbs.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_monitor_breadcrumbs.test.tsx @@ -11,9 +11,9 @@ import { Route } from 'react-router-dom'; import { of } from 'rxjs'; import { chromeServiceMock, uiSettingsServiceMock } from '@kbn/core/public/mocks'; import { useMonitorBreadcrumb } from './use_monitor_breadcrumb'; -import { Ping, SyntheticsJourneyApiResponse } from '../../../../../../../../common/runtime_types'; -import { render } from '../../../../../utils/testing'; -import { OVERVIEW_ROUTE } from '../../../../../../../../common/constants'; +import { Ping, SyntheticsJourneyApiResponse } from '../../../../../../common/runtime_types'; +import { render } from '../../../utils/testing'; +import { OVERVIEW_ROUTE } from '../../../../../../common/constants'; describe('useMonitorBreadcrumbs', () => { it('sets the given breadcrumbs for steps list view', () => { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/use_step_waterfall_metrics.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_step_waterfall_metrics.test.tsx similarity index 100% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/use_step_waterfall_metrics.test.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_step_waterfall_metrics.test.tsx diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/use_step_waterfall_metrics.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_step_waterfall_metrics.ts similarity index 97% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/use_step_waterfall_metrics.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_step_waterfall_metrics.ts index 290bf7efbb020..54d382c2240ca 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/use_step_waterfall_metrics.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/use_step_waterfall_metrics.ts @@ -6,7 +6,7 @@ */ import { createEsParams, useEsSearch } from '@kbn/observability-plugin/public'; -import { MarkerItems } from '../waterfall/context/waterfall_chart'; +import { MarkerItems } from './waterfall/context/waterfall_context'; export interface Props { checkGroup: string; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/README.md b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/README.md similarity index 100% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/README.md rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/README.md diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/constants.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/constants.ts similarity index 79% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/constants.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/constants.ts index d36cb025f3c2b..67dd1d5e29e5c 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/constants.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/constants.ts @@ -10,12 +10,17 @@ export const BAR_HEIGHT = 24; // Flex grow value export const MAIN_GROW_SIZE = 8; // Flex grow value -export const SIDEBAR_GROW_SIZE = 2; +export const SIDEBAR_GROW_SIZE = 3; // Axis height // NOTE: This isn't a perfect solution - changes in font size etc within charts could change the ideal height here. export const FIXED_AXIS_HEIGHT = 24; +// Font size of the request titles/links in the left sidebar +export const RESOURCE_TITLE_FONT_SIZE = 14; + // number of items to display in canvas, since canvas can only have limited size export const CANVAS_MAX_ITEMS = 150; export const CHART_LEGEND_PADDING = 33; + +export const CHART_HEADER_HEIGHT = 146; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/context/waterfall_chart.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/context/waterfall_context.tsx similarity index 63% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/context/waterfall_chart.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/context/waterfall_context.tsx index 115dd15b416fc..daf38c465292b 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/context/waterfall_chart.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/context/waterfall_context.tsx @@ -5,11 +5,15 @@ * 2.0. */ -import React, { createContext, useContext, Context } from 'react'; -import { JourneyStep } from '../../../../../../../../../common/runtime_types'; -import { WaterfallData, WaterfallDataEntry, WaterfallMetadata } from '../types'; -import { OnSidebarClick, OnElementClick, OnProjectionClick } from '../components/use_flyout'; -import { SidebarItems } from '../../step_detail/waterfall/types'; +import React, { createContext, useContext, Context, Dispatch, SetStateAction } from 'react'; +import { JourneyStep } from '../../../../../../../../common/runtime_types'; +import { + WaterfallData, + WaterfallDataEntry, + WaterfallMetadata, +} from '../../../common/network_data/types'; +import { OnSidebarClick, OnElementClick, OnProjectionClick } from '../waterfall_flyout/use_flyout'; +import { SidebarItem } from '../../../common/network_data/types'; export type MarkerItems = Array<{ id: @@ -31,8 +35,7 @@ export interface IWaterfallContext { onProjectionClick?: OnProjectionClick; onSidebarClick?: OnSidebarClick; showOnlyHighlightedNetworkRequests: boolean; - sidebarItems?: SidebarItems; - legendItems?: unknown[]; + sidebarItems?: SidebarItem[]; metadata: WaterfallMetadata; renderTooltipItem: ( item: WaterfallDataEntry['config']['tooltipProps'], @@ -40,28 +43,16 @@ export interface IWaterfallContext { ) => JSX.Element; markerItems?: MarkerItems; activeStep?: JourneyStep; + activeFilters: string[]; + setActiveFilters: Dispatch>; + setOnlyHighlighted: (val: boolean) => void; + query: string; + setQuery: (val: string) => void; } export const WaterfallContext = createContext>({}); -interface ProviderProps { - totalNetworkRequests: number; - highlightedNetworkRequests: number; - fetchedNetworkRequests: number; - data: IWaterfallContext['data']; - onElementClick?: IWaterfallContext['onElementClick']; - onProjectionClick?: IWaterfallContext['onProjectionClick']; - onSidebarClick?: IWaterfallContext['onSidebarClick']; - showOnlyHighlightedNetworkRequests: IWaterfallContext['showOnlyHighlightedNetworkRequests']; - sidebarItems?: IWaterfallContext['sidebarItems']; - legendItems?: IWaterfallContext['legendItems']; - metadata: IWaterfallContext['metadata']; - renderTooltipItem: IWaterfallContext['renderTooltipItem']; - markerItems?: MarkerItems; - activeStep?: JourneyStep; -} - -export const WaterfallProvider: React.FC = ({ +export const WaterfallProvider: React.FC = ({ children, data, markerItems, @@ -70,13 +61,17 @@ export const WaterfallProvider: React.FC = ({ onSidebarClick, showOnlyHighlightedNetworkRequests, sidebarItems, - legendItems, metadata, renderTooltipItem, totalNetworkRequests, highlightedNetworkRequests, fetchedNetworkRequests, activeStep, + activeFilters, + setActiveFilters, + setOnlyHighlighted, + query, + setQuery, }) => { return ( = ({ markerItems, showOnlyHighlightedNetworkRequests, sidebarItems, - legendItems, metadata, onElementClick, onProjectionClick, @@ -95,6 +89,11 @@ export const WaterfallProvider: React.FC = ({ totalNetworkRequests, highlightedNetworkRequests, fetchedNetworkRequests, + activeFilters, + setActiveFilters, + setOnlyHighlighted, + query, + setQuery, }} > {children} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/middle_truncated_text.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/middle_truncated_text.test.tsx similarity index 97% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/middle_truncated_text.test.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/middle_truncated_text.test.tsx index 707a561043b4f..e6b29cfb9faa7 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/middle_truncated_text.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/middle_truncated_text.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { within, fireEvent, waitFor } from '@testing-library/react'; import { getChunks, MiddleTruncatedText } from './middle_truncated_text'; -import { render } from '../../../../../../utils/testing'; +import { render } from '../../../../utils/testing'; const longString = 'this-is-a-really-really-really-really-really-really-really-really-long-string.madeup.extension'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/middle_truncated_text.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/middle_truncated_text.tsx similarity index 91% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/middle_truncated_text.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/middle_truncated_text.tsx index 7da52b2ce9bc2..9c96c78e74649 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/middle_truncated_text.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/middle_truncated_text.tsx @@ -19,8 +19,8 @@ import { i18n } from '@kbn/i18n'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { WaterfallTooltipContent } from './waterfall_tooltip_content'; import { WaterfallChartTooltip } from './styles'; -import { FIXED_AXIS_HEIGHT } from './constants'; -import { formatTooltipHeading } from '../../step_detail/waterfall/data_formatting'; +import { FIXED_AXIS_HEIGHT, RESOURCE_TITLE_FONT_SIZE } from './constants'; +import { formatTooltipHeading } from '../../common/network_data/data_formatting'; interface Props { index: number; @@ -49,10 +49,12 @@ const InnerContainer = euiStyled.span` const IndexNumber = euiStyled(EuiText)` font-family: ${(props) => props.theme.eui.euiCodeFontFamily}; - margin-right: ${(props) => props.theme.eui.euiSizeXS}; + margin-right: ${(props) => props.theme.eui.euiSizeS}; line-height: ${FIXED_AXIS_HEIGHT}px; text-align: right; background-color: ${(props) => props.theme.eui.euiColorLightestShade}; + text-align: center; + color: ${(props) => props.theme.eui.euiColorDarkShade}; `; const FirstChunk = euiStyled.span` @@ -60,12 +62,14 @@ const FirstChunk = euiStyled.span` white-space: nowrap; overflow: hidden; line-height: ${FIXED_AXIS_HEIGHT}px; + font-size: ${RESOURCE_TITLE_FONT_SIZE}px; text-align: left; `; // safari doesn't auto align text left in some cases const LastChunk = euiStyled.span` flex-shrink: 0; line-height: ${FIXED_AXIS_HEIGHT}px; + font-size: ${RESOURCE_TITLE_FONT_SIZE}px; text-align: left; `; // safari doesn't auto align text left in some cases @@ -135,11 +139,11 @@ export const MiddleTruncatedText = ({ > - {index + '.'} + {index} {secureHttps && ( = ({ items, render }) => { + const { euiTheme } = useEuiTheme(); const { onSidebarClick } = useWaterfallContext(); const handleSidebarClick = useMemo(() => onSidebarClick, [onSidebarClick]); return ( - - - + {items.map((item, index) => { return ( - + {render(item, index, handleSidebarClick)} - + ); })} - - - + +
+
); }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/styles.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/styles.ts new file mode 100644 index 0000000000000..646ff0b960cd0 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/styles.ts @@ -0,0 +1,122 @@ +/* + * 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 { EuiFlexItem } from '@elastic/eui'; +import { rgba } from 'polished'; +import { euiStyled } from '@kbn/kibana-react-plugin/common'; +import { FIXED_AXIS_HEIGHT, CHART_HEADER_HEIGHT } from './constants'; + +interface WaterfallChartOuterContainerProps { + height?: string; +} + +const StyledScrollDiv = euiStyled.div` + &::-webkit-scrollbar { + height: ${({ theme }) => theme.eui.euiScrollBar}; + width: ${({ theme }) => theme.eui.euiScrollBar}; + } + &::-webkit-scrollbar-thumb { + background-clip: content-box; + background-color: ${({ theme }) => rgba(theme.eui.euiColorDarkShade, 0.5)}; + border: ${({ theme }) => theme.eui.euiScrollBarCorner} solid transparent; + } + &::-webkit-scrollbar-corner, + &::-webkit-scrollbar-track { + background-color: transparent; + } +`; + +export const WaterfallChartOuterContainer = euiStyled( + StyledScrollDiv +)` + height: auto; + overflow: hidden; + z-index: 50; +`; + +export const WaterfallChartStickyHeaderContainer = euiStyled(StyledScrollDiv)` + position: sticky; + top: 96px; + z-index: ${(props) => props.theme.eui.euiZLevel5}; + overflow: visible; + min-height: ${CHART_HEADER_HEIGHT}px; + border-color: ${(props) => props.theme.eui.euiColorLightShade}; + border-top: ${(props) => props.theme.eui.euiBorderThin}; + border-bottom: ${(props) => props.theme.eui.euiBorderThin}; + padding: ${(props) => props.theme.eui.euiSizeL}; + padding-bottom: ${(props) => props.theme.eui.euiSizeXL}; + padding-left: ${(props) => props.theme.eui.euiSizeM}; +`; + +export const WaterfallChartTimeTicksContainer = euiStyled(StyledScrollDiv)` + z-index: ${(props) => props.theme.eui.euiZLevel6}; + overflow: hidden; + position: absolute; + left: 0; + bottom: -10px; + width: 100%; + height: auto; + border: none; + background: transparent; +`; + +export const WaterfallChartFixedAxisContainer = euiStyled.div` + z-index: ${(props) => props.theme.eui.euiZLevel4}; + height: 100%; + &&& { + .echAnnotation__icon { + top: 8px; + } + } +`; + +export const WaterfallChartSidebarWrapper = euiStyled(EuiFlexItem)` + z-index: ${(props) => props.theme.eui.euiZLevel4}; + min-width: 0; +`; // NOTE: min-width: 0 ensures flexbox and no-wrap children can co-exist + +export const SideBarItemHighlighter = euiStyled(EuiFlexItem)` + height: 100%; + .euiButtonEmpty { + height: ${FIXED_AXIS_HEIGHT}px; + font-size:${({ theme }) => theme.eui.euiFontSizeM}; + } +`; + +interface WaterfallChartChartContainer { + height: number; + chartIndex: number; +} + +export const WaterfallChartChartContainer = euiStyled.div` + width: 100%; + height: ${(props) => `${props.height + FIXED_AXIS_HEIGHT + 4}px`}; + margin-top: -${FIXED_AXIS_HEIGHT + 4}px; + z-index: ${(props) => Math.round(props.theme.eui.euiZLevel3 / (props.chartIndex + 1))}; + background-color: ${(props) => props.theme.eui.euiColorEmptyShade}; + + &&& { + .echCanvasRenderer { + height: calc(100% + 0px) !important; + } + } +`; + +export const WaterfallTooltipResponsiveMaxWidth = euiStyled.div` + margin-top: 16px; + max-width: 90vw; +`; + +export const WaterfallChartTooltip = euiStyled(WaterfallTooltipResponsiveMaxWidth)` + background-color: ${(props) => props.theme.eui.euiColorDarkestShade}; + border-radius: ${(props) => props.theme.eui.euiBorderRadius}; + color: ${(props) => props.theme.eui.euiColorLightestShade}; + padding: ${(props) => props.theme.eui.euiSizeS}; + .euiToolTip__arrow { + background-color: ${(props) => props.theme.eui.euiColorDarkestShade}; + } +`; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/translations.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/translations.ts similarity index 72% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/translations.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/translations.ts index 6bb0c03f7b99e..a1deffad52e43 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/translations.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/translations.ts @@ -14,6 +14,13 @@ export const FILTER_REQUESTS_LABEL = i18n.translate( } ); +export const SEARCH_REQUESTS_LABEL = i18n.translate( + 'xpack.synthetics.synthetics.waterfall.searchBox.searchLabel', + { + defaultMessage: 'Search', + } +); + export const FILTER_SCREENREADER_LABEL = i18n.translate( 'xpack.synthetics.synthetics.waterfall.filterGroup.filterScreenreaderLabel', { @@ -28,20 +35,6 @@ export const FILTER_REMOVE_SCREENREADER_LABEL = i18n.translate( } ); -export const FILTER_POPOVER_OPEN_LABEL = i18n.translate( - 'xpack.synthetics.pingList.synthetics.waterfall.filters.popover', - { - defaultMessage: 'Click to open waterfall filters', - } -); - -export const FILTER_COLLAPSE_REQUESTS_LABEL = i18n.translate( - 'xpack.synthetics.pingList.synthetics.waterfall.filters.collapseRequestsLabel', - { - defaultMessage: 'Collapse to only show matching requests', - } -); - export const SIDEBAR_FILTER_MATCHES_SCREENREADER_LABEL = i18n.translate( 'xpack.synthetics.synthetics.waterfall.sidebar.filterMatchesScreenReaderLabel', { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/use_bar_charts.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/use_bar_charts.test.tsx similarity index 98% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/use_bar_charts.test.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/use_bar_charts.test.tsx index a963fb1e2939c..24c1c074bd86a 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/use_bar_charts.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/use_bar_charts.test.tsx @@ -7,7 +7,7 @@ import { useBarCharts } from './use_bar_charts'; import { renderHook } from '@testing-library/react-hooks'; -import { IWaterfallContext } from '../context/waterfall_chart'; +import { IWaterfallContext } from './context/waterfall_context'; import { CANVAS_MAX_ITEMS } from './constants'; const generateTestData = ( diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/use_bar_charts.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/use_bar_charts.ts similarity index 69% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/use_bar_charts.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/use_bar_charts.ts index 2baf895504911..2045c9c1f08c3 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/use_bar_charts.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/use_bar_charts.ts @@ -6,7 +6,7 @@ */ import { useEffect, useState } from 'react'; -import { IWaterfallContext } from '../context/waterfall_chart'; +import { IWaterfallContext } from './context/waterfall_context'; import { CANVAS_MAX_ITEMS } from './constants'; export interface UseBarHookProps { @@ -27,19 +27,21 @@ export const useBarCharts = ({ data }: UseBarHookProps) => { * We must keep track of the number of unique resources added to the each array. */ const uniqueResources = new Set(); let lastIndex: number; - data.forEach((item) => { - if (uniqueResources.size === CANVAS_MAX_ITEMS && item.x > lastIndex) { - chartIndex++; - uniqueResources.clear(); - } - uniqueResources.add(item.x); - lastIndex = item.x; - if (!chartsN[chartIndex]) { - chartsN.push([item]); - return; - } - chartsN[chartIndex].push(item); - }); + data + .filter((item) => true) + .forEach((item) => { + if (uniqueResources.size === CANVAS_MAX_ITEMS && item.x > lastIndex) { + chartIndex++; + uniqueResources.clear(); + } + uniqueResources.add(item.x); + lastIndex = item.x; + if (!chartsN[chartIndex]) { + chartsN.push([item]); + return; + } + chartsN[chartIndex].push(item); + }); } setCharts(chartsN); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_bar_chart.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_bar_chart.tsx similarity index 86% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_bar_chart.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_bar_chart.tsx index 3c9baed0dd3d6..124b64793678b 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_bar_chart.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_bar_chart.tsx @@ -18,13 +18,15 @@ import { TickFormatter, TooltipInfo, } from '@elastic/charts'; -import { useChartTheme } from '../../../../../../../../hooks/use_chart_theme'; +import { useEuiTheme } from '@elastic/eui'; +import { useChartTheme } from '../../../../../../hooks/use_chart_theme'; import { BAR_HEIGHT } from './constants'; import { WaterfallChartChartContainer, WaterfallChartTooltip } from './styles'; -import { useWaterfallContext, WaterfallData } from '..'; +import { WaterfallData } from '../../common/network_data/types'; +import { useWaterfallContext } from './context/waterfall_context'; import { WaterfallTooltipContent } from './waterfall_tooltip_content'; -import { formatTooltipHeading } from '../../step_detail/waterfall/data_formatting'; -import { WaterfallChartMarkers } from './waterfall_markers'; +import { formatTooltipHeading } from '../../common/network_data/data_formatting'; +import { WaterfallChartMarkers } from './waterfall_marker/waterfall_markers'; const getChartHeight = (data: WaterfallData): number => { // We get the last item x(number of bars) and adds 1 to cater for 0 index @@ -71,6 +73,7 @@ export const WaterfallBarChart = ({ index, }: Props) => { const theme = useChartTheme(); + const { euiTheme } = useEuiTheme(); const { onElementClick, onProjectionClick } = useWaterfallContext(); const handleElementClick = useMemo(() => onElementClick, [onElementClick]); const handleProjectionClick = useMemo(() => onProjectionClick, [onProjectionClick]); @@ -108,6 +111,10 @@ export const WaterfallBarChart = ({ axisLine: { visible: false, }, + tickLabel: { + fontSize: 12, + fill: euiTheme.colors.darkestShade, + }, }} /> diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart.tsx new file mode 100644 index 0000000000000..9ea2ff0cd4b5b --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart.tsx @@ -0,0 +1,144 @@ +/* + * 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, { useRef } from 'react'; +import { TickFormatter, DomainRange, BarStyleAccessor } from '@elastic/charts'; +import { EuiFlexGroup, EuiFlexItem, useEuiTheme } from '@elastic/eui'; + +import { useWaterfallContext } from './context/waterfall_context'; +import { WaterfallSearch } from './waterfall_header/waterfall_search'; +import { WaterfallLegend } from './waterfall_header/waterfall_legend'; +import { WaterfallTickAxis } from './waterfall_header/waterfall_tick_axis'; + +import { + WaterfallChartOuterContainer, + WaterfallChartStickyHeaderContainer, + WaterfallChartSidebarWrapper, +} from './styles'; +import { MAIN_GROW_SIZE, SIDEBAR_GROW_SIZE } from './constants'; +import { Sidebar } from './sidebar'; +import { useBarCharts } from './use_bar_charts'; +import { WaterfallBarChart } from './waterfall_bar_chart'; + +export type RenderItem = ( + item: I, + index: number, + onClick?: (event: any) => void +) => JSX.Element; +export type RenderElement = () => JSX.Element; + +export interface WaterfallChartProps { + tickFormat: TickFormatter; + domain: DomainRange; + barStyleAccessor: BarStyleAccessor; + renderSidebarItem?: RenderItem; + renderLegendItem?: RenderItem; + renderFlyout?: RenderElement; +} + +export const WaterfallChart = ({ + tickFormat, + domain, + barStyleAccessor, + renderSidebarItem, + renderFlyout, +}: WaterfallChartProps) => { + const { euiTheme } = useEuiTheme(); + const { + data, + query, + setQuery, + sidebarItems, + activeFilters, + setActiveFilters, + showOnlyHighlightedNetworkRequests, + setOnlyHighlighted, + totalNetworkRequests, + highlightedNetworkRequests, + fetchedNetworkRequests, + } = useWaterfallContext(); + + const chartWrapperDivRef = useRef(null); + + const shouldRenderSidebar = !!(sidebarItems && renderSidebarItem); + + const chartsToDisplay = useBarCharts({ data }); + const cancelPagePadding = { + marginLeft: `-${euiTheme.size.l}`, + marginRight: `-${euiTheme.size.l}`, + }; + + return ( +
+ + + {shouldRenderSidebar && ( + + + + )} + + + + + + + + + + + {shouldRenderSidebar ? ( + + ) : null} + + {chartsToDisplay.map((chartData, ind) => ( + + ))} + + + + {renderFlyout && renderFlyout()} +
+ ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_chart_container.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_container.test.tsx similarity index 98% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_chart_container.test.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_container.test.tsx index 3802ace38f453..0533e47c6244e 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_chart_container.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_container.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { screen } from '@testing-library/react'; import { WaterfallChartContainer } from './waterfall_chart_container'; -import { render } from '../../../../../../utils/testing'; +import { render } from '../../../../utils/testing'; const networkEvents = { events: [ diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_chart_container.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_container.tsx similarity index 91% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_chart_container.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_container.tsx index effe2c2ed42ca..f63c4beddd855 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_chart_container.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_container.tsx @@ -10,11 +10,11 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import React, { useEffect } from 'react'; import { useSelector, useDispatch } from 'react-redux'; -import { networkEventsSelector } from '../../../../../../state/network_events/selectors'; -import { getNetworkEvents } from '../../../../../../state/network_events/actions'; -import { JourneyStep } from '../../../../../../../../../common/runtime_types'; +import { networkEventsSelector } from '../../../../state/network_events/selectors'; +import { getNetworkEvents } from '../../../../state/network_events/actions'; +import { JourneyStep } from '../../../../../../../common/runtime_types'; import { WaterfallChartWrapper } from './waterfall_chart_wrapper'; -import { extractItems } from './data_formatting'; +import { extractItems } from '../../common/network_data/data_formatting'; import { useStepWaterfallMetrics } from '../use_step_waterfall_metrics'; export const NO_DATA_TEXT = i18n.translate( diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_chart_fixed_axis.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_fixed_axis.tsx similarity index 75% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_chart_fixed_axis.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_fixed_axis.tsx index 15b29beb19759..56f95f64bdc78 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_chart_fixed_axis.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_fixed_axis.tsx @@ -18,9 +18,10 @@ import { TickFormatter, TooltipType, } from '@elastic/charts'; -import { useChartTheme } from '../../../../../../../../hooks/use_chart_theme'; +import { useEuiTheme } from '@elastic/eui'; +import { useChartTheme } from '../../../../../../hooks/use_chart_theme'; import { WaterfallChartFixedAxisContainer } from './styles'; -import { WaterfallChartMarkers } from './waterfall_markers'; +import { WaterfallChartMarkers } from './waterfall_marker/waterfall_markers'; interface Props { tickFormat: TickFormatter; @@ -30,6 +31,7 @@ interface Props { export const WaterfallChartFixedAxis = ({ tickFormat, domain, barStyleAccessor }: Props) => { const theme = useChartTheme(); + const { euiTheme } = useEuiTheme(); return ( @@ -38,13 +40,26 @@ export const WaterfallChartFixedAxis = ({ tickFormat, domain, barStyleAccessor } showLegend={false} rotation={90} tooltip={{ type: TooltipType.None }} - theme={theme} + theme={[ + { + background: { + color: 'transparent', + }, + }, + theme, + ]} /> diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_chart_wrapper.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_wrapper.test.tsx similarity index 76% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_chart_wrapper.test.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_wrapper.test.tsx index 94df6a4e2e698..872e67fcab0c2 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_chart_wrapper.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_wrapper.test.tsx @@ -8,20 +8,23 @@ import React from 'react'; import { act, fireEvent, waitFor } from '@testing-library/react'; import { WaterfallChartWrapper } from './waterfall_chart_wrapper'; -import { networkItems as mockNetworkItems } from './data_formatting.test'; +import { networkItems as mockNetworkItems } from '../../common/network_data/data_formatting.test'; -import { extractItems, isHighlightedItem } from './data_formatting'; -import { BAR_HEIGHT } from '../../waterfall/components/constants'; -import { MimeType } from './types'; import { - FILTER_POPOVER_OPEN_LABEL, - FILTER_REQUESTS_LABEL, - FILTER_COLLAPSE_REQUESTS_LABEL, -} from '../../waterfall/components/translations'; -import { render } from '../../../../../../utils/testing'; + extractItems, + isHighlightedItem, + getQueryMatcher, + getFilterMatcher, +} from '../../common/network_data/data_formatting'; +import { BAR_HEIGHT } from './constants'; +import { MimeType } from '../../common/network_data/types'; +import { FILTER_REQUESTS_LABEL } from './translations'; +import { render } from '../../../../utils/testing'; const getHighLightedItems = (query: string, filters: string[]) => { - return NETWORK_EVENTS.events.filter((item) => isHighlightedItem(item, query, filters)); + return NETWORK_EVENTS.events.filter((item) => + isHighlightedItem(item, getQueryMatcher(query), getFilterMatcher(filters)) + ); }; describe('WaterfallChartWrapper', () => { @@ -67,13 +70,14 @@ describe('WaterfallChartWrapper', () => { ); const SIDE_BAR_ITEMS_HEIGHT = NETWORK_EVENTS.events.length * BAR_HEIGHT; - expect(getByTestId('wfSidebarContainer')).toHaveAttribute('height', `${SIDE_BAR_ITEMS_HEIGHT}`); - - expect(getByTestId('wfDataOnlyBarChart')).toHaveAttribute('height', `${SIDE_BAR_ITEMS_HEIGHT}`); + expect(getByTestId('wfSidebarContainer').style).toHaveProperty( + 'height', + `${SIDE_BAR_ITEMS_HEIGHT}px` + ); }); it('search by mime type works', () => { - const { getAllByTestId, getByLabelText, getAllByText } = render( + const { getAllByTestId, getByText } = render( ); @@ -81,9 +85,7 @@ describe('WaterfallChartWrapper', () => { expect(sideBarItems).toHaveLength(5); - fireEvent.click(getByLabelText(FILTER_POPOVER_OPEN_LABEL)); - - fireEvent.click(getAllByText('XHR')[1]); + fireEvent.click(getByText('XHR')); // inout has debounce effect so hence the timer act(() => { @@ -99,7 +101,7 @@ describe('WaterfallChartWrapper', () => { }); it('renders sidebar even when filter matches 0 resources', () => { - const { getAllByTestId, getByLabelText, getAllByText, queryAllByTestId } = render( + const { getAllByTestId, getByTestId, getByLabelText, queryAllByTestId, getByText } = render( ); @@ -107,9 +109,7 @@ describe('WaterfallChartWrapper', () => { expect(sideBarItems).toHaveLength(5); - fireEvent.click(getByLabelText(FILTER_POPOVER_OPEN_LABEL)); - - fireEvent.click(getAllByText('CSS')[1]); + fireEvent.click(getByText('CSS')); // inout has debounce effect so hence the timer act(() => { @@ -124,7 +124,7 @@ describe('WaterfallChartWrapper', () => { NETWORK_EVENTS.events.length - highlightedItemsLength ); - fireEvent.click(getByLabelText(FILTER_COLLAPSE_REQUESTS_LABEL)); + fireEvent.click(getByTestId('syntheticsWaterfallHideNonMatching')); // filter bar is still accessible even when no resources match filter expect(getByLabelText(FILTER_REQUESTS_LABEL)).toBeInTheDocument(); @@ -140,7 +140,7 @@ describe('WaterfallChartWrapper', () => { ); expect(getByText(`${mockNetworkItems[0].url}`)).toBeInTheDocument(); - expect(getByText(`1.`)).toBeInTheDocument(); + expect(getByText(`1`)).toBeInTheDocument(); expect(queryByText('Content type')).not.toBeInTheDocument(); expect(queryByText(`${mockNetworkItems[0]?.mimeType}`)).not.toBeInTheDocument(); @@ -167,35 +167,18 @@ describe('WaterfallChartWrapper', () => { }); }); - it('opens flyout on sidebar click and closes on second sidebar click', async () => { - const { getByText, getByTestId, queryByText } = render( - + it('Shows "Hide nonmatching" when search or filter is active', async () => { + const { getByText, getByTestId, queryByTestId } = render( + ); - expect(getByText(`${mockNetworkItems[0].url}`)).toBeInTheDocument(); - expect(getByText(`1.`)).toBeInTheDocument(); - expect(queryByText('Content type')).not.toBeInTheDocument(); - expect(queryByText(`${mockNetworkItems[0]?.mimeType}`)).not.toBeInTheDocument(); - - // open flyout - // selector matches both button and accessible text. Button is the second element in the array; - const sidebarButton = getByTestId(`middleTruncatedTextButton1`); - fireEvent.click(sidebarButton); - - // check for sample flyout items and that the flyout is focused - await waitFor(() => { - const waterfallFlyout = getByTestId('waterfallFlyout'); - expect(waterfallFlyout).toBeInTheDocument(); - expect(getByText('Content type')).toBeInTheDocument(); - expect(getByText(`${mockNetworkItems[0]?.mimeType}`)).toBeInTheDocument(); - }); + expect(queryByTestId('syntheticsWaterfallHideNonMatching')).not.toBeInTheDocument(); - fireEvent.click(sidebarButton); + // Toggle a filter + fireEvent.click(getByText('Image').closest('[aria-checked]')); - /* check that sample flyout items are gone from the DOM */ await waitFor(() => { - expect(queryByText('Content type')).not.toBeInTheDocument(); - expect(queryByText(`${mockNetworkItems[0]?.mimeType}`)).not.toBeInTheDocument(); + expect(getByTestId('syntheticsWaterfallHideNonMatching')).toBeInTheDocument(); }); }); }); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_chart_wrapper.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_wrapper.tsx similarity index 68% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_chart_wrapper.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_wrapper.tsx index 724b06167ca3c..cf8715c83e875 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_chart_wrapper.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_chart_wrapper.tsx @@ -7,19 +7,19 @@ import React, { useCallback, useMemo, useState } from 'react'; import { EuiHealth } from '@elastic/eui'; -import { useTrackMetric, METRIC_TYPE } from '@kbn/observability-plugin/public'; -import { JourneyStep } from '../../../../../../../../../common/runtime_types'; -import { getSeriesAndDomain, getSidebarItems, getLegendItems } from './data_formatting'; -import { SidebarItem, LegendItem, NetworkItems } from './types'; -import { WaterfallProvider, WaterfallChart, RenderItem, useFlyout } from '../../waterfall'; -import { WaterfallFilter } from './waterfall_filter'; -import { WaterfallFlyout } from './waterfall_flyout'; +import { JourneyStep, NetworkEvent } from '../../../../../../../common/runtime_types'; +import { getSeriesAndDomain, getSidebarItems } from '../../common/network_data/data_formatting'; +import { SidebarItem, LegendItem } from '../../common/network_data/types'; +import { RenderItem, WaterfallDataEntry } from '../../common/network_data/types'; +import { useFlyout } from './waterfall_flyout/use_flyout'; +import { WaterfallFlyout } from './waterfall_flyout/waterfall_flyout'; import { WaterfallSidebarItem } from './waterfall_sidebar_item'; -import { MarkerItems } from '../../waterfall/context/waterfall_chart'; +import { MarkerItems, WaterfallProvider } from './context/waterfall_context'; +import { WaterfallChart } from './waterfall_chart'; export const renderLegendItem: RenderItem = (item) => { return ( - + {item.name} ); @@ -28,7 +28,7 @@ export const renderLegendItem: RenderItem = (item) => { interface Props { total: number; activeStep?: JourneyStep; - data: NetworkItems; + data: NetworkEvent[]; markerItems?: MarkerItems; } @@ -42,7 +42,7 @@ export const WaterfallChartWrapper: React.FC = ({ const [activeFilters, setActiveFilters] = useState([]); const [onlyHighlighted, setOnlyHighlighted] = useState(false); - const [networkData] = useState(data); + const [networkData] = useState(data); const hasFilters = activeFilters.length > 0; @@ -54,10 +54,6 @@ export const WaterfallChartWrapper: React.FC = ({ return getSidebarItems(networkData, onlyHighlighted, query, activeFilters); }, [networkData, query, activeFilters, onlyHighlighted]); - const legendItems = useMemo(() => { - return getLegendItems(); - }, []); - const { flyoutData, onBarClick, @@ -67,19 +63,6 @@ export const WaterfallChartWrapper: React.FC = ({ onFlyoutClose, } = useFlyout(metadata); - const renderFilter = useCallback(() => { - return ( - - ); - }, [activeFilters, setActiveFilters, onlyHighlighted, setOnlyHighlighted, query, setQuery]); - const renderFlyout = useCallback(() => { return ( = ({ ); }, [flyoutData, isFlyoutVisible, onFlyoutClose]); - const highestSideBarIndex = Math.max(...series.map((sr) => sr.x)); + const highestSideBarIndex = Math.max(...series.map((sr: WaterfallDataEntry) => sr.x)); const renderSidebarItem: RenderItem = useCallback( (item) => { @@ -106,14 +89,6 @@ export const WaterfallChartWrapper: React.FC = ({ [hasFilters, onlyHighlighted, onSidebarClick, highestSideBarIndex] ); - useTrackMetric({ app: 'uptime', metric: 'waterfall_chart_view', metricType: METRIC_TYPE.COUNT }); - useTrackMetric({ - app: 'uptime', - metric: 'waterfall_chart_view', - metricType: METRIC_TYPE.COUNT, - delay: 15000, - }); - return ( = ({ onSidebarClick={onSidebarClick} showOnlyHighlightedNetworkRequests={onlyHighlighted} sidebarItems={sidebarItems} - legendItems={legendItems} metadata={metadata} + activeFilters={activeFilters} + setActiveFilters={setActiveFilters} + setOnlyHighlighted={setOnlyHighlighted} + query={query} + setQuery={setQuery} renderTooltipItem={useCallback((tooltipProps) => { return {tooltipProps?.value}; }, [])} @@ -150,8 +129,6 @@ export const WaterfallChartWrapper: React.FC = ({ renderSidebarItem={renderSidebarItem} renderLegendItem={renderLegendItem} renderFlyout={renderFlyout} - renderFilter={renderFilter} - fullHeight={true} /> ); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/use_flyout.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/use_flyout.test.tsx similarity index 97% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/use_flyout.test.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/use_flyout.test.tsx index 5b388874d508e..584d17e873629 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/use_flyout.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/use_flyout.test.tsx @@ -7,7 +7,7 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { useFlyout } from './use_flyout'; -import { IWaterfallContext } from '../context/waterfall_chart'; +import { IWaterfallContext } from '../context/waterfall_context'; import { ProjectedValues, XYChartElementEvent } from '@elastic/charts'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/use_flyout.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/use_flyout.ts similarity index 96% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/use_flyout.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/use_flyout.ts index 6e1795c4933ec..f17b7f811a050 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/use_flyout.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/use_flyout.ts @@ -14,7 +14,7 @@ import { XYChartElementEvent, } from '@elastic/charts'; -import { WaterfallMetadata, WaterfallMetadataEntry } from '../types'; +import { WaterfallMetadata, WaterfallMetadataEntry } from '../../../common/network_data/types'; interface OnSidebarClickParams { buttonRef?: ButtonRef; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_flyout.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/waterfall_flyout.test.tsx similarity index 96% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_flyout.test.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/waterfall_flyout.test.tsx index 278ac92bd915b..6e91c47922170 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_flyout.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/waterfall_flyout.test.tsx @@ -13,8 +13,8 @@ import { REQUEST_HEADERS, RESPONSE_HEADERS, } from './waterfall_flyout'; -import { WaterfallMetadataEntry } from '../../waterfall/types'; -import { render } from '../../../../../../utils/testing'; +import { WaterfallMetadataEntry } from '../../../common/network_data/types'; +import { render } from '../../../../../utils/testing'; describe('WaterfallFlyout', () => { const flyoutData: WaterfallMetadataEntry = { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_flyout.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/waterfall_flyout.tsx similarity index 90% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_flyout.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/waterfall_flyout.tsx index 4c78010e9c4e6..2091d02f499d2 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_flyout.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/waterfall_flyout.tsx @@ -7,7 +7,7 @@ import React, { useEffect, useRef } from 'react'; -import styled from 'styled-components'; +import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { EuiFlyout, @@ -19,10 +19,10 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { METRIC_TYPE, useUiTracker } from '@kbn/observability-plugin/public'; -import { Table } from '../../waterfall/components/waterfall_flyout_table'; -import { MiddleTruncatedText } from '../../waterfall'; -import { WaterfallMetadataEntry } from '../../waterfall/types'; -import { OnFlyoutClose } from '../../waterfall/components/use_flyout'; +import { Table } from './waterfall_flyout_table'; +import { MiddleTruncatedText } from '../middle_truncated_text'; +import { WaterfallMetadataEntry } from '../../../common/network_data/types'; +import { OnFlyoutClose } from './use_flyout'; export const DETAILS = i18n.translate('xpack.synthetics.synthetics.waterfall.flyout.details', { defaultMessage: 'Details', @@ -49,7 +49,7 @@ export const RESPONSE_HEADERS = i18n.translate( } ); -const FlyoutContainer = styled(EuiFlyout)` +const FlyoutContainer = euiStyled(EuiFlyout)` z-index: ${(props) => props.theme.eui.euiZLevel5}; `; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_flyout_table.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/waterfall_flyout_table.tsx similarity index 93% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_flyout_table.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/waterfall_flyout_table.tsx index 8f723eb92fd94..92714aa148174 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_flyout_table.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_flyout/waterfall_flyout_table.tsx @@ -6,7 +6,7 @@ */ import React, { useMemo } from 'react'; -import styled from 'styled-components'; +import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { EuiText, EuiBasicTable, EuiSpacer } from '@elastic/eui'; @@ -20,7 +20,7 @@ interface Props { title: string; } -const StyledText = styled(EuiText)` +const StyledText = euiStyled(EuiText)` width: 100%; `; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/network_requests_total.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/network_requests_total.test.tsx new file mode 100644 index 0000000000000..ac77db5537ff5 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/network_requests_total.test.tsx @@ -0,0 +1,40 @@ +/* + * 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 { NetworkRequestsTotal } from './network_requests_total'; +import { render } from '../../../../../utils/testing'; + +describe('NetworkRequestsTotal', () => { + it('message in case total is greater than fetched', () => { + const { getByTestId, getByText } = render( + + ); + + expect(getByText('Info')).toBeInTheDocument(); + expect(getByTestId('syntheticsWaterfallChartCountShown')).toHaveTextContent('1,000'); + expect(getByText(/of 1,100/i)).toBeInTheDocument(); + }); + + it('message in case total is equal to fetched requests', () => { + const { getByTestId, queryByText } = render( + + ); + + expect(queryByText('Info')).not.toBeInTheDocument(); + expect(getByTestId('syntheticsWaterfallChartCountShown')).toHaveTextContent('500'); + expect(queryByText(/of 500/i)).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/network_requests_total.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/network_requests_total.tsx new file mode 100644 index 0000000000000..3c09a4c5dce21 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/network_requests_total.tsx @@ -0,0 +1,64 @@ +/* + * 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 { FormattedMessage } from '@kbn/i18n-react'; +import { i18n } from '@kbn/i18n'; +import { EuiI18nNumber, EuiIconTip, EuiFlexGroup, EuiText } from '@elastic/eui'; + +interface Props { + totalNetworkRequests: number; + fetchedNetworkRequests: number; + highlightedNetworkRequests: number; +} + +export const NetworkRequestsTotal = ({ + totalNetworkRequests, + fetchedNetworkRequests, + highlightedNetworkRequests, +}: Props) => { + return ( + + + + + + ), + total: , + networkRequestsLabel: ( + + {i18n.translate('xpack.synthetics.waterfall.networkRequests.pluralizedCount', { + defaultMessage: '{total, plural, one {network request} other {network requests}}', + values: { + total: totalNetworkRequests, + }, + })} + + ), + }} + /> + {totalNetworkRequests > fetchedNetworkRequests && ( + + )} + + + ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_legend.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_legend.test.tsx new file mode 100644 index 0000000000000..8f64e0dc24eb9 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_legend.test.tsx @@ -0,0 +1,110 @@ +/* + * 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, { useState } from 'react'; +import { fireEvent } from '@testing-library/react'; +import 'jest-canvas-mock'; +import { MIME_FILTERS, MimeType } from '../../../common/network_data/types'; +import { WaterfallLegend } from './waterfall_legend'; +import { render } from '../../../../../utils/testing'; + +describe('waterfall_legend', () => { + jest.useFakeTimers(); + const activeFilters = [MimeType.XHR]; + const setActiveFilters = jest.fn(); + const defaultProps = { + activeFilters, + setActiveFilters, + }; + + beforeEach(() => { + jest.resetAllMocks(); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('renders correctly', () => { + const { getByText } = render(); + + MIME_FILTERS.forEach((filter) => { + expect(getByText(filter.label)); + }); + }); + + it('filter icon changes state/appearance on active/inactive filters', () => { + const Component = () => { + const [activeFiltersTest, setActiveFiltersTest] = useState([]); + + return ( + + ); + }; + const { getByText, queryByText } = render(); + + expect(getByText('Select an item to apply filter')); + + const xhrFilterItem = getByText('XHR').closest('[aria-checked]'); + const imageFilterItem = getByText('Image').closest('[aria-checked]'); + fireEvent.click(imageFilterItem); + + expect(imageFilterItem.getAttribute('aria-checked')).toBe('true'); + + // toggle filters + fireEvent.click(xhrFilterItem); + fireEvent.click(imageFilterItem); + + expect(imageFilterItem.getAttribute('aria-checked')).toBe('false'); + + expect(queryByText('Select an item to apply filter')).toBeNull(); + }); + + it('resets all filters on clear filters', () => { + const Component = () => { + const [activeFiltersTest, setActiveFiltersTest] = useState([]); + + return ( + + ); + }; + const { getByText, queryByText, getAllByRole } = render(); + + expect(getByText('Select an item to apply filter')); + + // "Clear filters" should only appear when at least one filter in set + expect(queryByText('Clear filters')).toBeNull(); + + const imageFilterItem = getByText('Image').closest('[aria-checked]'); + fireEvent.click(imageFilterItem); + + // Ensure at least one filter is selected + expect( + getAllByRole('checkbox').some((filter: HTMLDivElement) => filter.getAttribute('aria-checked')) + ).toBeTruthy(); + + expect(getByText('Clear filters')); + + expect(imageFilterItem.getAttribute('aria-checked')).toBe('true'); + + // Clear all filters + fireEvent.click(getByText('Clear filters')); + + // All filters should be checked because no filter means all filters are active + expect( + getAllByRole('checkbox').every((filter: HTMLDivElement) => + filter.getAttribute('aria-checked') + ) + ).toBeTruthy(); + }); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_legend.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_legend.tsx new file mode 100644 index 0000000000000..2eae65a44ff5f --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_legend.tsx @@ -0,0 +1,169 @@ +/* + * 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, { Dispatch, SetStateAction, useState, useCallback, MouseEventHandler } from 'react'; +import { i18n } from '@kbn/i18n'; +import { euiStyled } from '@kbn/kibana-react-plugin/common'; +import { EuiIcon, EuiText, EuiFlexGroup, EuiButtonEmpty, useEuiTheme } from '@elastic/eui'; + +import { + FriendlyTimingLabels, + MIME_FILTERS, + MimeType, + Timings, +} from '../../../common/network_data/types'; +import { colourPalette } from '../../../common/network_data/data_formatting'; + +interface Props { + activeFilters: string[]; + setActiveFilters: Dispatch>; +} + +export const WaterfallLegend = ({ activeFilters, setActiveFilters }: Props) => { + const { euiTheme } = useEuiTheme(); + + const addOrRemoveFilter = useCallback( + (filter: MimeType) => { + setActiveFilters((filters) => { + const updated = filters.includes(filter) + ? filters.filter((f) => f !== filter) + : [...filters, filter]; + return updated.length === MIME_FILTERS.length ? [] : updated; + }); + }, + [setActiveFilters] + ); + + const clearFilters = useCallback(() => { + setActiveFilters([]); + }, [setActiveFilters]); + + const anyFilterApplied = activeFilters.length > 0; + + return ( + <> + + + +

{LEGEND_LABEL}

+
+ {!anyFilterApplied ? ( + + {APPLY_FILTER_LABEL} + + ) : null} + + {anyFilterApplied ? ( + + {CLEAR_FILTER_LABEL} + + ) : null} +
+ + + {MIME_FILTERS.map((f) => ( + + ))} + + +
+ + + {Object.values(Timings) + .filter((t) => t !== Timings.Receive) + .map((t) => ( + + ))} + + + ); +}; + +const LEGEND_LABEL = i18n.translate('xpack.synthetics.waterfall.chartLegend.heading', { + defaultMessage: 'Legend', +}); + +function LegendItem({ + id, + color, + label, + boxSize = 12, + isClickable = false, + isActive = false, + onClick, +}: { + id: T; + color: string; + label: string; + boxSize?: number; + isActive?: boolean; + isClickable?: boolean; + onClick?: (id: T) => void; +}) { + const [isHovered, setIsHovered] = useState(false); + const onMouseEvent: MouseEventHandler = useCallback((evt) => { + setIsHovered(evt?.type === 'mouseenter'); + }, []); + + const isBoxFilled = !isClickable || isActive || isHovered; + const title = isClickable ? CLICK_FILTER_LABEL : undefined; + const ariaLabel = `${label}${isClickable ? ` - ${title}` : ''}`; + + return ( + { + onClick?.(id); + }} + > + + + {label} + + ); +} + +const EuiFlexGroupLegendItem = euiStyled(EuiFlexGroup)` + flex-grow: 0; + flex-shrink: 0; + &:active { + ${({ role }) => (role === 'checkbox' ? 'text-decoration: underline;' : '')} + } +`; + +const APPLY_FILTER_LABEL = i18n.translate('xpack.synthetics.waterfall.applyFilters.label', { + defaultMessage: 'Select an item to apply filter', +}); + +const CLICK_FILTER_LABEL = i18n.translate('xpack.synthetics.waterfall.applyFilters.message', { + defaultMessage: 'Click to add or remove filter', +}); + +const CLEAR_FILTER_LABEL = i18n.translate('xpack.synthetics.waterfall.clearFilters.label', { + defaultMessage: 'Clear filters', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_search.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_search.test.tsx new file mode 100644 index 0000000000000..15629a6df825c --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_search.test.tsx @@ -0,0 +1,58 @@ +/* + * 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 { act, fireEvent } from '@testing-library/react'; +import 'jest-canvas-mock'; +import { WaterfallSearch } from './waterfall_search'; +import { FILTER_REQUESTS_LABEL } from '../translations'; +import { render } from '../../../../../utils/testing'; + +describe('waterfall filter', () => { + jest.useFakeTimers(); + const query = ''; + const setQuery = jest.fn(); + const defaultProps = { + query, + setQuery, + totalNetworkRequests: 10, + highlightedNetworkRequests: 5, + fetchedNetworkRequests: 10, + }; + + beforeEach(() => { + jest.resetAllMocks(); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('renders correctly', () => { + const { getByText } = render(); + + expect(getByText('Network Requests')); + }); + + it('search input is working properly', () => { + const Component = () => { + return ; + }; + const { getByLabelText } = render(); + + const testText = 'js'; + + fireEvent.change(getByLabelText(FILTER_REQUESTS_LABEL), { target: { value: testText } }); + + // input has debounce effect so hence the timer + act(() => { + jest.advanceTimersByTime(300); + }); + + expect(setQuery).toHaveBeenCalledWith(testText); + }); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_search.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_search.tsx new file mode 100644 index 0000000000000..c72b15229aa68 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_search.tsx @@ -0,0 +1,86 @@ +/* + * 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, useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiFieldSearch, EuiFlexGroup, EuiText, useEuiTheme } from '@elastic/eui'; +import useDebounce from 'react-use/lib/useDebounce'; +import { METRIC_TYPE, useUiTracker } from '@kbn/observability-plugin/public'; +import { FILTER_REQUESTS_LABEL, SEARCH_REQUESTS_LABEL } from '../translations'; +import { NetworkRequestsTotal } from './network_requests_total'; + +interface Props { + query: string; + setQuery: (val: string) => void; + totalNetworkRequests: number; + highlightedNetworkRequests: number; + fetchedNetworkRequests: number; +} + +export const WaterfallSearch = ({ + query, + setQuery, + totalNetworkRequests, + highlightedNetworkRequests, + fetchedNetworkRequests, +}: Props) => { + const trackMetric = useUiTracker({ app: 'uptime' }); + + const [value, setValue] = useState(query); + const { euiTheme } = useEuiTheme(); + + useDebounce( + () => { + setQuery(value); + }, + 300, + [value] + ); + + // indicates use of the query input box + useEffect(() => { + if (query) { + trackMetric({ metric: 'waterfall_filter_input_changed', metricType: METRIC_TYPE.CLICK }); + } + }, [query, trackMetric]); + + return ( + + +

{NETWORK_REQUESTS_LABEL}

+
+ + { + setValue(evt.target.value); + }} + value={value} + /> + + +
+ ); +}; + +const NETWORK_REQUESTS_LABEL = i18n.translate( + 'xpack.synthetics.waterfall.networkRequests.heading', + { + defaultMessage: 'Network Requests', + } +); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_tick_axis.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_tick_axis.test.tsx new file mode 100644 index 0000000000000..e3984ba6052c8 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_tick_axis.test.tsx @@ -0,0 +1,50 @@ +/* + * 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 { fireEvent, waitFor } from '@testing-library/react'; + +import { render } from '../../../../../utils/testing'; +import { WaterfallTickAxis } from './waterfall_tick_axis'; + +describe('WaterfallChartWrapper', () => { + const setOnlyHighlightedMock = jest.fn(); + const defaultProps = { + showOnlyHighlightedNetworkRequests: false, + setOnlyHighlighted: setOnlyHighlightedMock, + highlightedNetworkRequests: 10, + fetchedNetworkRequests: 20, + shouldRenderSidebar: true, + barStyleAccessor: ({ datum }: { datum: { config: { colour: string } } }) => ({ + rect: { + fill: datum.config?.colour, + opacity: 0.1, + }, + }), + domain: { min: 0, max: 1 }, + tickFormat: (d: number) => `${Number(d).toFixed(0)} ms`, + }; + + it('renders correctly', () => { + const { getByTestId } = render(); + + expect(getByTestId('syntheticsWaterfallHideNonMatching')).toBeInTheDocument(); + }); + + it('updates "Hide nonmatching" status', () => { + const { getByTestId } = render(); + + fireEvent.click(getByTestId('syntheticsWaterfallHideNonMatching')); + expect(setOnlyHighlightedMock).toHaveBeenCalledWith(true); + + fireEvent.click(getByTestId('syntheticsWaterfallHideNonMatching')); + + waitFor(() => { + expect(setOnlyHighlightedMock).toHaveBeenCalledWith(false); + }); + }); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_tick_axis.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_tick_axis.tsx new file mode 100644 index 0000000000000..4c57eb3f4f9bb --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_header/waterfall_tick_axis.tsx @@ -0,0 +1,98 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { BarStyleAccessor, DomainRange, TickFormatter } from '@elastic/charts'; +import { EuiFlexGroup, EuiFlexItem, EuiSwitch, EuiText, useEuiTheme } from '@elastic/eui'; + +import { MAIN_GROW_SIZE, SIDEBAR_GROW_SIZE } from '../constants'; +import { WaterfallChartSidebarWrapper, WaterfallChartTimeTicksContainer } from '../styles'; +import { WaterfallChartFixedAxis } from '../waterfall_chart_fixed_axis'; + +interface Props { + showOnlyHighlightedNetworkRequests: boolean; + setOnlyHighlighted: (val: boolean) => void; + highlightedNetworkRequests: number; + fetchedNetworkRequests: number; + shouldRenderSidebar: boolean; + barStyleAccessor: BarStyleAccessor; + domain: DomainRange; + tickFormat: TickFormatter; +} + +export const WaterfallTickAxis = ({ + showOnlyHighlightedNetworkRequests, + setOnlyHighlighted, + highlightedNetworkRequests, + fetchedNetworkRequests, + shouldRenderSidebar, + barStyleAccessor, + domain, + tickFormat, +}: Props) => { + const { euiTheme } = useEuiTheme(); + + return ( + + + + + {shouldRenderSidebar && ( + + {highlightedNetworkRequests < fetchedNetworkRequests ? ( + + + + } + checked={showOnlyHighlightedNetworkRequests} + onChange={(e) => { + setOnlyHighlighted(e.target.checked); + }} + /> + ) : null} + + )} + + + + + + + + ); +}; + +const FILTER_COLLAPSE_REQUESTS_LABEL = i18n.translate( + 'xpack.synthetics.pingList.synthetics.waterfall.filters.collapseRequestsLabel', + { + defaultMessage: 'Collapse to only show matching requests', + } +); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_icon.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_icon.test.tsx similarity index 96% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_icon.test.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_icon.test.tsx index 222f152c01b1b..3ebbb2b1c6b57 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_icon.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_icon.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { fireEvent, waitFor } from '@testing-library/dom'; import { WaterfallMarkerIcon } from './waterfall_marker_icon'; import { TestWrapper } from './waterfall_marker_test_helper'; -import { render } from '../../../../../../utils/testing'; +import { render } from '../../../../../utils/testing'; describe('', () => { it('renders a dot icon when `field` is an empty string', () => { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_icon.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_icon.tsx similarity index 86% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_icon.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_icon.tsx index 675224bfa8f79..99a677e50d79a 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_icon.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_icon.tsx @@ -7,11 +7,12 @@ import React, { useState } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiButtonIcon, EuiIcon, EuiPopover } from '@elastic/eui'; +import { EuiButtonIcon, EuiIcon, EuiPopover, useEuiTheme } from '@elastic/eui'; import { WaterfallMarkerTrend } from './waterfall_marker_trend'; export function WaterfallMarkerIcon({ field, label }: { field: string; label: string }) { const [isOpen, setIsOpen] = useState(false); + const { euiTheme } = useEuiTheme(); if (!field) { return ( @@ -20,7 +21,7 @@ export function WaterfallMarkerIcon({ field, label }: { field: string; label: st defaultMessage: 'An icon indicating that this marker has no field associated with it', })} type="dot" - size="l" + size="m" /> ); } @@ -32,8 +33,10 @@ export function WaterfallMarkerIcon({ field, label }: { field: string; label: st anchorPosition="downLeft" panelStyle={{ paddingBottom: 0, paddingLeft: 4 }} zIndex={100} + css={{ top: 4 }} button={ setIsOpen((prevState) => !prevState)} /> } diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_test_helper.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_test_helper.tsx similarity index 90% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_test_helper.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_test_helper.tsx index ce033b6f2ef2b..65df8f8e5a69f 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_test_helper.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_test_helper.tsx @@ -6,9 +6,9 @@ */ import React from 'react'; -import { SyntheticsStartupPluginsContext } from '../../../../../../contexts'; -import { JourneyStep } from '../../../../../../../../../common/runtime_types'; -import { WaterfallContext } from '../context/waterfall_chart'; +import { SyntheticsStartupPluginsContext } from '../../../../../contexts'; +import { JourneyStep } from '../../../../../../../../common/runtime_types'; +import { WaterfallContext } from '../context/waterfall_context'; const EmbeddableMock = ({ title, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_trend.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_trend.test.tsx similarity index 96% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_trend.test.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_trend.test.tsx index f75b25b056e0d..b44dd47c8023b 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_trend.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_trend.test.tsx @@ -9,8 +9,8 @@ import React from 'react'; import { WaterfallMarkerTrend } from './waterfall_marker_trend'; import moment from 'moment'; import { TestWrapper } from './waterfall_marker_test_helper'; -import { render } from '../../../../../../utils/testing'; -import { JourneyStep } from '../../../../../../../../../common/runtime_types'; +import { render } from '../../../../../utils/testing'; +import { JourneyStep } from '../../../../../../../../common/runtime_types'; describe('', () => { const mockDiff = jest.fn(); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_trend.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_trend.tsx similarity index 77% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_trend.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_trend.tsx index 5ab0196701083..5d05a8ce31fcc 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_marker_trend.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_trend.tsx @@ -6,8 +6,8 @@ */ import React from 'react'; -import { StepFieldTrend } from '../../../../../common/step_field_trend/step_field_trend'; -import { useWaterfallContext } from '../context/waterfall_chart'; +import { StepFieldTrend } from '../../../../common/step_field_trend/step_field_trend'; +import { useWaterfallContext } from '../context/waterfall_context'; export function WaterfallMarkerTrend({ title, field }: { title: string; field: string }) { const { activeStep } = useWaterfallContext(); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_markers.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_markers.tsx similarity index 71% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_markers.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_markers.tsx index 1a8e5dd1d51b4..e2337746cbcd0 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_markers.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_markers.tsx @@ -10,8 +10,8 @@ import { AnnotationDomainType, LineAnnotation } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; import { useTheme } from '@kbn/observability-plugin/public'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; -import { useWaterfallContext } from '..'; -import { MarkerItems } from '../context/waterfall_chart'; + +import { MarkerItems, useWaterfallContext } from '../context/waterfall_context'; import { WaterfallMarkerIcon } from './waterfall_marker_icon'; export const FIELD_SYNTHETICS_LCP = 'browser.experience.lcp.us'; @@ -21,9 +21,8 @@ export const FIELD_SYNTHETICS_DCL = 'browser.experience.dcl.us'; export const LAYOUT_SHIFT = 'layoutShift'; export function WaterfallChartMarkers() { - const { markerItems } = useWaterfallContext(); - const theme = useTheme(); + const { markerItems } = useWaterfallContext(); const markerItemsByOffset = useMemo( () => @@ -35,16 +34,36 @@ export function WaterfallChartMarkers() { ); const annotations = useMemo(() => { - return Array.from(markerItemsByOffset.entries()).map(([offset, items]) => { - let uniqueIds = (items ?? []) + let lastOffset: number; + const recognizedMarkerItemsByOffset = Array.from(markerItemsByOffset.entries()).reduce( + (acc, [offset, items]) => { + // Remove unrecognized marks e.g. custom marks + const vitalMarkers = items.filter(({ id }) => getMarkersInfo(id, theme) !== undefined); + + const hasMultipleMarksAtOffset = vitalMarkers.some(({ id }) => id !== LAYOUT_SHIFT); + const isLastOffsetTooClose = lastOffset && Math.abs(offset - lastOffset) < 100; // 100ms + + // If offsets coincide or are too close, remove less important marks e.g. Layout Shift + const filteredItems = + hasMultipleMarksAtOffset || isLastOffsetTooClose + ? vitalMarkers.filter(({ id }) => id !== LAYOUT_SHIFT) + : vitalMarkers; + + if (filteredItems.length) { + acc.set(offset, filteredItems); + } + + lastOffset = offset; + return acc; + }, + new Map() + ); + + return Array.from(recognizedMarkerItemsByOffset.entries()).map(([offset, items]) => { + const uniqueIds = (items ?? []) .map(({ id }) => id) .filter((id, index, arr) => arr.indexOf(id) === index); - // Omit coinciding layoutShift's with other vital marks - if (uniqueIds.length > 1) { - uniqueIds = uniqueIds.filter((id) => id !== LAYOUT_SHIFT); - } - const label = uniqueIds.map((id) => getMarkersInfo(id, theme)?.label ?? id).join(' / '); const id = uniqueIds[0]; const markersInfo = getMarkersInfo(id, theme); @@ -56,6 +75,7 @@ export function WaterfallChartMarkers() { field: markersInfo?.field ?? '', color: markersInfo?.color ?? theme.eui.euiColorMediumShade, strokeWidth: markersInfo?.strokeWidth ?? 1, + dash: markersInfo?.dash, }; }); }, [markerItemsByOffset, theme]); @@ -66,7 +86,7 @@ export function WaterfallChartMarkers() { return ( - {annotations.map(({ id, offset, label, field, color, strokeWidth }) => { + {annotations.map(({ id, offset, label, field, color, strokeWidth, dash }) => { const key = `${id}-${offset}`; return ( @@ -90,8 +110,10 @@ export function WaterfallChartMarkers() { strokeWidth, stroke: color, opacity: 1, + dash, }, }} + zIndex={theme.eui.euiZLevel0} /> ); })} @@ -104,37 +126,42 @@ function getMarkersInfo(id: string, theme: ReturnType) { case 'domContentLoaded': return { label: DOCUMENT_CONTENT_LOADED_LABEL, - color: theme.eui.euiColorVis0, + color: theme.eui.euiColorMediumShade, field: FIELD_SYNTHETICS_DCL, - strokeWidth: 2, + strokeWidth: 1, + dash: undefined, }; case 'firstContentfulPaint': return { label: FCP_LABEL, - color: theme.eui.euiColorVis1, + color: theme.eui.euiColorMediumShade, field: FIELD_SYNTHETICS_FCP, - strokeWidth: 2, + strokeWidth: 1, + dash: undefined, }; case 'largestContentfulPaint': return { label: LCP_LABEL, - color: theme.eui.euiColorVis2, + color: theme.eui.euiColorMediumShade, field: FIELD_SYNTHETICS_LCP, - strokeWidth: 2, + strokeWidth: 1, + dash: undefined, }; case 'layoutShift': return { label: LAYOUT_SHIFT_LABEL, - color: theme.eui.euiColorVis6, + color: theme.eui.euiColorMediumShade, field: '', strokeWidth: 1, + dash: [5, 5], }; case 'loadEvent': return { label: LOAD_EVENT_LABEL, - color: theme.eui.euiColorVis9, + color: theme.eui.euiColorMediumShade, field: FIELD_SYNTHETICS_DOCUMENT_ONLOAD, - strokeWidth: 2, + strokeWidth: 1, + dash: undefined, }; } diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_sidebar_item.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_sidebar_item.test.tsx similarity index 86% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_sidebar_item.test.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_sidebar_item.test.tsx index c9fbcd2244252..786978e3647a7 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_sidebar_item.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_sidebar_item.test.tsx @@ -9,11 +9,11 @@ import React from 'react'; import 'jest-canvas-mock'; import { fireEvent } from '@testing-library/react'; -import { SidebarItem } from './types'; +import { SidebarItem } from '../../common/network_data/types'; import { WaterfallSidebarItem } from './waterfall_sidebar_item'; -import { SIDEBAR_FILTER_MATCHES_SCREENREADER_LABEL } from '../../waterfall/components/translations'; -import { getChunks } from '../../waterfall/components/middle_truncated_text'; -import { render } from '../../../../../../utils/testing'; +import { SIDEBAR_FILTER_MATCHES_SCREENREADER_LABEL } from './translations'; +import { getChunks } from './middle_truncated_text'; +import { render } from '../../../../utils/testing'; describe('waterfall filter', () => { const url = 'http://www.elastic.co/observability/uptime'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_sidebar_item.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_sidebar_item.tsx similarity index 88% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_sidebar_item.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_sidebar_item.tsx index 193fe33121636..cff7853b2bcd6 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/step_detail/waterfall/waterfall_sidebar_item.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_sidebar_item.tsx @@ -7,11 +7,11 @@ import React, { RefObject, useMemo, useCallback, useState } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiBadge } from '@elastic/eui'; -import { SidebarItem } from './types'; -import { MiddleTruncatedText } from '../../waterfall'; -import { SideBarItemHighlighter } from '../../waterfall/components/styles'; -import { SIDEBAR_FILTER_MATCHES_SCREENREADER_LABEL } from '../../waterfall/components/translations'; -import { OnSidebarClick } from '../../waterfall/components/use_flyout'; +import { SidebarItem } from '../../common/network_data/types'; +import { MiddleTruncatedText } from './middle_truncated_text'; +import { SideBarItemHighlighter } from './styles'; +import { SIDEBAR_FILTER_MATCHES_SCREENREADER_LABEL } from './translations'; +import { OnSidebarClick } from './waterfall_flyout/use_flyout'; interface SidebarItemProps { item: SidebarItem; @@ -54,7 +54,7 @@ export const WaterfallSidebarItem = ({ return ( {!status || !isErrorStatusCode(status) ? ( diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_tooltip_content.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_tooltip_content.test.tsx similarity index 95% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_tooltip_content.test.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_tooltip_content.test.tsx index 0df81cca48df3..9cd85c0b32281 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_tooltip_content.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_tooltip_content.test.tsx @@ -7,9 +7,9 @@ import React from 'react'; import { WaterfallTooltipContent } from './waterfall_tooltip_content'; -import { render } from '../../../../../../utils/testing'; +import { render } from '../../../../utils/testing'; -jest.mock('../context/waterfall_chart', () => ({ +jest.mock('./context/waterfall_context', () => ({ useWaterfallContext: jest.fn().mockReturnValue({ data: [ { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_tooltip_content.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_tooltip_content.tsx similarity index 95% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_tooltip_content.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_tooltip_content.tsx index b9f385c29b9f8..23ad238a71864 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/components/network_waterfall/waterfall/components/waterfall_tooltip_content.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_tooltip_content.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiText } from '@elastic/eui'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; -import { useWaterfallContext } from '../context/waterfall_chart'; +import { useWaterfallContext } from './context/waterfall_context'; interface Props { text: string; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/components/step_details.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/components/step_details.tsx new file mode 100644 index 0000000000000..79a6c3d9081bc --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/components/step_details.tsx @@ -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 { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React from 'react'; +import { JourneyStep, SyntheticsJourneyApiResponse } from '../../../../../../common/runtime_types'; +import { StepNumberNav } from './step_number_nav'; +import { StepScreenshotDetails } from '../step_screenshot_details'; +import { StepTabs } from '../step_tabs'; + +export const StepDetails = ({ + step, + loading, + stepIndex, + stepsData, + totalSteps, + setStepIndex, +}: { + loading: boolean; + step?: JourneyStep; + stepsData: SyntheticsJourneyApiResponse; + stepIndex: number; + totalSteps: number; + setStepIndex: (stepIndex: number) => void; +}) => { + return ( + + + + +

+ +

+
+
+ + { + setStepIndex(stepIndex + 1); + }} + handlePreviousStep={() => { + setStepIndex(stepIndex - 1); + }} + /> + +
+ + + + +
+ ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/hooks/use_test_run_details_breadcrumbs.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/hooks/use_test_run_details_breadcrumbs.ts index 7e16b8c190de8..ea2d3475a4781 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/hooks/use_test_run_details_breadcrumbs.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/hooks/use_test_run_details_breadcrumbs.ts @@ -6,6 +6,7 @@ */ import { i18n } from '@kbn/i18n'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useSelectedLocation } from '../../monitor_details/hooks/use_selected_location'; import { useSelectedMonitor } from '../../monitor_details/hooks/use_selected_monitor'; import { useBreadcrumbs } from '../../../hooks/use_breadcrumbs'; import { ConfigKey } from '../../../../../../common/runtime_types'; @@ -19,6 +20,7 @@ export const useTestRunDetailsBreadcrumbs = ( const appPath = kibana.services.application?.getUrlForApp(PLUGIN.SYNTHETICS_PLUGIN_ID) ?? ''; const { monitor } = useSelectedMonitor(); + const selectedLocation = useSelectedLocation(); useBreadcrumbs([ { @@ -30,7 +32,7 @@ export const useTestRunDetailsBreadcrumbs = ( href: `${appPath}${MONITOR_ROUTE.replace( ':monitorId', monitor?.[ConfigKey.CONFIG_ID] ?? '' - )}`, + )}?locationId=${selectedLocation?.id ?? ''}`, }, ...(extraCrumbs ?? []), ]); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/step_screenshot_details.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/step_screenshot_details.tsx index 5219fef84d2a9..c416d71168af1 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/step_screenshot_details.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/step_screenshot_details.tsx @@ -32,7 +32,7 @@ export const StepScreenshotDetails = ({ ); case 'console': + return ( + + {getBrowserConsoles(1)?.join('\n')} + + ); + case 'stackTrace': return ( {step?.synthetics?.error?.stack} @@ -91,7 +97,7 @@ export const StepTabs = ({ default: return ( - {getBrowserConsoles(1)?.join('\n')} + {step?.synthetics?.payload?.source} ); } diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/test_run_details.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/test_run_details.tsx index e95794194bcfa..ebf6bb6913e4d 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/test_run_details.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/test_run_details.tsx @@ -6,17 +6,14 @@ */ import React from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import moment from 'moment'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { StepNumberNav } from './components/step_number_nav'; -import { StepScreenshotDetails } from './step_screenshot_details'; -import { StepTabs } from './step_tabs'; import { MonitorDetailsPanel } from '../monitor_details/monitor_summary/monitor_details_panel'; import { useJourneySteps } from '../monitor_details/hooks/use_journey_steps'; import { StepDurationPanel } from '../monitor_details/monitor_summary/step_duration_panel'; import { TestRunSteps } from './test_run_steps'; import { useTestRunDetailsBreadcrumbs } from './hooks/use_test_run_details_breadcrumbs'; +import { StepDetails } from './components/step_details'; export const TestRunDetails = () => { // Step index from starts at 1 in synthetics @@ -35,40 +32,14 @@ export const TestRunDetails = () => { return ( - - - - -

- -

-
-
- - { - setStepIndex(stepIndex + 1); - }} - handlePreviousStep={() => { - setStepIndex(stepIndex - 1); - }} - /> - -
- - - - -
+
diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_redux_es_search.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_redux_es_search.ts new file mode 100644 index 0000000000000..72715c596e82a --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_redux_es_search.ts @@ -0,0 +1,54 @@ +/* + * 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 type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { ESSearchResponse } from '@kbn/es-types'; +import { IInspectorInfo } from '@kbn/data-plugin/common'; +import { useInspectorContext } from '@kbn/observability-plugin/public'; +import { useDispatch, useSelector } from 'react-redux'; +import { useEffect, useMemo } from 'react'; +import { + executeEsQueryAction, + selectEsQueryLoading, + selectEsQueryResult, +} from '../state/elasticsearch'; + +export const useReduxEsSearch = < + DocumentSource extends unknown, + TParams extends estypes.SearchRequest +>( + params: TParams, + fnDeps: any[], + options: { inspector?: IInspectorInfo; name: string } +) => { + const { name } = options ?? {}; + + const { addInspectorRequest } = useInspectorContext(); + + const dispatch = useDispatch(); + + const loadings = useSelector(selectEsQueryLoading); + const results = useSelector(selectEsQueryResult); + + useEffect(() => { + if (params.index) { + dispatch(executeEsQueryAction.get({ params, name, addInspectorRequest })); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [addInspectorRequest, dispatch, name, JSON.stringify(params)]); + + return useMemo(() => { + return { + data: results[name] as ESSearchResponse, + loading: loadings[name], + }; + }, [loadings, name, results]); +}; + +export function createEsParams(params: T): T { + return params; +} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx index 7f10a3598dbf2..9d938e4ce6b37 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx @@ -18,7 +18,6 @@ import { useInspectorContext } from '@kbn/observability-plugin/public'; import type { LazyObservabilityPageTemplateProps } from '@kbn/observability-plugin/public'; import { getSettingsRouteConfig } from './components/settings/route_config'; import { TestRunDetails } from './components/test_run_details/test_run_details'; -import { ErrorDetailsPage } from './components/error_details/error_details_page'; import { StepTitle } from './components/step_details_page/step_title'; import { MonitorAddPageWithServiceAllowed } from './components/monitor_add_edit/monitor_add_page'; import { MonitorEditPageWithServiceAllowed } from './components/monitor_add_edit/monitor_edit_page'; @@ -42,7 +41,6 @@ import { MONITOR_ERRORS_ROUTE, MONITOR_HISTORY_ROUTE, MONITOR_ROUTE, - ERROR_DETAILS_ROUTE, STEP_DETAIL_ROUTE, OVERVIEW_ROUTE, TEST_RUN_DETAILS_ROUTE, @@ -58,6 +56,7 @@ import { MonitorSummary } from './components/monitor_details/monitor_summary/mon import { MonitorHistory } from './components/monitor_details/monitor_history/monitor_history'; import { MonitorErrors } from './components/monitor_details/monitor_errors/monitor_errors'; import { StepDetailPage } from './components/step_details_page/step_detail_page'; +import { getErrorDetailsRouteConfig } from './components/error_details/route_config'; export type RouteProps = LazyObservabilityPageTemplateProps & { path: string; @@ -84,6 +83,7 @@ const getRoutes = ( ): RouteProps[] => { return [ ...getSettingsRouteConfig(history, syntheticsPath, baseTitle), + getErrorDetailsRouteConfig(history, syntheticsPath, baseTitle), { title: i18n.translate('xpack.synthetics.gettingStartedRoute.title', { defaultMessage: 'Synthetics Getting Started | {baseTitle}', @@ -285,23 +285,6 @@ const getRoutes = ( ], }, }, - { - title: i18n.translate('xpack.synthetics.errorDetailsRoute.title', { - defaultMessage: 'Error details | {baseTitle}', - values: { baseTitle }, - }), - path: ERROR_DETAILS_ROUTE, - component: ErrorDetailsPage, - dataTestSubj: 'syntheticsMonitorEditPage', - pageHeader: { - pageTitle: ( - - ), - }, - }, { title: i18n.translate('xpack.synthetics.testRunDetailsRoute.title', { defaultMessage: 'Test run details | {baseTitle}', diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/actions.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/actions.ts new file mode 100644 index 0000000000000..fbf505ecc950d --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/actions.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 * as esTypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { ESSearchResponse } from '@kbn/es-types'; +import { FetcherResult } from '@kbn/observability-plugin/public/hooks/use_fetcher'; +import { createAsyncAction } from '../utils/actions'; + +export const executeEsQueryAction = createAsyncAction< + { + params: esTypes.SearchRequest; + name: string; + addInspectorRequest: (result: FetcherResult) => void; + }, + { name: string; result: ESSearchResponse } +>('executeEsQueryAction'); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/api.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/api.ts new file mode 100644 index 0000000000000..6f233b89423b2 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/api.ts @@ -0,0 +1,107 @@ +/* + * 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 { + IKibanaSearchResponse, + isCompleteResponse, + isErrorResponse, +} from '@kbn/data-plugin/common'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { ESSearchResponse } from '@kbn/es-types'; +import { FETCH_STATUS } from '@kbn/observability-plugin/public'; +import { getInspectResponse } from '@kbn/observability-plugin/common'; +import type { FetcherResult } from '@kbn/observability-plugin/public/hooks/use_fetcher'; +import { kibanaService } from '../../../../utils/kibana_service'; + +export const executeEsQueryAPI = async ({ + params, + name, + addInspectorRequest, +}: { + params: estypes.SearchRequest; + name: string; + addInspectorRequest: (result: FetcherResult) => void; +}) => { + const data = kibanaService.startPlugins.data; + + const response = new Promise((resolve, reject) => { + const startTime = Date.now(); + + const search$ = data.search + .search( + { + params, + }, + {} + ) + .subscribe({ + next: (result) => { + if (isCompleteResponse(result)) { + if (addInspectorRequest) { + addInspectorRequest({ + data: { + _inspect: [ + getInspectResponse({ + startTime, + esRequestParams: params, + esResponse: result.rawResponse, + esError: null, + esRequestStatus: 1, + operationName: name, + kibanaRequest: { + route: { + path: '/internal/bsearch', + method: 'POST', + }, + } as any, + }), + ], + }, + status: FETCH_STATUS.SUCCESS, + }); + } + // Final result + resolve(result); + search$.unsubscribe(); + } + }, + error: (err) => { + if (isErrorResponse(err)) { + // eslint-disable-next-line no-console + console.error(err); + reject(err); + if (addInspectorRequest) { + addInspectorRequest({ + data: { + _inspect: [ + getInspectResponse({ + startTime, + esRequestParams: params, + esResponse: null, + esError: { originalError: err, name: err.name, message: err.message }, + esRequestStatus: 2, + operationName: name, + kibanaRequest: { + route: { + path: '/internal/bsearch', + method: 'POST', + }, + } as any, + }), + ], + }, + status: FETCH_STATUS.SUCCESS, + }); + } + } + }, + }); + }); + + const { rawResponse } = await response; + return { result: rawResponse as ESSearchResponse, name }; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/effects.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/effects.ts new file mode 100644 index 0000000000000..d92285e537dc6 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/effects.ts @@ -0,0 +1,19 @@ +/* + * 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 { takeLeading } from 'redux-saga/effects'; + +import { fetchEffectFactory } from '../utils/fetch_effect'; +import { executeEsQueryAction } from './actions'; +import { executeEsQueryAPI } from './api'; + +export function* executeEsQueryEffect() { + yield takeLeading( + executeEsQueryAction.get, + fetchEffectFactory(executeEsQueryAPI, executeEsQueryAction.success, executeEsQueryAction.fail) + ); +} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/index.ts new file mode 100644 index 0000000000000..1fbb4e352715b --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/index.ts @@ -0,0 +1,46 @@ +/* + * 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 { createReducer } from '@reduxjs/toolkit'; +import { ESSearchResponse } from '@kbn/es-types'; + +import { IHttpSerializedFetchError } from '..'; +import { executeEsQueryAction } from './actions'; + +export interface QueriesState { + results: Record; + loading: Record; + error: Record; +} + +const initialState: QueriesState = { + results: {}, + loading: {}, + error: {}, +}; + +export const elasticsearchReducer = createReducer(initialState, (builder) => { + builder + .addCase(executeEsQueryAction.get, (state, action) => { + const name = action.payload.name; + state.loading = { ...state.loading, [name]: true }; + }) + .addCase(executeEsQueryAction.success, (state, action) => { + const name = action.payload.name; + state.loading = { ...state.loading, [name]: false }; + state.results = { ...state.results, [name]: action.payload.result }; + }) + .addCase(executeEsQueryAction.fail, (state, action) => { + const name = action.payload.name; + state.loading = { ...state.loading, [name]: false }; + state.error = { ...state.error, [name]: action.payload }; + }); +}); + +export * from './actions'; +export * from './effects'; +export * from './selectors'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/selectors.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/selectors.ts new file mode 100644 index 0000000000000..b978908edc305 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/selectors.ts @@ -0,0 +1,17 @@ +/* + * 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 type { SyntheticsAppState } from '../root_reducer'; + +export const selectEsQueryLoading = (queryState: SyntheticsAppState) => + queryState.elasticsearch.loading; + +export const selectEsQueryResult = (queryState: SyntheticsAppState) => + queryState.elasticsearch.results; + +export const selectEsQueryError = (queryState: SyntheticsAppState) => + queryState.elasticsearch.error; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts index 943fa677367cd..f447f56c4aa63 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts @@ -7,6 +7,7 @@ import { all, fork } from 'redux-saga/effects'; import { enableDefaultAlertingEffect, updateDefaultAlertingEffect } from './alert_rules/effects'; +import { executeEsQueryEffect } from './elasticsearch'; import { fetchAlertConnectorsEffect, fetchDynamicSettingsEffect, @@ -50,5 +51,6 @@ export const rootEffect = function* root(): Generator { fork(enableDefaultAlertingEffect), fork(enableMonitorAlertEffect), fork(updateDefaultAlertingEffect), + fork(executeEsQueryEffect), ]); }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/root_reducer.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/root_reducer.ts index 72c6d693149dc..cc32d2d709dc6 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/root_reducer.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/root_reducer.ts @@ -9,8 +9,13 @@ import { combineReducers } from '@reduxjs/toolkit'; import { browserJourneyReducer } from './browser_journey'; import { defaultAlertingReducer, DefaultAlertingState } from './alert_rules'; -import { dynamicSettingsReducer, DynamicSettingsState, settingsReducer } from './settings'; -import { SettingsState } from './settings'; +import { + dynamicSettingsReducer, + DynamicSettingsState, + settingsReducer, + SettingsState, +} from './settings'; +import { elasticsearchReducer, QueriesState } from './elasticsearch'; import { agentPoliciesReducer, AgentPoliciesState } from './private_locations'; import { networkEventsReducer, NetworkEventsState } from './network_events'; import { monitorDetailsReducer, MonitorDetailsState } from './monitor_details'; @@ -27,6 +32,7 @@ export interface SyntheticsAppState { ui: UiState; settings: SettingsState; pingStatus: PingStatusState; + elasticsearch: QueriesState; monitorList: MonitorListState; indexStatus: IndexStatusState; overview: MonitorOverviewState; @@ -34,9 +40,9 @@ export interface SyntheticsAppState { agentPolicies: AgentPoliciesState; monitorDetails: MonitorDetailsState; browserJourney: BrowserJourneyState; - serviceLocations: ServiceLocationsState; dynamicSettings: DynamicSettingsState; defaultAlerting: DefaultAlertingState; + serviceLocations: ServiceLocationsState; syntheticsEnablement: SyntheticsEnablementState; } @@ -48,6 +54,7 @@ export const rootReducer = combineReducers({ indexStatus: indexStatusReducer, overview: monitorOverviewReducer, networkEvents: networkEventsReducer, + elasticsearch: elasticsearchReducer, agentPolicies: agentPoliciesReducer, monitorDetails: monitorDetailsReducer, browserJourney: browserJourneyReducer, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx index b70342e03dee4..a5846f7a4eda8 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx @@ -63,6 +63,7 @@ const Application = (props: SyntheticsAppProps) => { }, [canSave, renderGlobalHelpControls, setBadge]); kibanaService.core = core; + kibanaService.startPlugins = startPlugins; kibanaService.theme = props.appMountParameters.theme$; store.dispatch(setBasePath(basePath)); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.ts index ce9be57fe313d..511dc0b0c9b99 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.ts @@ -6,6 +6,7 @@ */ import moment from 'moment'; +import { useKibanaDateFormat } from '../../../../hooks/use_kibana_date_format'; /** * Formats the microseconds (µ) into either milliseconds (ms) or seconds (s) based on the duration value @@ -34,3 +35,11 @@ export function formatTestRunAt(timestamp: string, format: string) { const stampedMoment = moment(timestamp); return stampedMoment.format(format); } + +export function useFormatTestRunAt(timestamp?: string) { + const format = useKibanaDateFormat(); + if (!timestamp) { + return ''; + } + return formatTestRunAt(timestamp, format); +} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_store.mock.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_store.mock.ts index ca65c80a97cb3..8e0aa77e55f00 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_store.mock.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_store.mock.ts @@ -129,6 +129,11 @@ export const mockState: SyntheticsAppState = { error: null, success: null, }, + elasticsearch: { + results: {}, + loading: {}, + error: {}, + }, }; function getBrowserJourneyMockSlice() { diff --git a/x-pack/plugins/synthetics/public/plugin.ts b/x-pack/plugins/synthetics/public/plugin.ts index ef8be0a72b316..e82daf4bd7813 100644 --- a/x-pack/plugins/synthetics/public/plugin.ts +++ b/x-pack/plugins/synthetics/public/plugin.ts @@ -273,7 +273,7 @@ function registerSyntheticsRoutesWithNavigation( }), app: 'synthetics', path: OVERVIEW_ROUTE, - matchFullPath: true, + matchFullPath: false, ignoreTrailingSlash: true, }, ], diff --git a/x-pack/plugins/synthetics/public/utils/kibana_service/kibana_service.ts b/x-pack/plugins/synthetics/public/utils/kibana_service/kibana_service.ts index 06fa2b892b4a0..021d8c7ec3d7d 100644 --- a/x-pack/plugins/synthetics/public/utils/kibana_service/kibana_service.ts +++ b/x-pack/plugins/synthetics/public/utils/kibana_service/kibana_service.ts @@ -7,11 +7,13 @@ import type { Observable } from 'rxjs'; import type { CoreStart, CoreTheme } from '@kbn/core/public'; +import { ClientPluginsStart } from '../../plugin'; import { apiService } from '../api_service/api_service'; class KibanaService { private static instance: KibanaService; private _core!: CoreStart; + private _startPlugins!: ClientPluginsStart; private _theme!: Observable; public get core() { @@ -23,6 +25,14 @@ class KibanaService { apiService.http = this._core.http; } + public get startPlugins() { + return this._startPlugins; + } + + public set startPlugins(startPlugins: ClientPluginsStart) { + this._startPlugins = startPlugins; + } + public get theme() { return this._theme; } diff --git a/x-pack/plugins/synthetics/server/legacy_uptime/lib/requests/get_journey_details.ts b/x-pack/plugins/synthetics/server/legacy_uptime/lib/requests/get_journey_details.ts index 8eeb744eb3a0d..be69da15f389e 100644 --- a/x-pack/plugins/synthetics/server/legacy_uptime/lib/requests/get_journey_details.ts +++ b/x-pack/plugins/synthetics/server/legacy_uptime/lib/requests/get_journey_details.ts @@ -40,7 +40,10 @@ export const getJourneyDetails: UMElasticsearchQueryFn< size: 1, }; - const { body: thisJourney } = await uptimeEsClient.search({ body: baseParams }); + const { body: thisJourney } = await uptimeEsClient.search( + { body: baseParams }, + 'getJourneyDetails' + ); if (thisJourney.hits.hits.length > 0) { const { _id, _source } = thisJourney.hits.hits[0]; diff --git a/x-pack/plugins/synthetics/server/legacy_uptime/lib/requests/get_journey_steps.ts b/x-pack/plugins/synthetics/server/legacy_uptime/lib/requests/get_journey_steps.ts index e2aea3ede8747..c200a4c22a671 100644 --- a/x-pack/plugins/synthetics/server/legacy_uptime/lib/requests/get_journey_steps.ts +++ b/x-pack/plugins/synthetics/server/legacy_uptime/lib/requests/get_journey_steps.ts @@ -63,7 +63,7 @@ export const getJourneySteps: UMElasticsearchQueryFn< }, size: 500, }; - const { body: result } = await uptimeEsClient.search({ body: params }); + const { body: result } = await uptimeEsClient.search({ body: params }, 'getJourneySteps'); const steps = result.hits.hits.map( ({ _id, _source }) => Object.assign({ _id }, _source) as ResultType diff --git a/x-pack/plugins/synthetics/server/routes/monitor_cruds/bulk_cruds/edit_monitor_bulk.ts b/x-pack/plugins/synthetics/server/routes/monitor_cruds/bulk_cruds/edit_monitor_bulk.ts index 8cc6c5c8d30a8..b2abc0f7f534b 100644 --- a/x-pack/plugins/synthetics/server/routes/monitor_cruds/bulk_cruds/edit_monitor_bulk.ts +++ b/x-pack/plugins/synthetics/server/routes/monitor_cruds/bulk_cruds/edit_monitor_bulk.ts @@ -78,16 +78,19 @@ export const syncEditedMonitorBulk = async ({ async function syncUpdatedMonitors() { try { const editSyncPromise = await syntheticsMonitorClient.editMonitors( - monitorsToUpdate.map(({ normalizedMonitor, previousMonitor }) => ({ - monitor: { - ...(normalizedMonitor as MonitorFields), - [ConfigKey.CONFIG_ID]: previousMonitor.id, - [ConfigKey.MONITOR_QUERY_ID]: - normalizedMonitor[ConfigKey.CUSTOM_HEARTBEAT_ID] || previousMonitor.id, - }, - id: previousMonitor.id, - previousMonitor, - })), + monitorsToUpdate.map( + ({ normalizedMonitor, previousMonitor, decryptedPreviousMonitor }) => ({ + monitor: { + ...(normalizedMonitor as MonitorFields), + [ConfigKey.CONFIG_ID]: previousMonitor.id, + [ConfigKey.MONITOR_QUERY_ID]: + normalizedMonitor[ConfigKey.CUSTOM_HEARTBEAT_ID] || previousMonitor.id, + }, + id: previousMonitor.id, + previousMonitor, + decryptedPreviousMonitor, + }) + ), request, savedObjectsClient, privateLocations, diff --git a/x-pack/plugins/synthetics/server/routes/monitor_cruds/edit_monitor.ts b/x-pack/plugins/synthetics/server/routes/monitor_cruds/edit_monitor.ts index 46434d41523b2..fb20ca8c82de5 100644 --- a/x-pack/plugins/synthetics/server/routes/monitor_cruds/edit_monitor.ts +++ b/x-pack/plugins/synthetics/server/routes/monitor_cruds/edit_monitor.ts @@ -162,7 +162,14 @@ export const syncEditedMonitor = async ({ const allPrivateLocations = await getSyntheticsPrivateLocations(savedObjectsClient); const editSyncPromise = syntheticsMonitorClient.editMonitors( - [{ monitor: monitorWithId as MonitorFields, id: previousMonitor.id, previousMonitor }], + [ + { + monitor: monitorWithId as MonitorFields, + id: previousMonitor.id, + previousMonitor, + decryptedPreviousMonitor, + }, + ], request, savedObjectsClient, allPrivateLocations, diff --git a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_monitor/synthetics_monitor_client.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_monitor/synthetics_monitor_client.test.ts index e56b2fd9f839a..1a59bb3be7c3a 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_monitor/synthetics_monitor_client.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_monitor/synthetics_monitor_client.test.ts @@ -97,8 +97,13 @@ describe('SyntheticsMonitorClient', () => { id: '7af7e2f0-d5dc-11ec-87ac-bdfdb894c53d', fields: { config_id: '7af7e2f0-d5dc-11ec-87ac-bdfdb894c53d' }, fields_under_root: true, + secrets: '{}', } as unknown as MonitorFields; + const previousMonitor: any = { + attributes: { ...monitor }, + }; + it('should add a monitor', async () => { locations[1].isServiceManaged = false; @@ -125,11 +130,44 @@ describe('SyntheticsMonitorClient', () => { const client = new SyntheticsMonitorClient(syntheticsService, serverMock); client.privateLocationAPI.editMonitors = jest.fn(); + await client.editMonitors( + [ + { + id, + monitor, + previousMonitor, + decryptedPreviousMonitor: previousMonitor, + }, + ], + mockRequest, + savedObjectsClientMock, + privateLocations, + 'test-space' + ); + + expect(syntheticsService.editConfig).toHaveBeenCalledTimes(1); + expect(client.privateLocationAPI.editMonitors).toHaveBeenCalledTimes(1); + }); + + it('deletes a monitor from location, if location is removed from monitor', async () => { + locations[1].isServiceManaged = false; + + const id = 'test-id-1'; + const client = new SyntheticsMonitorClient(syntheticsService, serverMock); + syntheticsService.editConfig = jest.fn(); + client.privateLocationAPI.editMonitors = jest.fn(); + + monitor.locations = previousMonitor.attributes.locations.filter( + (loc: any) => loc.id !== locations[0].id + ); + await client.editMonitors( [ { monitor, id, + previousMonitor, + decryptedPreviousMonitor: previousMonitor, }, ], mockRequest, @@ -139,6 +177,8 @@ describe('SyntheticsMonitorClient', () => { ); expect(syntheticsService.editConfig).toHaveBeenCalledTimes(1); + expect(syntheticsService.editConfig).toHaveBeenCalledWith(deletePayload); + expect(syntheticsService.deleteConfigs).toHaveBeenCalledTimes(1); expect(client.privateLocationAPI.editMonitors).toHaveBeenCalledTimes(1); }); @@ -147,6 +187,7 @@ describe('SyntheticsMonitorClient', () => { const client = new SyntheticsMonitorClient(syntheticsService, serverMock); client.privateLocationAPI.deleteMonitors = jest.fn(); + syntheticsService.deleteConfigs = jest.fn(); await client.deleteMonitors( [monitor as unknown as SyntheticsMonitorWithId], @@ -159,3 +200,45 @@ describe('SyntheticsMonitorClient', () => { expect(client.privateLocationAPI.deleteMonitors).toHaveBeenCalledTimes(1); }); }); + +const deletePayload = [ + { + enabled: true, + fields: { + config_id: 'test-id-1', + 'monitor.project.id': undefined, + 'monitor.project.name': undefined, + run_once: undefined, + test_run_id: undefined, + }, + fields_under_root: true, + id: '7af7e2f0-d5dc-11ec-87ac-bdfdb894c53d', + locations: [ + { + geo: { lat: 0, lon: 0 }, + id: 'loc-1', + isServiceManaged: false, + label: 'Location 1', + status: 'ga', + url: 'https://example.com/1', + }, + { + geo: { lat: 0, lon: 0 }, + id: 'loc-2', + isServiceManaged: true, + label: 'Location 2', + status: 'ga', + url: 'https://example.com/2', + }, + ], + max_redirects: '0', + name: 'my mon', + params: '', + password: '', + proxy_url: '', + schedule: { number: '3', unit: 'm' }, + secrets: '{}', + type: 'http', + urls: 'http://google.com', + }, +]; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_monitor/synthetics_monitor_client.ts b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_monitor/synthetics_monitor_client.ts index 490354cc15bf6..31be90c6d7827 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_monitor/synthetics_monitor_client.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_monitor/synthetics_monitor_client.ts @@ -24,6 +24,7 @@ import { PrivateLocation, EncryptedSyntheticsMonitor, SyntheticsMonitorWithSecrets, + MonitorServiceLocation, } from '../../../common/runtime_types'; import { syntheticsMonitorType } from '../../legacy_uptime/lib/saved_objects/synthetics_monitor'; @@ -93,7 +94,8 @@ export class SyntheticsMonitorClient { monitors: Array<{ monitor: MonitorFields; id: string; - previousMonitor?: SavedObject; + previousMonitor: SavedObject; + decryptedPreviousMonitor: SavedObject; }>, request: KibanaRequest, savedObjectsClient: SavedObjectsClientContract, @@ -102,6 +104,7 @@ export class SyntheticsMonitorClient { ) { const privateConfigs: HeartbeatConfig[] = []; const publicConfigs: HeartbeatConfig[] = []; + const deletedPublicConfigs: HeartbeatConfig[] = []; const paramsBySpace = await this.syntheticsService.getSyntheticsParams({ spaceId }); @@ -117,6 +120,15 @@ export class SyntheticsMonitorClient { publicConfigs.push(editedConfig); } + const deletedPublicConfig = this.hasDeletedPublicLocations( + publicLocations, + editedMonitor.decryptedPreviousMonitor + ); + + if (deletedPublicConfig) { + deletedPublicConfigs.push(deletedPublicConfig); + } + if (privateLocations.length > 0 || this.hasPrivateLocations(editedMonitor.previousMonitor)) { privateConfigs.push(editedConfig); } @@ -130,6 +142,10 @@ export class SyntheticsMonitorClient { spaceId ); + if (deletedPublicConfigs.length > 0) { + await this.syntheticsService.deleteConfigs(deletedPublicConfigs); + } + if (publicConfigs.length > 0) { return await this.syntheticsService.editConfig(publicConfigs); } @@ -155,15 +171,36 @@ export class SyntheticsMonitorClient { return pubicResponse; } - hasPrivateLocations(previousMonitor?: SavedObject) { - if (!previousMonitor) { - return false; - } + hasPrivateLocations(previousMonitor: SavedObject) { const { locations } = previousMonitor.attributes; return locations.some((loc) => !loc.isServiceManaged); } + hasDeletedPublicLocations( + updatedLocations: MonitorServiceLocation[], + decryptedPreviousMonitor: SavedObject + ) { + const { locations } = decryptedPreviousMonitor.attributes; + + const prevPublicLocations = locations.filter((loc) => loc.isServiceManaged); + + const missingPublicLocations = prevPublicLocations.filter((prevLoc) => { + return !updatedLocations.some((updatedLoc) => updatedLoc.id === prevLoc.id); + }); + if (missingPublicLocations.length > 0) { + const { attributes: normalizedPreviousMonitor } = normalizeSecrets(decryptedPreviousMonitor); + normalizedPreviousMonitor.locations = missingPublicLocations; + + return formatHeartbeatRequest({ + monitor: normalizedPreviousMonitor, + monitorId: normalizedPreviousMonitor.id, + heartbeatId: (normalizedPreviousMonitor as MonitorFields)[ConfigKey.MONITOR_QUERY_ID], + params: {}, + }); + } + } + parseLocations(config: HeartbeatConfig) { const { locations } = config; diff --git a/x-pack/plugins/threat_intelligence/cypress/e2e/cases.cy.ts b/x-pack/plugins/threat_intelligence/cypress/e2e/cases.cy.ts index 52cdf25da68c2..94b103b827d4b 100644 --- a/x-pack/plugins/threat_intelligence/cypress/e2e/cases.cy.ts +++ b/x-pack/plugins/threat_intelligence/cypress/e2e/cases.cy.ts @@ -29,10 +29,6 @@ import { login } from '../tasks/login'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; import { selectRange } from '../tasks/select_range'; -before(() => { - login(); -}); - const THREAT_INTELLIGENCE = '/app/security/threat_intelligence/indicators'; const CASES = 'app/security/cases'; @@ -74,10 +70,14 @@ const deleteCase = () => { describe('Cases with invalid indicators', () => { before(() => { esArchiverLoad('threat_intelligence/invalid_indicators_data'); + login(); + }); + beforeEach(() => { cy.visit(THREAT_INTELLIGENCE); selectRange(); }); + after(() => { esArchiverUnload('threat_intelligence/invalid_indicators_data'); }); @@ -105,7 +105,9 @@ describe('Cases with invalid indicators', () => { describe('Cases interactions', () => { before(() => { esArchiverLoad('threat_intelligence/indicators_data'); + login(); }); + after(() => { esArchiverUnload('threat_intelligence/indicators_data'); }); diff --git a/x-pack/plugins/threat_intelligence/cypress/e2e/empty_page.cy.ts b/x-pack/plugins/threat_intelligence/cypress/e2e/empty_page.cy.ts index 6e31db8e12edc..ef534deece7d4 100644 --- a/x-pack/plugins/threat_intelligence/cypress/e2e/empty_page.cy.ts +++ b/x-pack/plugins/threat_intelligence/cypress/e2e/empty_page.cy.ts @@ -14,13 +14,16 @@ import { const THREAT_INTEL_PATH = '/app/security/threat_intelligence/'; -before(() => { - login(); -}); - describe('Empty Page', () => { - it('should render the empty page with link to docs and integrations', () => { + before(() => { + login(); + }); + + beforeEach(() => { cy.visit(THREAT_INTEL_PATH); + }); + + it('should render the empty page with link to docs and integrations', () => { cy.get(EMPTY_PAGE_BODY).should('be.visible'); cy.get(EMPTY_PAGE_DOCS_LINK).should('be.visible'); cy.get(EMPTY_PAGE_INTEGRATIONS_LINK).should('be.visible'); diff --git a/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts b/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts index da5af8f6632d9..d9bf2bdc928c3 100644 --- a/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts +++ b/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts @@ -46,23 +46,26 @@ import { login } from '../tasks/login'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; import { selectRange } from '../tasks/select_range'; -before(() => { - login(); -}); - const THREAT_INTELLIGENCE = '/app/security/threat_intelligence/indicators'; const URL_WITH_CONTRADICTORY_FILTERS = '/app/security/threat_intelligence/indicators?indicators=(filterQuery:(language:kuery,query:%27%27),filters:!((%27$state%27:(store:appState),meta:(alias:!n,disabled:!f,index:%27%27,key:threat.indicator.type,negate:!f,params:(query:file),type:phrase),query:(match_phrase:(threat.indicator.type:file))),(%27$state%27:(store:appState),meta:(alias:!n,disabled:!f,index:%27%27,key:threat.indicator.type,negate:!f,params:(query:url),type:phrase),query:(match_phrase:(threat.indicator.type:url)))),timeRange:(from:now/d,to:now/d))'; describe('Invalid Indicators', () => { + before(() => { + login(); + }); + describe('verify the grid loads even with missing fields', () => { before(() => { esArchiverLoad('threat_intelligence/invalid_indicators_data'); + }); + beforeEach(() => { cy.visit(THREAT_INTELLIGENCE); selectRange(); }); + after(() => { esArchiverUnload('threat_intelligence/invalid_indicators_data'); }); @@ -110,10 +113,13 @@ describe('Invalid Indicators', () => { describe('verify the grid loads even with missing mappings and missing fields', () => { before(() => { esArchiverLoad('threat_intelligence/missing_mappings_indicators_data'); + }); + beforeEach(() => { cy.visit(THREAT_INTELLIGENCE); selectRange(); }); + after(() => { esArchiverUnload('threat_intelligence/missing_mappings_indicators_data'); }); @@ -134,7 +140,9 @@ describe('Invalid Indicators', () => { describe('Indicators', () => { before(() => { esArchiverLoad('threat_intelligence/indicators_data'); + login(); }); + after(() => { esArchiverUnload('threat_intelligence/indicators_data'); }); @@ -149,7 +157,7 @@ describe('Indicators', () => { }); describe('Indicators page basics', () => { - before(() => { + beforeEach(() => { cy.visit(THREAT_INTELLIGENCE); selectRange(); @@ -200,7 +208,7 @@ describe('Indicators', () => { }); describe('Indicator page search', () => { - before(() => { + beforeEach(() => { cy.visit(THREAT_INTELLIGENCE); selectRange(); diff --git a/x-pack/plugins/threat_intelligence/cypress/e2e/query_bar.cy.ts b/x-pack/plugins/threat_intelligence/cypress/e2e/query_bar.cy.ts index e6eaa5671bed9..dd54473abc125 100644 --- a/x-pack/plugins/threat_intelligence/cypress/e2e/query_bar.cy.ts +++ b/x-pack/plugins/threat_intelligence/cypress/e2e/query_bar.cy.ts @@ -28,15 +28,12 @@ import { selectRange } from '../tasks/select_range'; import { login } from '../tasks/login'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; -before(() => { - login(); -}); - const THREAT_INTELLIGENCE = '/app/security/threat_intelligence/indicators'; describe('Indicators', () => { before(() => { esArchiverLoad('threat_intelligence/indicators_data'); + login(); }); after(() => { esArchiverUnload('threat_intelligence/indicators_data'); diff --git a/x-pack/plugins/threat_intelligence/cypress/e2e/timeline.cy.ts b/x-pack/plugins/threat_intelligence/cypress/e2e/timeline.cy.ts index 23aac220fc5cd..2f07c4199f3cb 100644 --- a/x-pack/plugins/threat_intelligence/cypress/e2e/timeline.cy.ts +++ b/x-pack/plugins/threat_intelligence/cypress/e2e/timeline.cy.ts @@ -28,14 +28,12 @@ import { selectRange } from '../tasks/select_range'; const THREAT_INTELLIGENCE = '/app/security/threat_intelligence/indicators'; -before(() => { - login(); -}); - describe('Indicators', () => { before(() => { esArchiverLoad('threat_intelligence/indicators_data'); + login(); }); + after(() => { esArchiverUnload('threat_intelligence/indicators_data'); }); diff --git a/x-pack/plugins/threat_intelligence/cypress/tasks/login.ts b/x-pack/plugins/threat_intelligence/cypress/tasks/login.ts index accbed00a47e9..2f490e37595e1 100644 --- a/x-pack/plugins/threat_intelligence/cypress/tasks/login.ts +++ b/x-pack/plugins/threat_intelligence/cypress/tasks/login.ts @@ -162,19 +162,21 @@ export const loginWithRole = async (role: ROLES) => { port: Cypress.env('configport'), } as UrlObject); cy.log(`origin: ${theUrl}`); - cy.request({ - body: { - providerType: 'basic', - providerName: 'basic', - currentURL: '/', - params: { - username: role, - password: 'changeme', + cy.session(role, () => { + cy.request({ + body: { + providerType: 'basic', + providerName: 'basic', + currentURL: '/', + params: { + username: role, + password: 'changeme', + }, }, - }, - headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, - method: 'POST', - url: getUrlWithRoute(role, LOGIN_API_ENDPOINT), + headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, + method: 'POST', + url: getUrlWithRoute(role, LOGIN_API_ENDPOINT), + }); }); }; @@ -214,20 +216,25 @@ const loginViaEnvironmentCredentials = () => { `Authenticating via environment credentials from the \`CYPRESS_${ELASTICSEARCH_USERNAME}\` and \`CYPRESS_${ELASTICSEARCH_PASSWORD}\` environment variables` ); + const username = Cypress.env(ELASTICSEARCH_USERNAME); + const password = Cypress.env(ELASTICSEARCH_PASSWORD); + // programmatically authenticate without interacting with the Kibana login page - cy.request({ - body: { - providerType: 'basic', - providerName: 'basic', - currentURL: '/', - params: { - username: Cypress.env(ELASTICSEARCH_USERNAME), - password: Cypress.env(ELASTICSEARCH_PASSWORD), + cy.session([username, password], () => { + cy.request({ + body: { + providerType: 'basic', + providerName: 'basic', + currentURL: '/', + params: { + username, + password, + }, }, - }, - headers: { 'kbn-xsrf': 'cypress-creds-via-env' }, - method: 'POST', - url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`, + headers: { 'kbn-xsrf': 'cypress-creds-via-env' }, + method: 'POST', + url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`, + }); }); }; @@ -245,20 +252,25 @@ const loginViaConfig = () => { cy.readFile(KIBANA_DEV_YML_PATH).then((kibanaDevYml) => { const config = yaml.safeLoad(kibanaDevYml); + const username = config.elasticsearch.username; + const password = config.elasticsearch.password; + // programmatically authenticate without interacting with the Kibana login page - cy.request({ - body: { - providerType: 'basic', - providerName: 'basic', - currentURL: '/', - params: { - username: config.elasticsearch.username, - password: config.elasticsearch.password, + cy.session([username, password], () => { + cy.request({ + body: { + providerType: 'basic', + providerName: 'basic', + currentURL: '/', + params: { + username, + password, + }, }, - }, - headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, - method: 'POST', - url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`, + headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, + method: 'POST', + url: `${Cypress.config().baseUrl}${LOGIN_API_ENDPOINT}`, + }); }); }); }; diff --git a/x-pack/plugins/threat_intelligence/public/modules/cases/hooks/use_indicator_by_id.ts b/x-pack/plugins/threat_intelligence/public/modules/cases/hooks/use_indicator_by_id.ts index 23088f7f8c0f1..379618b998f92 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/cases/hooks/use_indicator_by_id.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/cases/hooks/use_indicator_by_id.ts @@ -34,10 +34,8 @@ export const useIndicatorById = (indicatorId: string) => { bool: { must: [ { - term: { - _id: { - value: indicatorId, - }, + ids: { + values: [indicatorId], }, }, ], @@ -51,7 +49,6 @@ export const useIndicatorById = (indicatorId: string) => { ]; const req = { params: { - index: ['filebeat-*'], body: { query, fields, diff --git a/x-pack/plugins/transform/common/types/common.ts b/x-pack/plugins/transform/common/types/common.ts index 94cb935f52634..1cbb370b0a3ab 100644 --- a/x-pack/plugins/transform/common/types/common.ts +++ b/x-pack/plugins/transform/common/types/common.ts @@ -20,7 +20,3 @@ export function dictionaryToArray(dict: Dictionary): TValue[] { export type DeepPartial = { [P in keyof T]?: DeepPartial; }; - -export function isDefined(argument: T | undefined | null): argument is T { - return argument !== undefined && argument !== null; -} diff --git a/x-pack/plugins/transform/public/alerting/transform_health_rule_type/transform_selector_control.tsx b/x-pack/plugins/transform/public/alerting/transform_health_rule_type/transform_selector_control.tsx index 4300b75cb3fa4..2a44d8fd973f7 100644 --- a/x-pack/plugins/transform/public/alerting/transform_health_rule_type/transform_selector_control.tsx +++ b/x-pack/plugins/transform/public/alerting/transform_health_rule_type/transform_selector_control.tsx @@ -7,8 +7,8 @@ import { EuiComboBox, EuiComboBoxProps, EuiFormRow } from '@elastic/eui'; import React, { FC, useMemo } from 'react'; +import { isDefined } from '@kbn/ml-is-defined'; import { ALL_TRANSFORMS_SELECTION } from '../../../common/constants'; -import { isDefined } from '../../../common/types/common'; export interface TransformSelectorControlProps { label?: string | JSX.Element; diff --git a/x-pack/plugins/transform/public/app/hooks/use_get_transforms.ts b/x-pack/plugins/transform/public/app/hooks/use_get_transforms.ts index c92a7a41da03f..55e3bc40360cf 100644 --- a/x-pack/plugins/transform/public/app/hooks/use_get_transforms.ts +++ b/x-pack/plugins/transform/public/app/hooks/use_get_transforms.ts @@ -6,6 +6,7 @@ */ import type { IHttpFetchError } from '@kbn/core-http-browser'; +import { isDefined } from '@kbn/ml-is-defined'; import { isGetTransformNodesResponseSchema, isGetTransformsResponseSchema, @@ -22,7 +23,6 @@ import { import { useApi } from './use_api'; import { TRANSFORM_ERROR_TYPE } from '../common/transform'; -import { isDefined } from '../../../common/types/common'; export type GetTransforms = (forceRefresh?: boolean) => void; diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/advanced_runtime_mappings_settings/advanced_runtime_mappings_settings.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/advanced_runtime_mappings_settings/advanced_runtime_mappings_settings.tsx index a07978e12ec0f..db617690efc5f 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/advanced_runtime_mappings_settings/advanced_runtime_mappings_settings.tsx +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/advanced_runtime_mappings_settings/advanced_runtime_mappings_settings.tsx @@ -18,7 +18,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { isDefined } from '../../../../../../common/types/common'; +import { isDefined } from '@kbn/ml-is-defined'; import { StepDefineFormHook } from '../step_define'; import { AdvancedRuntimeMappingsEditor } from '../advanced_runtime_mappings_editor/advanced_runtime_mappings_editor'; import { AdvancedRuntimeMappingsEditorSwitch } from '../advanced_runtime_mappings_editor_switch'; diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_pivot_config.ts b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_pivot_config.ts index 962bc45f3d212..17240497d2057 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_pivot_config.ts +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_pivot_config.ts @@ -9,8 +9,9 @@ import { useCallback, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { KBN_FIELD_TYPES } from '@kbn/field-types'; +import { isDefined } from '@kbn/ml-is-defined'; import { AggName } from '../../../../../../../common/types/aggregations'; -import { dictionaryToArray, isDefined } from '../../../../../../../common/types/common'; +import { dictionaryToArray } from '../../../../../../../common/types/common'; import { useToastNotifications } from '../../../../../app_dependencies'; import { diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/expanded_row_json_pane.test.tsx.snap b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/expanded_row_json_pane.test.tsx.snap index 7a640389e2915..19a5055954d84 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/expanded_row_json_pane.test.tsx.snap +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/expanded_row_json_pane.test.tsx.snap @@ -21,7 +21,6 @@ exports[`Transform: Transform List Expanded Row Minimal } } > - value= { "id": "fq_date_histogram_1m_1441", "source": { diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row.tsx index d96911cfdaa71..6f1d219ce7928 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row.tsx @@ -13,7 +13,7 @@ import { i18n } from '@kbn/i18n'; import { stringHash } from '@kbn/ml-string-hash'; import moment from 'moment-timezone'; -import { isDefined } from '../../../../../../common/types/common'; +import { isDefined } from '@kbn/ml-is-defined'; import { TransformListRow } from '../../../../common'; import { useAppDependencies } from '../../../../app_dependencies'; import { ExpandedRowDetailsPane, SectionConfig, SectionItem } from './expanded_row_details_pane'; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row_json_pane.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row_json_pane.tsx index f3dd44afe1948..c68a57ea12109 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row_json_pane.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row_json_pane.tsx @@ -34,7 +34,7 @@ export const ExpandedRowJsonPane: FC = ({ json }) => { style={{ width: '100%' }} isCopyable > - value={JSON.stringify(json, null, 2)} + {JSON.stringify(json, null, 2)}
  diff --git a/x-pack/plugins/transform/tsconfig.json b/x-pack/plugins/transform/tsconfig.json index 2b4b5554ef9d0..8cb77da845d58 100644 --- a/x-pack/plugins/transform/tsconfig.json +++ b/x-pack/plugins/transform/tsconfig.json @@ -45,6 +45,7 @@ "@kbn/ui-theme", "@kbn/field-types", "@kbn/ml-nested-property", + "@kbn/ml-is-defined", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 40b8dcd9b6f7d..5640e16ad39c5 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -2447,7 +2447,6 @@ "embeddableApi.addPanel.displayName": "Ajouter un panneau", "embeddableApi.addPanel.noMatchingObjectsMessage": "Aucun objet correspondant trouvé.", "embeddableApi.addPanel.Title": "Ajouter depuis la bibliothèque", - "embeddableApi.contextMenuTrigger.description": "Un menu contextuel cliquable dans l’angle supérieur droit du panneau.", "embeddableApi.contextMenuTrigger.title": "Menu contextuel", "embeddableApi.customizePanel.action.displayName": "Modifier le titre du panneau", "embeddableApi.customizePanel.modal.cancel": "Annuler", @@ -10149,7 +10148,6 @@ "xpack.csp.benchmarks.benchmarkEmptyState.integrationsNotFoundForNameTitle": " pour \"{name}\"", "xpack.csp.benchmarks.totalIntegrationsCountMessage": "Affichage de {pageCount} sur {totalCount, plural, one {# intégration} other {# intégrations}}", "xpack.csp.cloudPosturePage.errorRenderer.errorDescription": "{error} {statusCode} : {body}", - "xpack.csp.cloudPosturePage.packageNotInstalled.description": "Utilisez notre intégration {integrationFullName} (KSPM) pour mesurer votre configuration de cluster Kubernetes par rapport aux recommandations du CIS.", "xpack.csp.complianceDashboard.complianceByCisSection.complianceColumnTooltip": "{passed}/{total}", "xpack.csp.dashboard.benchmarkSection.clusterTitle": "{title} - {shortId}", "xpack.csp.dashboard.benchmarkSection.clusterTitleTooltip.clusterTitle": "{title} - {shortId}", @@ -10180,8 +10178,6 @@ "xpack.csp.cloudPosturePage.defaultNoDataConfig.solutionNameLabel": "Niveau de sécurité du cloud", "xpack.csp.cloudPosturePage.errorRenderer.errorTitle": "Nous n'avons pas pu récupérer vos données sur le niveau de sécurité du cloud.", "xpack.csp.cloudPosturePage.loadingDescription": "Chargement...", - "xpack.csp.cloudPosturePage.packageNotInstalled.buttonLabel": "Ajouter une intégration KSPM", - "xpack.csp.cloudPosturePage.packageNotInstalled.integrationNameLabel": "Gestion du niveau de sécurité Kubernetes", "xpack.csp.cloudPosturePage.packageNotInstalled.pageTitle": "Installer l'intégration pour commencer", "xpack.csp.cloudPosturePage.packageNotInstalled.solutionNameLabel": "Niveau de sécurité du cloud", "xpack.csp.cloudPostureScoreChart.counterLink.failedFindingsTooltip": "Échec des résultats", @@ -19436,7 +19432,6 @@ "xpack.maps.fileUpload.trimmedResultsMsg": "Résultats limités à {numFeatures} fonctionnalités, {previewCoverage} % du fichier.", "xpack.maps.filterByMapExtentMenuItem.displayName": "Filtrer {containerLabel} selon les limites de la carte", "xpack.maps.filterByMapExtentMenuItem.displayNameTooltip": "Quand vous vous déplacez sur la carte ou que vous zoomez, le {containerLabel} se met à jour pour afficher uniquement les données visibles dans les limites de la carte.", - "xpack.maps.hexbin.geoShape.disabledReason": "{hexLabel} requiert un champ de cluster \"geo_point\".", "xpack.maps.hexbin.license.disabledReason": "{hexLabel} est une fonctionnalité soumise à abonnement.", "xpack.maps.initialLayers.unableToParseMessage": "Impossible d'analyser le contenu du paramètre \"initialLayers\". Erreur : {errorMsg}", "xpack.maps.inspector.vectorTileRequest.errorTitle": "Impossible de convertir la requête de tuiles \"{tileUrl}\" en requête de recherche de tuiles vectorielles Elasticsearch, erreur : {error}", @@ -33586,7 +33581,6 @@ "xpack.synthetics.monitor.step.screenshot.notAvailable": "La capture d'écran de l'étape n'est pas disponible.", "xpack.synthetics.monitor.step.screenshot.unAvailable": "Image indisponible", "xpack.synthetics.monitor.step.thumbnail.alt": "Version plus grande de la capture d'écran de la miniature de l'étape du parcours.", - "xpack.synthetics.monitor.step.viewDetails": "Afficher les détails", "xpack.synthetics.monitor.stepName.label": "Nom de l'étape", "xpack.synthetics.monitorCharts.durationChart.wrapper.label": "Graphique affichant la durée de ping du moniteur, avec regroupement par emplacement.", "xpack.synthetics.monitorCharts.monitorDuration.titleLabel": "Durée du moniteur", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 09d95547cee96..00102806c2184 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -2445,7 +2445,6 @@ "embeddableApi.addPanel.displayName": "パネルの追加", "embeddableApi.addPanel.noMatchingObjectsMessage": "一致するオブジェクトが見つかりませんでした。", "embeddableApi.addPanel.Title": "ライブラリから追加", - "embeddableApi.contextMenuTrigger.description": "パネルの右上のコンテキストメニューをクリックします。", "embeddableApi.contextMenuTrigger.title": "コンテキストメニュー", "embeddableApi.customizePanel.action.displayName": "パネルタイトルを編集", "embeddableApi.customizePanel.modal.cancel": "キャンセル", @@ -10138,7 +10137,6 @@ "xpack.csp.benchmarks.benchmarkEmptyState.integrationsNotFoundForNameTitle": " \"{name}\"", "xpack.csp.benchmarks.totalIntegrationsCountMessage": "{pageCount}/{totalCount, plural, other {#個の統合}}を表示しています", "xpack.csp.cloudPosturePage.errorRenderer.errorDescription": "{error} {statusCode}: {body}", - "xpack.csp.cloudPosturePage.packageNotInstalled.description": "{integrationFullName}(KSPM)統合は、CISの推奨事項に照らしてKubernetesクラスター設定を測定します。", "xpack.csp.complianceDashboard.complianceByCisSection.complianceColumnTooltip": "{passed}/{total}", "xpack.csp.dashboard.benchmarkSection.clusterTitle": "{title} - {shortId}", "xpack.csp.dashboard.benchmarkSection.clusterTitleTooltip.clusterTitle": "{title} - {shortId}", @@ -10169,8 +10167,6 @@ "xpack.csp.cloudPosturePage.defaultNoDataConfig.solutionNameLabel": "クラウドセキュリティ態勢", "xpack.csp.cloudPosturePage.errorRenderer.errorTitle": "クラウドセキュリティ態勢データを取得できませんでした", "xpack.csp.cloudPosturePage.loadingDescription": "読み込み中...", - "xpack.csp.cloudPosturePage.packageNotInstalled.buttonLabel": "KSPM統合の追加", - "xpack.csp.cloudPosturePage.packageNotInstalled.integrationNameLabel": "Kubernetesセキュリティ態勢管理", "xpack.csp.cloudPosturePage.packageNotInstalled.pageTitle": "開始するには統合をインストールしてください", "xpack.csp.cloudPosturePage.packageNotInstalled.solutionNameLabel": "クラウドセキュリティ態勢", "xpack.csp.cloudPostureScoreChart.counterLink.failedFindingsTooltip": "失敗した調査結果", @@ -19419,7 +19415,6 @@ "xpack.maps.fileUpload.trimmedResultsMsg": "結果は{numFeatures}個の特徴量に制限されます。これはファイルの{previewCoverage}%です。", "xpack.maps.filterByMapExtentMenuItem.displayName": "マップ境界で{containerLabel}をフィルター", "xpack.maps.filterByMapExtentMenuItem.displayNameTooltip": "マップをズームおよびパンすると、{containerLabel}が更新され、マップ境界に表示されるデータのみが表示されます。", - "xpack.maps.hexbin.geoShape.disabledReason": "{hexLabel}には'geo_point'クラスターフィールドが必要です。", "xpack.maps.hexbin.license.disabledReason": "{hexLabel}はサブスクリプション機能です。", "xpack.maps.initialLayers.unableToParseMessage": "「initialLayers」パラメーターのコンテンツをパースできません。エラー:{errorMsg}", "xpack.maps.inspector.vectorTileRequest.errorTitle": "タイル要求'{tileUrl}'をElasticesarchベクトルタイル検索要求に変換できませんでした。エラー:{error}", @@ -33558,7 +33553,6 @@ "xpack.synthetics.monitor.step.screenshot.notAvailable": "ステップスクリーンショットがありません。", "xpack.synthetics.monitor.step.screenshot.unAvailable": "画像がありません", "xpack.synthetics.monitor.step.thumbnail.alt": "このステップのサムネイルのスクリーンショットの大きいバージョン。", - "xpack.synthetics.monitor.step.viewDetails": "詳細を表示", "xpack.synthetics.monitor.stepName.label": "ステップ名", "xpack.synthetics.monitorCharts.durationChart.wrapper.label": "場所でグループ化された、モニターのping期間を示すグラフ。", "xpack.synthetics.monitorCharts.monitorDuration.titleLabel": "監視期間", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 6f62334d0d453..9a8e8a74c4b12 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -2449,7 +2449,6 @@ "embeddableApi.addPanel.displayName": "添加面板", "embeddableApi.addPanel.noMatchingObjectsMessage": "未找到任何匹配对象。", "embeddableApi.addPanel.Title": "从库中添加", - "embeddableApi.contextMenuTrigger.description": "面板右上角上下文菜单单击。", "embeddableApi.contextMenuTrigger.title": "上下文菜单", "embeddableApi.customizePanel.action.displayName": "编辑面板标题", "embeddableApi.customizePanel.modal.cancel": "取消", @@ -10153,7 +10152,6 @@ "xpack.csp.benchmarks.benchmarkEmptyState.integrationsNotFoundForNameTitle": " 对于“{name}”", "xpack.csp.benchmarks.totalIntegrationsCountMessage": "正在显示 {pageCount}/{totalCount, plural, other {# 个集成}}", "xpack.csp.cloudPosturePage.errorRenderer.errorDescription": "{error} {statusCode}:{body}", - "xpack.csp.cloudPosturePage.packageNotInstalled.description": "使用我们的 {integrationFullName} (KSPM) 集成根据 CIS 建议衡量 Kubernetes 集群设置。", "xpack.csp.complianceDashboard.complianceByCisSection.complianceColumnTooltip": "{passed}/{total}", "xpack.csp.dashboard.benchmarkSection.clusterTitle": "{title} - {shortId}", "xpack.csp.dashboard.benchmarkSection.clusterTitleTooltip.clusterTitle": "{title} - {shortId}", @@ -10184,8 +10182,6 @@ "xpack.csp.cloudPosturePage.defaultNoDataConfig.solutionNameLabel": "云安全态势", "xpack.csp.cloudPosturePage.errorRenderer.errorTitle": "我们无法提取您的云安全态势数据", "xpack.csp.cloudPosturePage.loadingDescription": "正在加载……", - "xpack.csp.cloudPosturePage.packageNotInstalled.buttonLabel": "添加 KSPM 集成", - "xpack.csp.cloudPosturePage.packageNotInstalled.integrationNameLabel": "Kubernetes 安全态势管理", "xpack.csp.cloudPosturePage.packageNotInstalled.pageTitle": "安装集成以开始", "xpack.csp.cloudPosturePage.packageNotInstalled.solutionNameLabel": "云安全态势", "xpack.csp.cloudPostureScoreChart.counterLink.failedFindingsTooltip": "失败的结果", @@ -19443,7 +19439,6 @@ "xpack.maps.fileUpload.trimmedResultsMsg": "结果仅限于 {numFeatures} 个特征、{previewCoverage}% 的文件。", "xpack.maps.filterByMapExtentMenuItem.displayName": "按地图边界筛选 {containerLabel}", "xpack.maps.filterByMapExtentMenuItem.displayNameTooltip": "当您缩放和平移地图时,{containerLabel} 会进行更新以仅显示在地图边界中可见的数据。", - "xpack.maps.hexbin.geoShape.disabledReason": "{hexLabel} 需要“geo_point”集群字段。", "xpack.maps.hexbin.license.disabledReason": "{hexLabel} 是一项订阅功能。", "xpack.maps.initialLayers.unableToParseMessage": "无法解析“initialLayers”参数的内容。错误:{errorMsg}", "xpack.maps.inspector.vectorTileRequest.errorTitle": "无法将磁贴请求“{tileUrl}”转换为 Elasticesarch 矢量磁贴搜索请求,错误:{error}", @@ -33592,7 +33587,6 @@ "xpack.synthetics.monitor.step.screenshot.notAvailable": "步骤屏幕截图不可用。", "xpack.synthetics.monitor.step.screenshot.unAvailable": "图像不可用", "xpack.synthetics.monitor.step.thumbnail.alt": "此过程步骤的缩略图屏幕截图较大版本。", - "xpack.synthetics.monitor.step.viewDetails": "查看详情", "xpack.synthetics.monitor.stepName.label": "步骤名称", "xpack.synthetics.monitorCharts.durationChart.wrapper.label": "显示监测的 ping 持续时间(按位置分组)的图表。", "xpack.synthetics.monitorCharts.monitorDuration.titleLabel": "监测持续时间", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/mock/alert_summary_widget/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/mock/alert_summary_widget/index.ts index 566140397242e..aaeb820ff136b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/mock/alert_summary_widget/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/mock/alert_summary_widget/index.ts @@ -6,79 +6,45 @@ */ import { AlertSummaryTimeRange } from '../../hooks/use_load_alert_summary'; -import { Rule } from '../../../types'; - -export const mockRule = (): Rule => { - return { - id: '1', - name: 'test rule', - tags: ['tag1'], - enabled: true, - ruleTypeId: 'test_rule_type', - schedule: { interval: '1s' }, - actions: [], - params: { name: 'test rule type name' }, - createdBy: null, - updatedBy: null, - apiKeyOwner: null, - throttle: '1m', - muteAll: false, - mutedInstanceIds: [], - createdAt: new Date(), - updatedAt: new Date(), - consumer: 'alerts', - notifyWhen: 'onActiveAlert', - executionStatus: { - status: 'active', - lastDuration: 500, - lastExecutionDate: new Date('2020-08-20T19:23:38Z'), - }, - monitoring: { - run: { - history: [ - { - success: true, - duration: 1000000, - timestamp: 1234567, - }, - { - success: true, - duration: 200000, - timestamp: 1234567, - }, - { - success: false, - duration: 300000, - timestamp: 1234567, - }, - ], - calculated_metrics: { - success_ratio: 0.66, - p50: 200000, - p95: 300000, - p99: 390000, - }, - last_run: { - timestamp: '2020-08-20T19:23:38Z', - metrics: { - duration: 500, - }, - }, - }, - }, - }; -}; export const mockAlertSummaryResponse = { - activeAlertCount: 1, - recoveredAlertCount: 1, + activeAlertCount: 2, activeAlerts: [ - { key: 1671321600000, doc_count: 0 }, + { key: 1671108000000, doc_count: 0 }, + { key: 1671208000000, doc_count: 0 }, + { key: 1671308000000, doc_count: 0 }, { key: 1671408000000, doc_count: 2 }, + { key: 1671508000000, doc_count: 4 }, + { key: 1671608000000, doc_count: 5 }, + { key: 1671708000000, doc_count: 3 }, + { key: 1671808000000, doc_count: 6 }, + { key: 1671908000000, doc_count: 14 }, + { key: 1672008000000, doc_count: 15 }, + { key: 1672108000000, doc_count: 15 }, + { key: 1672208000000, doc_count: 10 }, + { key: 1672308000000, doc_count: 9 }, + { key: 1672408000000, doc_count: 7 }, + { key: 1672508000000, doc_count: 2 }, + { key: 1672608000000, doc_count: 2 }, ], + recoveredAlertCount: 15, recoveredAlerts: [ - { key: 1671321600000, doc_count: 0 }, - { key: 1671408000000, doc_count: 1 }, + { key: 1671108000000, doc_count: 0 }, + { key: 1671208000000, doc_count: 0 }, + { key: 1671308000000, doc_count: 0 }, + { key: 1671408000000, doc_count: 0 }, + { key: 1671508000000, doc_count: 0 }, + { key: 1671608000000, doc_count: 0 }, + { key: 1671708000000, doc_count: 2 }, + { key: 1671808000000, doc_count: 0 }, + { key: 1671908000000, doc_count: 0 }, + { key: 1672008000000, doc_count: 0 }, + { key: 1672108000000, doc_count: 0 }, + { key: 1672208000000, doc_count: 5 }, + { key: 1672308000000, doc_count: 1 }, + { key: 1672408000000, doc_count: 2 }, + { key: 1672508000000, doc_count: 5 }, + { key: 1672608000000, doc_count: 0 }, ], }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/alert_summary_widget.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/alert_summary_widget.test.tsx index 00059e491da00..721118c8a8dcf 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/alert_summary_widget.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/alert_summary_widget.test.tsx @@ -6,17 +6,19 @@ */ import React from 'react'; -import { act } from 'react-dom/test-utils'; -import { nextTick } from '@kbn/test-jest-helpers'; -import { AlertSummaryWidget } from './alert_summary_widget'; -import { mount, ReactWrapper } from 'enzyme'; +import { render } from '@testing-library/react'; import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; +import { AlertSummaryWidget } from './alert_summary_widget'; +import { AlertSummaryWidgetProps } from './types'; import { mockAlertSummaryTimeRange } from '../../../../mock/alert_summary_widget'; +import { useLoadAlertSummary } from '../../../../hooks/use_load_alert_summary'; jest.mock('@kbn/kibana-react-plugin/public/ui_settings/use_ui_setting', () => ({ useUiSetting: jest.fn().mockImplementation(() => true), })); +const TITLE_DATA_TEST_SUBJ = 'mockedTimeRangeTitle'; + jest.mock('../../../../hooks/use_load_alert_summary', () => ({ useLoadAlertSummary: jest.fn().mockReturnValue({ alertSummary: { @@ -33,40 +35,74 @@ jest.mock('../../../../hooks/use_load_alert_summary', () => ({ }, }), })); +const useLoadAlertSummaryMock = useLoadAlertSummary as jest.Mock; -describe('Alert Summary Widget', () => { - let wrapper: ReactWrapper; +describe('AlertSummaryWidget', () => { const mockedTimeRange = { ...mockAlertSummaryTimeRange, - title:

mockedTimeRangeTitle

, + title:

mockedTimeRangeTitle

, }; - async function setup() { - wrapper = mount( + const renderComponent = (props: Partial = {}) => + render( ); - await act(async () => { - await nextTick(); - wrapper.update(); - }); - } - beforeAll(async () => setup()); - it('should render the Rule Alerts Summary component', async () => { - expect(wrapper.find('[data-test-subj="alertSummaryWidget"]')).toBeTruthy(); + + it('should render AlertSummaryWidget compact version', async () => { + const alertSummaryWidget = renderComponent(); + + expect(alertSummaryWidget.queryByTestId('alertSummaryWidgetCompact')).toBeTruthy(); }); - it('should show zeros for all alerts counters', async () => { - expect(wrapper.find('[data-test-subj="activeAlertsCount"]').text()).toEqual('1'); - expect(wrapper.find('[data-test-subj="recoveredAlertsCount"]').text()).toBe('7'); - expect(wrapper.find('[data-test-subj="totalAlertsCount"]').at(1).text()).toBe('Alerts (8)'); - expect(wrapper.find('[data-test-subj="mockedTimeRangeTitle"]').text()).toBe( - 'mockedTimeRangeTitle' - ); + it('should render AlertSummaryWidget full-size version', async () => { + const alertSummaryWidget = renderComponent({ fullSize: true }); + + expect(alertSummaryWidget.queryByTestId('alertSummaryWidgetFullSize')).toBeTruthy(); + }); + + it('should render counts and title correctly', async () => { + const alertSummaryWidget = renderComponent(); + expect(alertSummaryWidget.queryByTestId('activeAlertsCount')).toHaveTextContent('1'); + expect(alertSummaryWidget.queryByTestId('recoveredAlertsCount')).toHaveTextContent('7'); + expect(alertSummaryWidget.queryByTestId('totalAlertsCount')).toHaveTextContent('8'); + expect(alertSummaryWidget.queryByTestId(TITLE_DATA_TEST_SUBJ)).toBeTruthy(); + }); + + it('should render AlertSummaryWidgetError when API call fails', async () => { + useLoadAlertSummaryMock.mockImplementation(() => ({ + alertSummary: { + activeAlertCount: 0, + activeAlerts: [], + recoveredAlertCount: 0, + recoveredAlerts: [], + }, + isLoading: false, + error: 'Fetch Alert Summary Failed', + })); + const alertSummaryWidget = renderComponent(); + + expect(alertSummaryWidget.queryByTestId('alertSummaryWidgetError')).toBeTruthy(); + }); + + it('should render AlertSummaryWidget loading when API is loading', async () => { + useLoadAlertSummaryMock.mockImplementation(() => ({ + alertSummary: { + activeAlertCount: 0, + activeAlerts: [], + recoveredAlertCount: 0, + recoveredAlerts: [], + }, + isLoading: true, + })); + const alertSummaryWidget = renderComponent(); + + expect(alertSummaryWidget.queryByTestId('alertSummaryWidgetLoading')).toBeTruthy(); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/alert_summary_widget.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/alert_summary_widget.tsx index 1c8b9016b3df4..5232eb2661966 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/alert_summary_widget.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/alert_summary_widget.tsx @@ -9,12 +9,17 @@ import { EuiLoadingSpinner } from '@elastic/eui'; import React from 'react'; import { useLoadAlertSummary } from '../../../../hooks/use_load_alert_summary'; import { AlertSummaryWidgetProps } from '.'; -import { AlertSummaryWidgetError, AlertsSummaryWidgetCompact } from './components'; +import { + AlertSummaryWidgetError, + AlertsSummaryWidgetCompact, + AlertsSummaryWidgetFullSize, +} from './components'; export const AlertSummaryWidget = ({ featureIds, filter, - onClick, + fullSize, + onClick = () => {}, timeRange, }: AlertSummaryWidgetProps) => { const { @@ -27,10 +32,17 @@ export const AlertSummaryWidget = ({ timeRange, }); - if (isLoading) return ; + if (isLoading) return ; if (error) return ; - return ( + return fullSize ? ( + + ) : ( { const isDarkMode = useUiSetting('theme:darkMode'); - const textColor = isDarkMode ? euiDarkVars.euiTextColor : euiLightVars.euiTextColor; + const { euiTheme } = useEuiTheme(); const theme = [ EUI_SPARKLINE_THEME_PARTIAL, { @@ -56,7 +61,7 @@ export const AlertStateInfo = ({ return ( - +

{count}

diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_compact.stories.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_compact.stories.tsx index 1c3cecc73f6fa..c676acdb60a8b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_compact.stories.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_compact.stories.tsx @@ -7,6 +7,7 @@ import { action } from '@storybook/addon-actions'; import { AlertsSummaryWidgetCompact as Component } from './alert_summary_widget_compact'; +import { mockAlertSummaryResponse } from '../../../../../mock/alert_summary_widget'; export default { component: Component, @@ -15,44 +16,7 @@ export default { export const Compact = { args: { - activeAlertCount: 94, - activeAlerts: [ - { key: 1671108000000, doc_count: 0 }, - { key: 1671208000000, doc_count: 0 }, - { key: 1671308000000, doc_count: 0 }, - { key: 1671408000000, doc_count: 2 }, - { key: 1671508000000, doc_count: 4 }, - { key: 1671608000000, doc_count: 5 }, - { key: 1671708000000, doc_count: 3 }, - { key: 1671808000000, doc_count: 6 }, - { key: 1671908000000, doc_count: 14 }, - { key: 1672008000000, doc_count: 15 }, - { key: 1672108000000, doc_count: 15 }, - { key: 1672208000000, doc_count: 10 }, - { key: 1672308000000, doc_count: 9 }, - { key: 1672408000000, doc_count: 7 }, - { key: 1672508000000, doc_count: 2 }, - { key: 1672608000000, doc_count: 2 }, - ], - recoveredAlertCount: 15, - recoveredAlerts: [ - { key: 1671108000000, doc_count: 0 }, - { key: 1671208000000, doc_count: 0 }, - { key: 1671308000000, doc_count: 0 }, - { key: 1671408000000, doc_count: 0 }, - { key: 1671508000000, doc_count: 0 }, - { key: 1671608000000, doc_count: 0 }, - { key: 1671708000000, doc_count: 2 }, - { key: 1671808000000, doc_count: 0 }, - { key: 1671908000000, doc_count: 0 }, - { key: 1672008000000, doc_count: 0 }, - { key: 1672108000000, doc_count: 0 }, - { key: 1672208000000, doc_count: 5 }, - { key: 1672308000000, doc_count: 1 }, - { key: 1672408000000, doc_count: 2 }, - { key: 1672508000000, doc_count: 5 }, - { key: 1672608000000, doc_count: 0 }, - ], + ...mockAlertSummaryResponse, timeRangeTitle: 'Last 30 days', onClick: action('clicked'), }, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_compact.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_compact.tsx index 392dd901563f1..341d87b5162af 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_compact.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_compact.tsx @@ -16,8 +16,8 @@ import { EuiTitle, } from '@elastic/eui'; import { ALERT_STATUS_ACTIVE, ALERT_STATUS_RECOVERED, AlertStatus } from '@kbn/rule-data-utils'; -import { FormattedMessage } from '@kbn/i18n-react'; import { AlertStateInfo } from './alert_state_info'; +import { ACTIVE_ALERT_LABEL, ALL_ALERT_LABEL, RECOVERED_ALERT_LABEL } from './constants'; import { Alert } from '../../../../../hooks/use_load_alert_summary'; export interface AlertsSummaryWidgetCompactProps { @@ -58,7 +58,7 @@ export const AlertsSummaryWidgetCompact = ({ return (
- -  ({activeAlertCount + recoveredAlertCount}) + {ALL_ALERT_LABEL} ({activeAlertCount + recoveredAlertCount})
{!!timeRangeTitle && ( @@ -100,12 +96,7 @@ export const AlertsSummaryWidgetCompact = ({ domain={domain} id="active" stroke="#E7664C" - title={ - - } + title={ACTIVE_ALERT_LABEL} />
@@ -123,12 +114,7 @@ export const AlertsSummaryWidgetCompact = ({ domain={domain} id="recovered" stroke="#54B399" - title={ - - } + title={RECOVERED_ALERT_LABEL} /> diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_error.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_error.tsx index 1ee04fe2f69d1..c44d1101366d4 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_error.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_error.tsx @@ -12,7 +12,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; export const AlertSummaryWidgetError = () => { return ( ({ + useUiSetting: jest.fn(() => false), +})); + +describe('AlertSummaryWidgetFullSize', () => { + const renderComponent = (props: Partial = {}) => + render( + + + + ); + + it('should render AlertSummaryWidgetFullSize', async () => { + const alertSummaryWidget = renderComponent(); + + expect(alertSummaryWidget.queryByTestId('alertSummaryWidgetFullSize')).toBeTruthy(); + }); + + it('should render counts correctly', async () => { + const alertSummaryWidget = renderComponent(); + + expect(alertSummaryWidget.queryByTestId('activeAlertsCount')).toHaveTextContent('2'); + expect(alertSummaryWidget.queryByTestId('recoveredAlertsCount')).toHaveTextContent('15'); + expect(alertSummaryWidget.queryByTestId('totalAlertsCount')).toHaveTextContent('17'); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_full_size.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_full_size.tsx new file mode 100644 index 0000000000000..4d8d7cc564e22 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/alert_summary_widget_full_size.tsx @@ -0,0 +1,161 @@ +/* + * 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 { + EUI_CHARTS_THEME_DARK, + EUI_CHARTS_THEME_LIGHT, + EUI_SPARKLINE_THEME_PARTIAL, +} from '@elastic/eui/dist/eui_charts_theme'; +import { useUiSetting } from '@kbn/kibana-react-plugin/public'; +import moment from 'moment'; +import React from 'react'; +import { Axis, Chart, CurveType, LineSeries, Position, ScaleType, Settings } from '@elastic/charts'; +import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer, EuiText, useEuiTheme } from '@elastic/eui'; +import { + ACTIVE_ALERT_LABEL, + ACTIVE_COLOR, + ALL_ALERT_LABEL, + RECOVERED_ALERT_LABEL, + RECOVERED_COLOR, + TOOLTIP_DATE_FORMAT, +} from './constants'; +import { Alert } from '../../../../../hooks/use_load_alert_summary'; + +export interface AlertsSummaryWidgetFullSizeProps { + activeAlertCount: number; + activeAlerts: Alert[]; + recoveredAlertCount: number; + recoveredAlerts: Alert[]; +} + +export const AlertsSummaryWidgetFullSize = ({ + activeAlertCount, + activeAlerts, + recoveredAlertCount, + recoveredAlerts, +}: AlertsSummaryWidgetFullSizeProps) => { + const isDarkMode = useUiSetting('theme:darkMode'); + const { euiTheme } = useEuiTheme(); + const chartTheme = [ + EUI_SPARKLINE_THEME_PARTIAL, + { + ...(isDarkMode ? EUI_CHARTS_THEME_DARK.theme : EUI_CHARTS_THEME_LIGHT.theme), + chartMargins: { + left: 10, + right: 10, + top: 10, + bottom: 10, + }, + }, + ]; + + return ( + + + + + + + + +

+ {activeAlertCount + recoveredAlertCount} +

+
+ + {ALL_ALERT_LABEL} + +
+ + +

{activeAlertCount}

+
+ + {ACTIVE_ALERT_LABEL} + +
+ + + +

{recoveredAlertCount}

+
+
+ + {RECOVERED_ALERT_LABEL} + +
+
+
+
+
+
+ + + moment(tooltip.value).format(TOOLTIP_DATE_FORMAT), + }} + /> + + + + + + +
+ ); +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/constants.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/constants.tsx new file mode 100644 index 0000000000000..33c1509adbc40 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/constants.tsx @@ -0,0 +1,34 @@ +/* + * 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 { FormattedMessage } from '@kbn/i18n-react'; +import React from 'react'; + +export const ACTIVE_COLOR = '#E7664C'; +export const RECOVERED_COLOR = '#54B399'; +export const TOOLTIP_DATE_FORMAT = 'MMMM D, YYYY'; + +export const ALL_ALERT_LABEL = ( + +); + +export const ACTIVE_ALERT_LABEL = ( + +); + +export const RECOVERED_ALERT_LABEL = ( + +); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/index.ts index 9f4cd46f2e360..51f94c6915f4c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/components/index.ts @@ -7,3 +7,4 @@ export { AlertsSummaryWidgetCompact } from './alert_summary_widget_compact'; export { AlertSummaryWidgetError } from './alert_summary_widget_error'; +export { AlertsSummaryWidgetFullSize } from './alert_summary_widget_full_size'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/types.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/types.ts index 61e189ab4e0c5..c9dc7b567d56c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/types.ts @@ -12,6 +12,7 @@ import { AlertSummaryTimeRange } from '../../../../hooks/use_load_alert_summary' export interface AlertSummaryWidgetProps { featureIds?: ValidFeatureId[]; filter?: estypes.QueryDslQueryContainer; - onClick: (status?: AlertStatus) => void; + fullSize?: boolean; + onClick?: (status?: AlertStatus) => void; timeRange: AlertSummaryTimeRange; } diff --git a/x-pack/test/api_integration/apis/maps/get_grid_tile.js b/x-pack/test/api_integration/apis/maps/get_grid_tile.js index cd1bc9f6b4c5b..6f35ca27cb926 100644 --- a/x-pack/test/api_integration/apis/maps/get_grid_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_grid_tile.js @@ -21,8 +21,7 @@ function findFeature(layer, callbackFn) { export default function ({ getService }) { const supertest = getService('supertest'); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/148122 - describe.skip('getGridTile', () => { + describe('getGridTile', () => { const URL = `/api/maps/mvt/getGridTile/3/2/3.pbf\ ?geometryFieldName=geo.coordinates\ &hasLabels=false\ @@ -145,20 +144,20 @@ export default function ({ getService }) { expect(gridFeature.id).to.be(undefined); expect(gridFeature.properties).to.eql({ _count: 1, - _key: '85264a33fffffff', + _key: '84264a3ffffffff', 'avg_of_bytes.value': 9252, }); // assert feature geometry is hex expect(gridFeature.loadGeometry()).to.eql([ [ - { x: 102, y: 669 }, - { x: 96, y: 676 }, - { x: 86, y: 674 }, - { x: 83, y: 664 }, + { x: 111, y: 698 }, + { x: 89, y: 710 }, + { x: 67, y: 696 }, + { x: 67, y: 669 }, { x: 89, y: 657 }, - { x: 99, y: 659 }, - { x: 102, y: 669 }, + { x: 112, y: 672 }, + { x: 111, y: 698 }, ], ]); }); @@ -183,11 +182,11 @@ export default function ({ getService }) { expect(labelFeature.id).to.be(undefined); expect(labelFeature.properties).to.eql({ _count: 1, - _key: '85264a33fffffff', + _key: '84264a3ffffffff', 'avg_of_bytes.value': 9252, _mvt_label_position: true, }); - expect(labelFeature.loadGeometry()).to.eql([[{ x: 93, y: 667 }]]); + expect(labelFeature.loadGeometry()).to.eql([[{ x: 89, y: 684 }]]); }); it('should return vector tile with meta layer', async () => { diff --git a/x-pack/test/apm_api_integration/tests/fleet/apm_package_policy.spec.ts b/x-pack/test/apm_api_integration/tests/fleet/apm_package_policy.spec.ts new file mode 100644 index 0000000000000..b1f4d0efac6fd --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/fleet/apm_package_policy.spec.ts @@ -0,0 +1,89 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { + createAgentPolicy, + createPackagePolicy, + deleteAgentPolicy, + deletePackagePolicy, + setupFleet, +} from './apm_package_policy_setup'; + +export default function ApiTest(ftrProviderContext: FtrProviderContext) { + const { getService } = ftrProviderContext; + const registry = getService('registry'); + const apmApiClient = getService('apmApiClient'); + + async function createConfiguration(configuration: any) { + return apmApiClient.writeUser({ + endpoint: 'PUT /api/apm/settings/agent-configuration', + params: { body: configuration }, + }); + } + + async function deleteConfiguration(configuration: any) { + return apmApiClient.writeUser({ + endpoint: 'DELETE /api/apm/settings/agent-configuration', + params: { body: { service: configuration.service } }, + }); + } + + registry.when('APM package policy', { config: 'basic', archives: [] }, () => { + let agentPolicyId: string; + + before(async () => { + await setupFleet(ftrProviderContext); + agentPolicyId = await createAgentPolicy(ftrProviderContext); + }); + + after(async () => { + await deleteAgentPolicy(ftrProviderContext, agentPolicyId); + }); + + describe('APM package policy callbacks', () => { + let apmPackagePolicy: any; + + beforeEach(async () => { + apmPackagePolicy = await createPackagePolicy(ftrProviderContext, agentPolicyId); + }); + + afterEach(async () => { + await deletePackagePolicy(ftrProviderContext, apmPackagePolicy.id); + }); + + it('sets default values for agent configs and source mapping in a new package policy', async () => { + const apmPackageConfig = apmPackagePolicy.inputs[0].config['apm-server'].value; + expect(apmPackageConfig.rum.source_mapping).to.eql({ metadata: [] }); + expect(apmPackageConfig.agent_config).to.eql([]); + }); + + describe('Agent config', () => { + const testConfiguration = { + service: {}, + settings: { transaction_sample_rate: '0.55' }, + }; + before(async () => { + await createConfiguration(testConfiguration); + }); + + after(async () => { + await deleteConfiguration(testConfiguration); + }); + + it('sets the expected agent configs on the new package policy object', async () => { + const { + agent_config: [{ service, config }], + } = apmPackagePolicy.inputs[0].config['apm-server'].value; + expect(service).to.eql({}); + expect(config).to.eql({ transaction_sample_rate: '0.55' }); + }); + }); + }); + }); +} diff --git a/x-pack/test/apm_api_integration/tests/fleet/apm_package_policy_setup.ts b/x-pack/test/apm_api_integration/tests/fleet/apm_package_policy_setup.ts new file mode 100644 index 0000000000000..fe3634a738fe6 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/fleet/apm_package_policy_setup.ts @@ -0,0 +1,88 @@ +/* + * 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 { FtrProviderContext } from '../../common/ftr_provider_context'; + +export async function setupFleet(ftrProviderContext: FtrProviderContext) { + const { getService } = ftrProviderContext; + const supertest = getService('supertest'); + // Initialize fleet setup + await supertest.post('/api/fleet/setup').set('kbn-xsrf', 'xxx').send().expect(200); +} + +export async function createAgentPolicy(ftrProviderContext: FtrProviderContext) { + const { getService } = ftrProviderContext; + const supertest = getService('supertest'); + // Ceate agent policy and get id + const agentPolicyResponse = await supertest + .post('/api/fleet/agent_policies?sys_monitoring=true') + .set('kbn-xsrf', 'true') + .send({ + name: 'test_agent_policy', + description: '', + namespace: 'default', + monitoring_enabled: ['logs', 'metrics'], + }) + .expect(200); + return agentPolicyResponse.body.item.id; +} + +export async function createPackagePolicy( + ftrProviderContext: FtrProviderContext, + agentPolicyId: string +) { + const { getService } = ftrProviderContext; + const supertest = getService('supertest'); + + // Get version of available APM package + const apmPackageResponse = await supertest + .get(`/api/fleet/epm/packages/apm`) + .set('kbn-xsrf', 'true') + .expect(200); + const apmPackageVersion = apmPackageResponse.body.item.version; + + // Create package policy for APM attached to given agent policy id + const packagePolicyResponse = await supertest + .post('/api/fleet/package_policies') + .set('kbn-xsrf', 'true') + .send({ + name: 'apm-integration-test-policy', + description: '', + namespace: 'default', + policy_id: agentPolicyId, + enabled: true, + inputs: [{ type: 'apm', policy_template: 'apmserver', enabled: true, streams: [], vars: {} }], + package: { name: 'apm', title: 'Elastic APM', version: apmPackageVersion }, + }) + .expect(200); + return packagePolicyResponse.body.item; +} + +export async function deleteAgentPolicy( + ftrProviderContext: FtrProviderContext, + agentPolicyId: string +) { + const { getService } = ftrProviderContext; + const supertest = getService('supertest'); + await supertest + .post('/api/fleet/agent_policies/delete') + .set('kbn-xsrf', 'true') + .send({ agentPolicyId }) + .expect(200); +} + +export async function deletePackagePolicy( + ftrProviderContext: FtrProviderContext, + packagePolicyId: string +) { + const { getService } = ftrProviderContext; + const supertest = getService('supertest'); + await supertest + .post(`/api/fleet/package_policies/delete`) + .set('kbn-xsrf', 'true') + .send({ packagePolicyIds: [packagePolicyId] }) + .expect(200); +} diff --git a/x-pack/test/fleet_api_integration/apis/agents/status.ts b/x-pack/test/fleet_api_integration/apis/agents/status.ts index bac78ed854bba..b110871275504 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/status.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/status.ts @@ -91,11 +91,27 @@ export default function ({ getService }: FtrProviderContext) { }, }, }); - // 1 agent upgrading + // 1 agents inactive through enrolled_at as no last_checkin await es.create({ id: 'agent5', refresh: 'wait_for', index: AGENTS_INDEX, + document: { + active: true, + access_api_key_id: 'api-key-4', + policy_id: 'policy-inactivity-timeout', + type: 'PERMANENT', + local_metadata: { host: { hostname: 'host6' } }, + user_provided_metadata: {}, + enrolled_at: new Date(Date.now() - 1000 * 60).toISOString(), // policy timeout 1 min + }, + }); + + // 1 agent upgrading + await es.create({ + id: 'agent6', + refresh: 'wait_for', + index: AGENTS_INDEX, document: { policy_revision_idx: 1, last_checkin: new Date().toISOString(), @@ -104,7 +120,7 @@ export default function ({ getService }: FtrProviderContext) { }); // 1 agent reassigned to a new policy await es.create({ - id: 'agent6', + id: 'agent7', refresh: 'wait_for', index: AGENTS_INDEX, document: { @@ -122,7 +138,7 @@ export default function ({ getService }: FtrProviderContext) { // 1 agent unenrolled await es.create({ - id: 'agent7', + id: 'agent8', refresh: 'wait_for', index: AGENTS_INDEX, document: { @@ -140,7 +156,7 @@ export default function ({ getService }: FtrProviderContext) { }); // 1 agent error await es.create({ - id: 'agent8', + id: 'agent9', refresh: 'wait_for', index: AGENTS_INDEX, document: { @@ -158,7 +174,7 @@ export default function ({ getService }: FtrProviderContext) { }); // 1 agent degraded (error category) await es.create({ - id: 'agent9', + id: 'agent10', refresh: 'wait_for', index: AGENTS_INDEX, document: { @@ -174,6 +190,22 @@ export default function ({ getService }: FtrProviderContext) { last_checkin_status: 'DEGRADED', }, }); + // 1 agent enrolling, no last_checkin yet + await es.create({ + id: 'agent11', + refresh: 'wait_for', + index: AGENTS_INDEX, + document: { + active: true, + access_api_key_id: 'api-key-4', + policy_id: 'policy-inactivity-timeout', + type: 'PERMANENT', + policy_revision_idx: 1, + local_metadata: { host: { hostname: 'host6' } }, + user_provided_metadata: {}, + enrolled_at: new Date().toISOString(), + }, + }); }); after(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/agents'); @@ -185,12 +217,12 @@ export default function ({ getService }: FtrProviderContext) { results: { events: 0, other: 0, - total: 7, + total: 8, online: 2, error: 2, offline: 1, - updating: 2, - inactive: 1, + updating: 3, + inactive: 2, unenrolled: 1, }, }); diff --git a/x-pack/test/fleet_api_integration/apis/epm/get.ts b/x-pack/test/fleet_api_integration/apis/epm/get.ts index 42e78b731a104..21b55e0dd7454 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/get.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/get.ts @@ -208,5 +208,34 @@ export default function (providerContext: FtrProviderContext) { ); expect(dataStream?.elasticsearch?.source_mode).equal(undefined); }); + + it('allows user with only package level permission to access corresponding packages', async function () { + const pkg = 'endpoint'; + const pkgVersion = '8.6.0'; + await installPackage(pkg, pkgVersion); + const response = await supertestWithoutAuth + .get(`/api/fleet/epm/packages/${pkg}`) + .auth( + testUsers.endpoint_integr_read_only_fleet_none.username, + testUsers.endpoint_integr_read_only_fleet_none.password + ) + .expect(200); + expect(response.body.item.name).to.be(pkg); + expect(response.body.item.version).to.be(pkgVersion); + await uninstallPackage(pkg, pkgVersion); + }); + + it('rejects user with only package level permission to access unauthorized packages', async function () { + const response = await supertestWithoutAuth + .get(`/api/fleet/epm/packages/${testPkgName}`) + .auth( + testUsers.endpoint_integr_read_only_fleet_none.username, + testUsers.endpoint_integr_read_only_fleet_none.password + ) + .expect(403); + expect(response.body.message).to.be( + 'Authorization denied to package: apache. Allowed package(s): endpoint' + ); + }); }); } diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/get.ts b/x-pack/test/fleet_api_integration/apis/package_policy/get.ts index 5e3978dc50597..be2c7cc73e5f3 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/get.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/get.ts @@ -144,8 +144,7 @@ export default function (providerContext: FtrProviderContext) { .expect(403, { statusCode: 403, error: 'Forbidden', - message: - "Authorization denied to [package.name=filetest]. Allowed package.name's: endpoint", + message: 'Authorization denied to package: filetest. Allowed package(s): endpoint', }); }); @@ -267,8 +266,7 @@ export default function (providerContext: FtrProviderContext) { .send({ ids: [packagePolicyId] }) .expect(403, { error: 'Forbidden', - message: - "Authorization denied to [package.name=filetest]. Allowed package.name's: endpoint", + message: 'Authorization denied to package: filetest. Allowed package(s): endpoint', statusCode: 403, }); }); diff --git a/x-pack/test/fleet_api_integration/apis/test_users.ts b/x-pack/test/fleet_api_integration/apis/test_users.ts index a202283cca9cc..d8800003bda04 100644 --- a/x-pack/test/fleet_api_integration/apis/test_users.ts +++ b/x-pack/test/fleet_api_integration/apis/test_users.ts @@ -128,6 +128,17 @@ export const testUsers: { username: 'endpoint_fleet_read_integr_none', password: 'changeme', }, + // no fleet or integrations but read access to security solution app + endpoint_integr_read_only_fleet_none: { + permissions: { + feature: { + siem: ['minimal_all'], + }, + spaces: ['*'], + }, + username: 'endpoint_integr_read_only_fleet_none', + password: 'changeme', + }, }; export const setupTestUsers = async (security: SecurityService) => { diff --git a/x-pack/test/fleet_packages/tests/install_all.ts b/x-pack/test/fleet_packages/tests/install_all.ts index f3b769f141c4a..1f950c4fb0d4e 100644 --- a/x-pack/test/fleet_packages/tests/install_all.ts +++ b/x-pack/test/fleet_packages/tests/install_all.ts @@ -22,12 +22,30 @@ export default function (providerContext: FtrProviderContext) { function installPackage( name: string, version: string - ): Promise<{ name: string; success: boolean; error?: any }> { + ): Promise<{ name: string; version: string; success: boolean; error?: any; took?: number }> { + const start = Date.now(); return supertest .post(`/api/fleet/epm/packages/${name}/${version}`) .set('kbn-xsrf', 'xxx') .send({ force: true }) .expect(200) + .then(() => { + const end = Date.now(); + return { name, version, success: true, took: (end - start) / 1000 }; + }) + .catch((error) => { + return { name, version, success: false, error }; + }); + } + + async function deletePackage( + name: string, + version: string + ): Promise<{ name: string; success: boolean; error?: any }> { + return supertest + .delete(`/api/fleet/epm/packages/${name}/${version}`) + .set('kbn-xsrf', 'xxx') + .expect(200) .then(() => { return { name, success: true }; }) @@ -41,22 +59,34 @@ export default function (providerContext: FtrProviderContext) { it('should work and install all packages', async () => { const { body: { items: packages }, - } = await supertest.get('/api/fleet/epm/packages').expect(200); + } = await supertest.get('/api/fleet/epm/packages?prerelease=true').expect(200); const allResults = []; for (const pkg of packages) { - const pkgName = `${pkg.name}@${pkg.version}`; + // skip deprecated failing package https://github.com/elastic/integrations/issues/4947 + if (pkg.name === 'zscaler') continue; const res = await installPackage(pkg.name, pkg.version); allResults.push(res); + if (res.success) { + await deletePackage(pkg.name, pkg.version); + } + } + const succeededInstall = allResults + .filter((res) => res.success === true) + .sort((a, b) => (b.took ?? 0) - (a.took ?? 0)); + succeededInstall.forEach((res) => { + const pkgName = `${res.name}@${res.version}`; if (!res.success) { logger.info(`❌ ${pkgName} failed: ${res?.error?.message}`); } else { - logger.info(`✅ ${pkgName}`); + logger.info(`✅ ${pkgName} took ${res.took}s`); } - } + }); const failedInstall = allResults.filter((res) => res.success === false); if (failedInstall.length) { throw new Error( - `Some package installe failed: ${failedInstall.map((res) => res.name).join(', ')}` + `Some package install failed: ${failedInstall + .map((res) => `${res.name}@${res.version}`) + .join(', ')}` ); } }); diff --git a/x-pack/test/functional/apps/discover/visualize_field.ts b/x-pack/test/functional/apps/discover/visualize_field.ts index 0abd41d94976c..e90d777d2dd9e 100644 --- a/x-pack/test/functional/apps/discover/visualize_field.ts +++ b/x-pack/test/functional/apps/discover/visualize_field.ts @@ -141,10 +141,11 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await testSubjects.click('textBased-visualize'); - await retry.try(async () => { + await PageObjects.header.waitUntilLoadingHasFinished(); + + await retry.waitFor('lens visualization', async () => { const dimensions = await testSubjects.findAll('lns-dimensionTrigger-textBased'); - expect(dimensions).to.have.length(2); - expect(await dimensions[1].getVisibleText()).to.be('average'); + return dimensions.length === 2 && (await dimensions[1].getVisibleText()) === 'average'; }); }); @@ -159,10 +160,11 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await testSubjects.click('textBased-visualize'); - await retry.try(async () => { + await PageObjects.header.waitUntilLoadingHasFinished(); + + await retry.waitFor('lens visualization', async () => { const dimensions = await testSubjects.findAll('lns-dimensionTrigger-textBased'); - expect(dimensions).to.have.length(2); - expect(await dimensions[1].getVisibleText()).to.be('average'); + return dimensions.length === 2 && (await dimensions[1].getVisibleText()) === 'average'; }); }); }); diff --git a/x-pack/test/functional/apps/maps/group1/saved_object_management.js b/x-pack/test/functional/apps/maps/group1/saved_object_management.js index 0ae023e645a56..c2971397f0171 100644 --- a/x-pack/test/functional/apps/maps/group1/saved_object_management.js +++ b/x-pack/test/functional/apps/maps/group1/saved_object_management.js @@ -21,13 +21,16 @@ export default function ({ getPageObjects, getService }) { const MAP2_NAME = `${MAP_NAME_PREFIX}map2`; describe('read', () => { + let joinMapUrl = ''; before(async () => { await security.testUser.setRoles([ 'global_maps_all', 'geoshape_data_reader', + 'meta_for_geoshape_data_reader', 'test_logstash_reader', ]); await PageObjects.maps.loadSavedMap('join example'); + joinMapUrl = await browser.getCurrentUrl(); }); after(async () => { await security.testUser.restoreDefaults(); @@ -58,6 +61,17 @@ export default function ({ getPageObjects, getService }) { expect(layerExists).to.equal(true); }); + it('should override time stored with map when query is provided in global state', async () => { + const urlSplit = joinMapUrl.split('?'); + const globalState = `_g=(time:(from:now-36m,to:now))`; + await browser.get(`${urlSplit[0]}?${globalState}`, true); + await PageObjects.maps.waitForLayersToLoad(); + + const timeConfig = await PageObjects.timePicker.getTimeConfig(); + expect(timeConfig.start).to.equal('~ 36 minutes ago'); + expect(timeConfig.end).to.equal('now'); + }); + describe('mapState contains query', () => { before(async () => { await PageObjects.maps.loadSavedMap('document example with query'); diff --git a/x-pack/test/functional/fixtures/kbn_archiver/saved_objects_management/saved_objects_mix.json b/x-pack/test/functional/fixtures/kbn_archiver/saved_objects_management/saved_objects_mix.json new file mode 100644 index 0000000000000..2cb6a2974e310 --- /dev/null +++ b/x-pack/test/functional/fixtures/kbn_archiver/saved_objects_management/saved_objects_mix.json @@ -0,0 +1,3091 @@ +{ + "attributes": { + "accessCount": 0, + "accessDate": 1621977234367, + "createDate": 1621977234367, + "url": "/app/dashboards#/view/154944b0-6249-11eb-aebf-c306684b328d?embed=true&_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15y,to:now))&_a=(description:%27%27,filters:!(),fullScreenMode:!f,options:(darkTheme:!f,hidePanelTitles:!f,useMargins:!t),panels:!((embeddableConfig:(enhancements:()),gridData:(h:15,i:%271%27,w:24,x:0,y:0),id:%2736b91810-6239-11eb-aebf-c306684b328d%27,panelIndex:%271%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:(),vis:!n),gridData:(h:15,i:%272%27,w:24,x:24,y:0),id:%270a274320-61cc-11eb-aebf-c306684b328d%27,panelIndex:%272%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%273%27,w:24,x:0,y:15),id:e4aef350-623d-11eb-aebf-c306684b328d,panelIndex:%273%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%274%27,w:24,x:24,y:15),id:f92e5630-623e-11eb-aebf-c306684b328d,panelIndex:%274%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:(),vis:!n),gridData:(h:15,i:%275%27,w:24,x:0,y:30),id:%279853d4d0-623d-11eb-aebf-c306684b328d%27,panelIndex:%275%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:(),vis:!n),gridData:(h:15,i:%276%27,w:24,x:24,y:30),id:%276ecb33b0-623d-11eb-aebf-c306684b328d%27,panelIndex:%276%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:(),vis:!n),gridData:(h:15,i:%277%27,w:24,x:0,y:45),id:b8e35c80-623c-11eb-aebf-c306684b328d,panelIndex:%277%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%278%27,w:24,x:24,y:45),id:f1bc75d0-6239-11eb-aebf-c306684b328d,panelIndex:%278%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%279%27,w:24,x:0,y:60),id:%270d8a8860-623a-11eb-aebf-c306684b328d%27,panelIndex:%279%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2710%27,w:24,x:24,y:60),id:d79fe3d0-6239-11eb-aebf-c306684b328d,panelIndex:%2710%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2711%27,w:24,x:0,y:75),id:%27318375a0-6240-11eb-aebf-c306684b328d%27,panelIndex:%2711%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2712%27,w:24,x:24,y:75),id:e461eb20-6245-11eb-aebf-c306684b328d,panelIndex:%2712%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2713%27,w:24,x:0,y:90),id:%2725bdc750-6242-11eb-aebf-c306684b328d%27,panelIndex:%2713%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2714%27,w:24,x:24,y:90),id:%2771dd7bc0-6248-11eb-aebf-c306684b328d%27,panelIndex:%2714%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2715%27,w:24,x:0,y:105),id:%276aea48a0-6240-11eb-aebf-c306684b328d%27,panelIndex:%2715%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2716%27,w:24,x:24,y:105),id:%2732b681f0-6241-11eb-aebf-c306684b328d%27,panelIndex:%2716%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2717%27,w:24,x:0,y:120),id:ccca99e0-6244-11eb-aebf-c306684b328d,panelIndex:%2717%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2718%27,w:24,x:24,y:120),id:a4d7be80-6245-11eb-aebf-c306684b328d,panelIndex:%2718%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2719%27,w:24,x:0,y:135),id:c94d8440-6248-11eb-aebf-c306684b328d,panelIndex:%2719%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2720%27,w:24,x:24,y:135),id:db6226f0-61c0-11eb-aebf-c306684b328d,panelIndex:%2720%27,type:search,version:%277.13.1%27)),query:(language:lucene,query:%27%27),tags:!(),timeRestore:!f,title:logstash_dashboardwithtime,viewMode:view)" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "058bc10f0578013fc41ddedc9a1dcd1e", + "references": [], + "type": "url", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzI5MSwxXQ==" +} + +{ + "attributes": { + "color": "#ba898f", + "description": "", + "name": "By value tag" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "07f48f70-ca29-11eb-bf5e-3de94e83d4f0", + "migrationVersion": { + "tag": "8.0.0" + }, + "references": [], + "type": "tag", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzI5MiwxXQ==" +} + +{ + "attributes": { + "fieldAttrs": "{\"machine.os\":{\"count\":1},\"spaces\":{\"count\":1},\"type\":{\"count\":1},\"bytes_scripted\":{\"count\":1}}", + "fields": "[{\"count\":1,\"script\":\"doc['bytes'].value*1024\",\"lang\":\"painless\",\"name\":\"bytes_scripted\",\"type\":\"number\",\"scripted\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false}]", + "runtimeFieldMap": "{}", + "timeFieldName": "@timestamp", + "title": "logstash-*" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "migrationVersion": { + "index-pattern": "8.0.0" + }, + "references": [], + "type": "index-pattern", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzI5MywxXQ==" +} + +{ + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[{\"meta\":{\"alias\":null,\"disabled\":false,\"key\":\"geo.srcdest\",\"negate\":true,\"params\":[\"CN:CN\",\"IN:CN\",\"CN:IN\",\"IN:IN\",\"CN:US\",\"IN:US\",\"US:IN\",\"US:CN\",\"ID:CN\",\"US:US\",\"CN:ID\",\"PK:CN\",\"BR:CN\",\"CN:PK\",\"BD:CN\",\"CN:BR\",\"IN:PK\",\"NG:CN\"],\"type\":\"phrases\",\"value\":\"CN:CN, IN:CN, CN:IN, IN:IN, CN:US, IN:US, US:IN, US:CN, ID:CN, US:US, CN:ID, PK:CN, BR:CN, CN:PK, BD:CN, CN:BR, IN:PK, NG:CN\",\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"bool\":{\"minimum_should_match\":1,\"should\":[{\"match_phrase\":{\"geo.srcdest\":\"CN:CN\"}},{\"match_phrase\":{\"geo.srcdest\":\"IN:CN\"}},{\"match_phrase\":{\"geo.srcdest\":\"CN:IN\"}},{\"match_phrase\":{\"geo.srcdest\":\"IN:IN\"}},{\"match_phrase\":{\"geo.srcdest\":\"CN:US\"}},{\"match_phrase\":{\"geo.srcdest\":\"IN:US\"}},{\"match_phrase\":{\"geo.srcdest\":\"US:IN\"}},{\"match_phrase\":{\"geo.srcdest\":\"US:CN\"}},{\"match_phrase\":{\"geo.srcdest\":\"ID:CN\"}},{\"match_phrase\":{\"geo.srcdest\":\"US:US\"}},{\"match_phrase\":{\"geo.srcdest\":\"CN:ID\"}},{\"match_phrase\":{\"geo.srcdest\":\"PK:CN\"}},{\"match_phrase\":{\"geo.srcdest\":\"BR:CN\"}},{\"match_phrase\":{\"geo.srcdest\":\"CN:PK\"}},{\"match_phrase\":{\"geo.srcdest\":\"BD:CN\"}},{\"match_phrase\":{\"geo.srcdest\":\"CN:BR\"}},{\"match_phrase\":{\"geo.srcdest\":\"IN:PK\"}},{\"match_phrase\":{\"geo.srcdest\":\"NG:CN\"}}]}},\"$state\":{\"store\":\"appState\"}}]}" + }, + "optionsJSON": "{\"hidePanelTitles\":false,\"useMargins\":true}", + "panelsJSON": "[{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"095e13b2-d0ac-47db-a62b-0aca28931402\"},\"panelIndex\":\"095e13b2-d0ac-47db-a62b-0aca28931402\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsXY\",\"state\":{\"datasourceStates\":{\"formBased\":{\"layers\":{\"f61694eb-94ed-495d-9ce8-63592f040b0b\":{\"columns\":{\"75ddcdb4-3050-4545-b401-509384b0d532\":{\"label\":\"Top values of machine.os.raw\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"machine.os.raw\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"2f97b0f5-f0ff-40f2-abb0-bb7d1081a126\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"273e31ef-7c2d-4d0e-9063-5528f4011a51\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true}},\"2f97b0f5-f0ff-40f2-abb0-bb7d1081a126\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\"},\"2eb30654-0ead-40ac-92ab-d8d113e25ac5\":{\"label\":\"Average of bytes\",\"dataType\":\"number\",\"operationType\":\"average\",\"sourceField\":\"bytes\",\"isBucketed\":false,\"scale\":\"ratio\"}},\"columnOrder\":[\"75ddcdb4-3050-4545-b401-509384b0d532\",\"273e31ef-7c2d-4d0e-9063-5528f4011a51\",\"2f97b0f5-f0ff-40f2-abb0-bb7d1081a126\",\"2eb30654-0ead-40ac-92ab-d8d113e25ac5\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\",\"legendSize\":\"auto\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"f61694eb-94ed-495d-9ce8-63592f040b0b\",\"accessors\":[\"2f97b0f5-f0ff-40f2-abb0-bb7d1081a126\",\"2eb30654-0ead-40ac-92ab-d8d113e25ac5\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"xAccessor\":\"273e31ef-7c2d-4d0e-9063-5528f4011a51\",\"splitAccessor\":\"75ddcdb4-3050-4545-b401-509384b0d532\",\"layerType\":\"data\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-f61694eb-94ed-495d-9ce8-63592f040b0b\"}]},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"da7ad2b6-1e4a-40b5-9123-d0ec2bde858d\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"lens_panel_drilldown\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}},\"type\":\"lens\"}},{\"version\":\"8.6.0\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":15,\"w\":24,\"h\":15,\"i\":\"a254a623-a9af-4372-851b-572fa95b0902\"},\"panelIndex\":\"a254a623-a9af-4372-851b-572fa95b0902\",\"embeddableConfig\":{\"savedVis\":{\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n/*\\n\\nWelcome to Vega visualizations. Here you can design your own dataviz from scratch using a declarative language called Vega, or its simpler form Vega-Lite. In Vega, you have the full control of what data is loaded, even from multiple sources, how that data is transformed, and what visual elements are used to show it. Use help icon to view Vega examples, tutorials, and other docs. Use the wrench icon to reformat this text, or to remove comments.\\n\\nThis example graph shows the document count in all indexes in the current time range. You might need to adjust the time filter in the upper right corner.\\n*/\\n\\n $schema: https://vega.github.io/schema/vega-lite/v4.json\\n title: Event counts from all indexes\\n\\n // Define the data source\\n data: {\\n url: {\\n/*\\nAn object instead of a string for the \\\"url\\\" param is treated as an Elasticsearch query. Anything inside this object is not part of the Vega language, but only understood by Kibana and Elasticsearch server. This query counts the number of documents per time interval, assuming you have a @timestamp field in your data.\\n\\nKibana has a special handling for the fields surrounded by \\\"%\\\". They are processed before the the query is sent to Elasticsearch. This way the query becomes context aware, and can use the time range and the dashboard filters.\\n*/\\n\\n // Apply dashboard context filters when set\\n %context%: true\\n // Filter the time picker (upper right corner) with this field\\n %timefield%: @timestamp\\n\\n/*\\nSee .search() documentation for : https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#api-search\\n*/\\n\\n // Which index to search\\n index: _all\\n // Aggregate data by the time field into time buckets, counting the number of documents in each bucket.\\n body: {\\n aggs: {\\n time_buckets: {\\n date_histogram: {\\n // Use date histogram aggregation on @timestamp field\\n field: @timestamp\\n // The interval value will depend on the daterange picker (true), or use an integer to set an approximate bucket count\\n interval: {%autointerval%: true}\\n // Make sure we get an entire range, even if it has no data\\n extended_bounds: {\\n // Use the current time range's start and end\\n min: {%timefilter%: \\\"min\\\"}\\n max: {%timefilter%: \\\"max\\\"}\\n }\\n // Use this for linear (e.g. line, area) graphs. Without it, empty buckets will not show up\\n min_doc_count: 0\\n }\\n }\\n }\\n // Speed up the response by only including aggregation results\\n size: 0\\n }\\n }\\n/*\\nElasticsearch will return results in this format:\\n\\naggregations: {\\n time_buckets: {\\n buckets: [\\n {\\n key_as_string: 2015-11-30T22:00:00.000Z\\n key: 1448920800000\\n doc_count: 0\\n },\\n {\\n key_as_string: 2015-11-30T23:00:00.000Z\\n key: 1448924400000\\n doc_count: 0\\n }\\n ...\\n ]\\n }\\n}\\n\\nFor our graph, we only need the list of bucket values. Use the format.property to discard everything else.\\n*/\\n format: {property: \\\"aggregations.time_buckets.buckets\\\"}\\n }\\n\\n // \\\"mark\\\" is the graphics element used to show our data. Other mark values are: area, bar, circle, line, point, rect, rule, square, text, and tick. See https://vega.github.io/vega-lite/docs/mark.html\\n mark: line\\n\\n // \\\"encoding\\\" tells the \\\"mark\\\" what data to use and in what way. See https://vega.github.io/vega-lite/docs/encoding.html\\n encoding: {\\n x: {\\n // The \\\"key\\\" value is the timestamp in milliseconds. Use it for X axis.\\n field: key\\n type: temporal\\n axis: {title: false} // Customize X axis format\\n }\\n y: {\\n // The \\\"doc_count\\\" is the count per bucket. Use it for Y axis.\\n field: doc_count\\n type: quantitative\\n axis: {title: \\\"Document count\\\"}\\n }\\n }\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[{\"$state\":{\"store\":\"appState\"},\"meta\":{\"alias\":null,\"disabled\":false,\"index\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"key\":\"geo.srcdest\",\"negate\":false,\"params\":{\"query\":\"CN:CN\"},\"type\":\"phrase\"},\"query\":{\"match_phrase\":{\"geo.srcdest\":\"CN:CN\"}}}]}}},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"cfd2521d-15a0-4c64-b0ab-d2dc18f396e3\",\"triggers\":[\"CONTEXT_MENU_TRIGGER\"],\"action\":{\"name\":\"URL\",\"config\":{\"url\":{\"template\":\"http://localhost:5601/app/discover#/view/4acce030-ca2a-11eb-bf5e-3de94e83d4f0?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15y,to:now))&_a=(columns:!(),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',key:ip,negate:!f,params:(query:'57.237.11.219'),type:phrase),query:(match_phrase:(ip:'57.237.11.219')))),index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',interval:auto,query:(language:kuery,query:''),sort:!(!('@timestamp',desc)))\"},\"openInNewTab\":true,\"encodeUrl\":true},\"factoryId\":\"URL_DRILLDOWN\"}}]}},\"type\":\"visualization\"}},{\"version\":\"8.6.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"5de83d82-bbd1-4d30-be61-dd6724f32c07\"},\"panelIndex\":\"5de83d82-bbd1-4d30-be61-dd6724f32c07\",\"embeddableConfig\":{\"savedVis\":{\"title\":\"\",\"description\":\"\",\"type\":\"metrics\",\"params\":{\"annotations\":[{\"fields\":\"response.raw\",\"template\":\"{{response.raw}}\",\"index_pattern\":\"logstash-*\",\"query_string\":{\"query\":\"response.raw :\\\"404\\\" \",\"language\":\"kuery\"},\"color\":\"#F00\",\"icon\":\"fa-bomb\",\"id\":\"37395960-ca28-11eb-9eac-2f3ccefcbeef\",\"ignore_global_filters\":1,\"ignore_panel_filters\":1,\"time_field\":\"@timestamp\"}],\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"axis_scale\":\"normal\",\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"index_pattern\":\"logstash-*\",\"interval\":\"\",\"isModelInvalid\":false,\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"number\",\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"line_width\":1,\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"count\"}],\"point_size\":1,\"separate_axis\":0,\"split_color_mode\":\"kibana\",\"split_mode\":\"everything\",\"stacked\":\"none\"}],\"show_grid\":1,\"show_legend\":1,\"time_field\":\"@timestamp\",\"tooltip_mode\":\"show_all\",\"type\":\"timeseries\",\"use_kibana_indexes\":false,\"drop_last_bucket\":1},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"23d04651-266f-4f0a-8eef-6f190f0a84af\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"dashboard\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}},\"type\":\"visualization\"}},{\"version\":\"8.6.0\",\"type\":\"map\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"ac0b1e52-de90-4c93-864b-32ce338fef51\"},\"panelIndex\":\"ac0b1e52-de90-4c93-864b-32ce338fef51\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"description\":\"\",\"layerListJSON\":\"[{\\\"sourceDescriptor\\\":{\\\"type\\\":\\\"EMS_TMS\\\",\\\"isAutoSelect\\\":true,\\\"lightModeDefault\\\":\\\"road_map\\\"},\\\"id\\\":\\\"0965c5ce-6347-43f2-917e-b938ea3862f8\\\",\\\"label\\\":null,\\\"minZoom\\\":0,\\\"maxZoom\\\":24,\\\"alpha\\\":1,\\\"visible\\\":true,\\\"style\\\":{\\\"type\\\":\\\"TILE\\\"},\\\"type\\\":\\\"EMS_VECTOR_TILE\\\"},{\\\"sourceDescriptor\\\":{\\\"geoField\\\":\\\"geo.coordinates\\\",\\\"filterByMapBounds\\\":true,\\\"scalingType\\\":\\\"CLUSTERS\\\",\\\"id\\\":\\\"8fcc6cc4-919b-418c-9815-5a002cfca117\\\",\\\"type\\\":\\\"ES_SEARCH\\\",\\\"applyGlobalQuery\\\":true,\\\"applyGlobalTime\\\":true,\\\"tooltipProperties\\\":[],\\\"sortField\\\":\\\"\\\",\\\"sortOrder\\\":\\\"desc\\\",\\\"topHitsSplitField\\\":\\\"\\\",\\\"topHitsSize\\\":1,\\\"indexPatternRefName\\\":\\\"layer_1_source_index_pattern\\\"},\\\"id\\\":\\\"0b28253c-ed9e-401f-9306-feb0e58d1c0e\\\",\\\"label\\\":\\\"Clustered logstash-*\\\",\\\"minZoom\\\":0,\\\"maxZoom\\\":24,\\\"alpha\\\":0.75,\\\"visible\\\":true,\\\"style\\\":{\\\"type\\\":\\\"VECTOR\\\",\\\"properties\\\":{\\\"icon\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"value\\\":\\\"marker\\\"}},\\\"fillColor\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"color\\\":\\\"#54B399\\\"}},\\\"lineColor\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"color\\\":\\\"#41937c\\\"}},\\\"lineWidth\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"size\\\":1}},\\\"iconSize\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"size\\\":6}},\\\"iconOrientation\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"orientation\\\":0}},\\\"labelText\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"value\\\":\\\"\\\"}},\\\"labelColor\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"color\\\":\\\"#000000\\\"}},\\\"labelSize\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"size\\\":14}},\\\"labelBorderColor\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"color\\\":\\\"#FFFFFF\\\"}},\\\"symbolizeAs\\\":{\\\"options\\\":{\\\"value\\\":\\\"circle\\\"}},\\\"labelBorderSize\\\":{\\\"options\\\":{\\\"size\\\":\\\"SMALL\\\"}}},\\\"isTimeAware\\\":true},\\\"type\\\":\\\"BLENDED_VECTOR\\\",\\\"joins\\\":[]}]\",\"mapStateJSON\":\"{\\\"zoom\\\":1.45,\\\"center\\\":{\\\"lon\\\":0,\\\"lat\\\":19.94277},\\\"timeFilters\\\":{\\\"from\\\":\\\"2015-09-20T01:56:56.132Z\\\",\\\"to\\\":\\\"2015-09-21T11:18:20.471Z\\\"},\\\"refreshConfig\\\":{\\\"isPaused\\\":true,\\\"interval\\\":0},\\\"query\\\":{\\\"query\\\":\\\"\\\",\\\"language\\\":\\\"kuery\\\"},\\\"filters\\\":[],\\\"settings\\\":{\\\"autoFitToDataBounds\\\":false,\\\"backgroundColor\\\":\\\"#ffffff\\\",\\\"disableInteractive\\\":false,\\\"disableTooltipControl\\\":false,\\\"hideToolbarOverlay\\\":false,\\\"hideLayerControl\\\":false,\\\"hideViewControl\\\":false,\\\"initialLocation\\\":\\\"LAST_SAVED_LOCATION\\\",\\\"fixedLocation\\\":{\\\"lat\\\":0,\\\"lon\\\":0,\\\"zoom\\\":2},\\\"browserLocation\\\":{\\\"zoom\\\":2},\\\"maxZoom\\\":24,\\\"minZoom\\\":0,\\\"showScaleControl\\\":false,\\\"showSpatialFilters\\\":true,\\\"spatialFiltersAlpa\\\":0.3,\\\"spatialFiltersFillColor\\\":\\\"#DA8B45\\\",\\\"spatialFiltersLineColor\\\":\\\"#DA8B45\\\"}}\",\"uiStateJSON\":\"{\\\"isLayerTOCOpen\\\":true,\\\"openTOCDetails\\\":[]}\"},\"mapCenter\":{\"lat\":-24.21784,\"lon\":4.3751,\"zoom\":1.45},\"mapBuffer\":{\"minLon\":-222.61538000000002,\"minLat\":-101.36965000000001,\"maxLon\":231.36558,\"maxLat\":65.74483000000001},\"isLayerTOCOpen\":true,\"openTOCDetails\":[],\"hiddenLayers\":[],\"enhancements\":{},\"type\":\"map\"}},{\"version\":\"8.6.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":30,\"w\":24,\"h\":15,\"i\":\"147049a3-5826-48e6-9514-17078f94b6bd\"},\"panelIndex\":\"147049a3-5826-48e6-9514-17078f94b6bd\",\"embeddableConfig\":{\"savedVis\":{\"title\":\"\",\"description\":\"\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"}},\"uiState\":{},\"data\":{\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"significant_terms\",\"params\":{\"field\":\"geo.srcdest\",\"size\":77},\"schema\":\"segment\"}],\"searchSource\":{\"index\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"enhancements\":{},\"type\":\"visualization\"}}]", + "timeRestore": false, + "title": "logstash_by_value_dashboard", + "version": 1 + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "08dec860-ca29-11eb-bf5e-3de94e83d4f0", + "migrationVersion": { + "dashboard": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "095e13b2-d0ac-47db-a62b-0aca28931402:indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "095e13b2-d0ac-47db-a62b-0aca28931402:indexpattern-datasource-layer-f61694eb-94ed-495d-9ce8-63592f040b0b", + "type": "index-pattern" + }, + { + "id": "35ce3b30-ca29-11eb-bf5e-3de94e83d4f0", + "name": "095e13b2-d0ac-47db-a62b-0aca28931402:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:da7ad2b6-1e4a-40b5-9123-d0ec2bde858d:dashboardId", + "type": "dashboard" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "a254a623-a9af-4372-851b-572fa95b0902:kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "type": "index-pattern" + }, + { + "id": "35ce3b30-ca29-11eb-bf5e-3de94e83d4f0", + "name": "5de83d82-bbd1-4d30-be61-dd6724f32c07:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:23d04651-266f-4f0a-8eef-6f190f0a84af:dashboardId", + "type": "dashboard" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "ac0b1e52-de90-4c93-864b-32ce338fef51:layer_1_source_index_pattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "147049a3-5826-48e6-9514-17078f94b6bd:kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + }, + { + "id": "07f48f70-ca29-11eb-bf5e-3de94e83d4f0", + "name": "tag-07f48f70-ca29-11eb-bf5e-3de94e83d4f0", + "type": "tag" + } + ], + "type": "dashboard", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzI5NSwxXQ==" +} + +{ + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}" + }, + "optionsJSON": "{\"hidePanelTitles\":false,\"useMargins\":true}", + "panelsJSON": "[{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"60aaea59-d871-4e90-9ff3-78946d6bef90\"},\"panelIndex\":\"60aaea59-d871-4e90-9ff3-78946d6bef90\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsPie\",\"state\":{\"datasourceStates\":{\"formBased\":{\"layers\":{\"2174c5fe-75d2-43ae-9c79-1a7cc7bbbaea\":{\"columns\":{\"65625f0d-e7f1-4370-b939-7db27af74de7\":{\"label\":\"Top values of geo.srcdest\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"geo.srcdest\",\"isBucketed\":true,\"params\":{\"size\":18,\"orderBy\":{\"type\":\"column\",\"columnId\":\"553a353f-dac5-4a52-a25d-52c6e1462597\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"553a353f-dac5-4a52-a25d-52c6e1462597\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\"}},\"columnOrder\":[\"65625f0d-e7f1-4370-b939-7db27af74de7\",\"553a353f-dac5-4a52-a25d-52c6e1462597\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"shape\":\"donut\",\"layers\":[{\"layerId\":\"2174c5fe-75d2-43ae-9c79-1a7cc7bbbaea\",\"numberDisplay\":\"percent\",\"categoryDisplay\":\"default\",\"legendDisplay\":\"default\",\"nestedLegend\":false,\"layerType\":\"data\",\"legendSize\":\"auto\",\"primaryGroups\":[\"65625f0d-e7f1-4370-b939-7db27af74de7\",\"65625f0d-e7f1-4370-b939-7db27af74de7\",\"65625f0d-e7f1-4370-b939-7db27af74de7\"],\"metrics\":[\"553a353f-dac5-4a52-a25d-52c6e1462597\"]}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-2174c5fe-75d2-43ae-9c79-1a7cc7bbbaea\"}]},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"9ed45b8b-534b-4fac-9fee-436896b90039\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"circular drilldown\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}},\"type\":\"lens\"}}]", + "timeRestore": false, + "title": "lens_panel_drilldown", + "version": 1 + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "35ce3b30-ca29-11eb-bf5e-3de94e83d4f0", + "migrationVersion": { + "dashboard": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "60aaea59-d871-4e90-9ff3-78946d6bef90:indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "60aaea59-d871-4e90-9ff3-78946d6bef90:indexpattern-datasource-layer-2174c5fe-75d2-43ae-9c79-1a7cc7bbbaea", + "type": "index-pattern" + }, + { + "id": "08dec860-ca29-11eb-bf5e-3de94e83d4f0", + "name": "60aaea59-d871-4e90-9ff3-78946d6bef90:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:9ed45b8b-534b-4fac-9fee-436896b90039:dashboardId", + "type": "dashboard" + }, + { + "id": "07f48f70-ca29-11eb-bf5e-3de94e83d4f0", + "name": "tag-07f48f70-ca29-11eb-bf5e-3de94e83d4f0", + "type": "tag" + } + ], + "type": "dashboard", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzI5NCwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "logstash_scriptedfieldviz", + "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}", + "version": 1, + "visState": "{\"title\":\"logstash_scriptedfieldviz\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"isDisplayWarning\":false,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":true,\"gaugeType\":\"Arc\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"invertColors\":false,\"labels\":{\"show\":true,\"color\":\"black\"},\"scale\":{\"show\":false,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"meter\",\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"range\",\"schema\":\"group\",\"params\":{\"field\":\"bytes_scripted\",\"ranges\":[{\"from\":0,\"to\":40000},{\"from\":40001,\"to\":20000000}]}}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "0a274320-61cc-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzI5NiwxXQ==" +} + +{ + "attributes": { + "columns": [], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[{\"meta\":{\"type\":\"phrases\",\"key\":\"geo.srcdest\",\"value\":\"IN:CN\",\"params\":[\"IN:CN\"],\"alias\":null,\"negate\":false,\"disabled\":false,\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"bool\":{\"should\":[{\"match_phrase\":{\"geo.srcdest\":\"IN:CN\"}}],\"minimum_should_match\":1}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "sort": [ + [ + "@timestamp", + "desc" + ] + ], + "title": "search_saved", + "version": 1 + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "0abce1c0-ca2a-11eb-bf5e-3de94e83d4f0", + "migrationVersion": { + "search": "8.0.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "type": "index-pattern" + } + ], + "type": "search", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzI5NywxXQ==" +} + +{ + "attributes": { + "color": "#81a93f", + "description": "", + "name": "logstash_tag" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "tag": "8.0.0" + }, + "references": [], + "type": "tag", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzI5OCwxXQ==" +} + +{ + "attributes": { + "description": "", + "layerListJSON": "[{\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true,\"lightModeDefault\":\"road_map\"},\"id\":\"4c2394ca-a6a2-4f8d-9631-259eb3a9627f\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"TILE\"},\"type\":\"EMS_VECTOR_TILE\"},{\"sourceDescriptor\":{\"geoField\":\"geo.coordinates\",\"filterByMapBounds\":true,\"scalingType\":\"CLUSTERS\",\"id\":\"7555324e-e793-4b7d-a9d2-cd63e6b7fe3d\",\"type\":\"ES_SEARCH\",\"applyGlobalQuery\":true,\"applyGlobalTime\":true,\"tooltipProperties\":[\"geo.srcdest\",\"machine.os\",\"type\"],\"sortField\":\"bytes_scripted\",\"sortOrder\":\"desc\",\"topHitsSplitField\":\"\",\"topHitsSize\":1,\"indexPatternRefName\":\"layer_1_source_index_pattern\"},\"id\":\"6a493d8b-a220-46bc-8906-a1a7569799e0\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}},\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"color\":\"Blues\",\"colorCategory\":\"palette_0\",\"field\":{\"name\":\"extension.raw\",\"origin\":\"source\"},\"fieldMetaOptions\":{\"isEnabled\":true,\"sigma\":3},\"type\":\"CATEGORICAL\"}},\"lineColor\":{\"type\":\"DYNAMIC\",\"options\":{\"color\":\"Blues\",\"colorCategory\":\"palette_0\",\"field\":{\"name\":\"machine.os.raw\",\"origin\":\"source\"},\"fieldMetaOptions\":{\"isEnabled\":true,\"sigma\":3},\"type\":\"CATEGORICAL\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":6}},\"iconOrientation\":{\"type\":\"STATIC\",\"options\":{\"orientation\":0}},\"labelText\":{\"type\":\"STATIC\",\"options\":{\"value\":\"\"}},\"labelColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#000000\"}},\"labelSize\":{\"type\":\"STATIC\",\"options\":{\"size\":14}},\"labelBorderColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"labelBorderSize\":{\"options\":{\"size\":\"SMALL\"}}},\"isTimeAware\":true},\"type\":\"BLENDED_VECTOR\",\"joins\":[]}]", + "mapStateJSON": "{\"zoom\":1.56,\"center\":{\"lon\":0,\"lat\":19.94277},\"timeFilters\":{\"from\":\"now-15y\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"backgroundColor\":\"#ffffff\",\"disableInteractive\":false,\"disableTooltipControl\":false,\"hideToolbarOverlay\":false,\"hideLayerControl\":false,\"hideViewControl\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"maxZoom\":24,\"minZoom\":0,\"showScaleControl\":false,\"showSpatialFilters\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}", + "title": "logstash_maps", + "uiStateJSON": "{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "0c5974f0-be5c-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "map": "8.4.0" + }, + "references": [ + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "layer_1_source_index_pattern", + "type": "index-pattern" + } + ], + "type": "map", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzI5OSwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "logstash_datatable", + "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}", + "version": 1, + "visState": "{\"title\":\"logstash_datatable\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":true,\"totalFunc\":\"sum\",\"showToolbar\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"bucket\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-07-24T08:58:14.175Z\",\"to\":\"2015-11-11T13:28:17.223Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"response.raw\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "0d8a8860-623a-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMwMCwxXQ==" +} + +{ + "attributes": { + "description": null, + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "35fd070e-5bbc-4906-bf69-8548a213d7a0": { + "columnOrder": [ + "2bf7969f-0371-4df2-a398-0a191e428ce5", + "aab812d6-609b-444d-9990-1e67f85fd85d", + "e9829e8a-c484-4c9d-b489-f1eb3fb138d2", + "4fc9fb3b-29a5-4679-ab3c-90d5daaf0661" + ], + "columns": { + "2bf7969f-0371-4df2-a398-0a191e428ce5": { + "dataType": "date", + "isBucketed": true, + "label": "@timestamp", + "operationType": "date_histogram", + "params": { + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + }, + "4fc9fb3b-29a5-4679-ab3c-90d5daaf0661": { + "dataType": "number", + "isBucketed": false, + "label": "Moving average of Median of bytes", + "operationType": "moving_average", + "params": { + "window": 5 + }, + "references": [ + "e9829e8a-c484-4c9d-b489-f1eb3fb138d2" + ], + "scale": "ratio" + }, + "aab812d6-609b-444d-9990-1e67f85fd85d": { + "dataType": "number", + "isBucketed": false, + "label": "Average of bytes", + "operationType": "average", + "scale": "ratio", + "sourceField": "bytes" + }, + "e9829e8a-c484-4c9d-b489-f1eb3fb138d2": { + "dataType": "number", + "isBucketed": false, + "label": "Median of bytes", + "operationType": "median", + "scale": "ratio", + "sourceField": "bytes" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "layers": [ + { + "accessors": [ + "aab812d6-609b-444d-9990-1e67f85fd85d", + "4fc9fb3b-29a5-4679-ab3c-90d5daaf0661" + ], + "layerId": "35fd070e-5bbc-4906-bf69-8548a213d7a0", + "layerType": "data", + "position": "top", + "seriesType": "bar_stacked", + "showGridlines": false, + "xAccessor": "2bf7969f-0371-4df2-a398-0a191e428ce5" + } + ], + "legend": { + "isVisible": true, + "legendSize": "auto", + "position": "right" + }, + "preferredSeriesType": "bar_stacked", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "lens_barvertical_stacked_average", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "0dbbf8b0-be3c-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-35fd070e-5bbc-4906-bf69-8548a213d7a0", + "type": "index-pattern" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMwMSwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "logstash_area_chart", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"logstash_area_chart\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"fittingFunction\":\"zero\",\"legendSize\":\"auto\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2010-01-28T19:25:55.242Z\",\"to\":\"2021-01-28T19:40:55.242Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"machine.os.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"machine OS\"}}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "36b91810-6239-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMwMiwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "logstash_horizontal", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"logstash_horizontal\",\"type\":\"horizontal_bar\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":200},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":75,\"filter\":true,\"truncate\":100},\"title\":{\"text\":\"no of documents\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"normal\",\"data\":{\"label\":\"no of documents\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":true,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"legendSize\":\"auto\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"no of documents\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-07-24T08:58:14.175Z\",\"to\":\"2015-11-11T13:28:17.223Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"agent.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"extension.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "e4aef350-623d-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMwMywxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "logstash_linechart", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"logstash_linechart\",\"type\":\"line\",\"params\":{\"type\":\"line\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"line\",\"mode\":\"normal\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"radiusRatio\":51,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"fittingFunction\":\"zero\",\"legendSize\":\"auto\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-09-18T06:38:43.311Z\",\"to\":\"2015-09-26T04:02:51.104Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"sum\",\"schema\":\"radius\",\"params\":{\"field\":\"bytes\",\"customLabel\":\"bubbles\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"machine.os.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "f92e5630-623e-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMwNCwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "logstash_heatmap", + "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0% - 25%\":\"rgb(255,255,204)\",\"25% - 50%\":\"rgb(254,217,118)\",\"50% - 75%\":\"rgb(253,141,60)\",\"75% - 100%\":\"rgb(227,27,28)\"}}}", + "version": 1, + "visState": "{\"title\":\"logstash_heatmap\",\"type\":\"heatmap\",\"params\":{\"type\":\"heatmap\",\"addTooltip\":true,\"addLegend\":true,\"enableHover\":false,\"legendPosition\":\"right\",\"times\":[],\"colorsNumber\":4,\"colorSchema\":\"Yellow to Red\",\"setColorRange\":false,\"colorsRange\":[],\"invertColors\":false,\"percentageMode\":true,\"valueAxes\":[{\"show\":false,\"id\":\"ValueAxis-1\",\"type\":\"value\",\"scale\":{\"type\":\"linear\",\"defaultYExtents\":false},\"labels\":{\"show\":false,\"rotate\":0,\"overwriteColor\":false,\"color\":\"#555\"}}],\"row\":true,\"legendSize\":\"auto\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-07-24T08:58:14.175Z\",\"to\":\"2015-11-11T13:28:17.223Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"machine.os.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"response.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "9853d4d0-623d-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMwNSwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "logstash_goalchart", + "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 33\":\"rgb(0,104,55)\",\"33 - 67\":\"rgb(255,255,190)\",\"67 - 100\":\"rgb(165,0,38)\"}}}", + "version": 1, + "visState": "{\"title\":\"logstash_goalchart\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"isDisplayWarning\":false,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":true,\"gaugeType\":\"Circle\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000},{\"from\":10001,\"to\":20000},{\"from\":20001,\"to\":30000}],\"invertColors\":false,\"labels\":{\"show\":true,\"color\":\"black\"},\"scale\":{\"show\":false,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"meter\",\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60},\"minAngle\":0,\"maxAngle\":6.283185307179586}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"group\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-07-24T08:58:14.175Z\",\"to\":\"2015-11-11T13:28:17.223Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "6ecb33b0-623d-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMwNiwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "logstash_gauge", + "uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 50\":\"rgb(0,104,55)\",\"50 - 75\":\"rgb(255,255,190)\",\"75 - 100\":\"rgb(165,0,38)\"}}}", + "version": 1, + "visState": "{\"title\":\"logstash_gauge\",\"type\":\"gauge\",\"params\":{\"type\":\"gauge\",\"addTooltip\":true,\"addLegend\":true,\"isDisplayWarning\":false,\"gauge\":{\"extendRange\":true,\"percentageMode\":false,\"gaugeType\":\"Arc\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"Labels\",\"colorsRange\":[{\"from\":0,\"to\":50},{\"from\":50,\"to\":75},{\"from\":75,\"to\":100}],\"invertColors\":false,\"labels\":{\"show\":true,\"color\":\"black\"},\"scale\":{\"show\":true,\"labels\":false,\"color\":\"#333\"},\"type\":\"meter\",\"style\":{\"bgWidth\":0.9,\"width\":0.9,\"mask\":false,\"bgMask\":false,\"maskBars\":50,\"bgFill\":\"#eee\",\"bgColor\":false,\"subText\":\"\",\"fontSize\":60,\"labelColor\":true},\"alignment\":\"horizontal\"}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"range\",\"schema\":\"group\",\"params\":{\"field\":\"bytes\",\"ranges\":[{\"from\":0,\"to\":10001},{\"from\":10002,\"to\":1000000}],\"json\":\"\"}}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "b8e35c80-623c-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMwNywxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "logstash_coordinatemaps", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"logstash_coordinatemaps\",\"type\":\"tile_map\",\"params\":{\"colorSchema\":\"Yellow to Red\",\"mapType\":\"Scaled Circle Markers\",\"isDesaturated\":false,\"addTooltip\":true,\"heatClusterSize\":1.5,\"legendPosition\":\"bottomright\",\"mapZoom\":2,\"mapCenter\":[0,0],\"wms\":{\"enabled\":false,\"options\":{\"format\":\"image/png\",\"transparent\":true},\"selectedTmsLayer\":{\"origin\":\"elastic_maps_service\",\"id\":\"road_map\",\"minZoom\":0,\"maxZoom\":18,\"attribution\":\"

© OpenStreetMap contributors|OpenMapTiles|Elastic Maps Service

\"}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"geohash_grid\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.coordinates\",\"autoPrecision\":true,\"isFilteredByCollar\":true,\"useGeocentroid\":true,\"mapZoom\":2,\"mapCenter\":[0,0],\"precision\":2,\"customLabel\":\"logstash src/dest\"}}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "f1bc75d0-6239-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMwOCwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "logstash_inputcontrols", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"logstash_inputcontrols\",\"type\":\"input_control_vis\",\"params\":{\"controls\":[{\"id\":\"1611928563867\",\"fieldName\":\"machine.ram\",\"parent\":\"\",\"label\":\"Logstash RAM\",\"type\":\"range\",\"options\":{\"decimalPlaces\":0,\"step\":1024},\"indexPatternRefName\":\"control_0_index_pattern\"},{\"id\":\"1611928586274\",\"fieldName\":\"machine.os.raw\",\"parent\":\"\",\"label\":\"Logstash OS\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"dynamicOptions\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_1_index_pattern\"}],\"updateFiltersOnChange\":false,\"useTimeFilter\":false,\"pinFilters\":false},\"aggs\":[]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "d79fe3d0-6239-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "control_0_index_pattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "control_1_index_pattern", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMwOSwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "logstash_markdown", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"logstash_markdown\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"openLinksInNewTab\":true,\"markdown\":\"Kibana is built with JS https://www.javascript.com/\"},\"aggs\":[]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "318375a0-6240-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMxMCwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "title": "logstash_vegaviz", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"logstash_vegaviz\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n/*\\n\\nWelcome to Vega visualizations. Here you can design your own dataviz from scratch using a declarative language called Vega, or its simpler form Vega-Lite. In Vega, you have the full control of what data is loaded, even from multiple sources, how that data is transformed, and what visual elements are used to show it. Use help icon to view Vega examples, tutorials, and other docs. Use the wrench icon to reformat this text, or to remove comments.\\n\\nThis example graph shows the document count in all indexes in the current time range. You might need to adjust the time filter in the upper right corner.\\n*/\\n\\n $schema: https://vega.github.io/schema/vega-lite/v2.json\\n title: Event counts from all indexes\\n\\n // Define the data source\\n data: {\\n url: {\\n/*\\nAn object instead of a string for the \\\"url\\\" param is treated as an Elasticsearch query. Anything inside this object is not part of the Vega language, but only understood by Kibana and Elasticsearch server. This query counts the number of documents per time interval, assuming you have a @timestamp field in your data.\\n\\nKibana has a special handling for the fields surrounded by \\\"%\\\". They are processed before the the query is sent to Elasticsearch. This way the query becomes context aware, and can use the time range and the dashboard filters.\\n*/\\n\\n // Apply dashboard context filters when set\\n %context%: true\\n // Filter the time picker (upper right corner) with this field\\n %timefield%: @timestamp\\n\\n/*\\nSee .search() documentation for : https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#api-search\\n*/\\n\\n // Which index to search\\n index: logstash-*\\n // Aggregate data by the time field into time buckets, counting the number of documents in each bucket.\\n body: {\\n aggs: {\\n time_buckets: {\\n date_histogram: {\\n // Use date histogram aggregation on @timestamp field\\n field: @timestamp\\n // The interval value will depend on the daterange picker (true), or use an integer to set an approximate bucket count\\n interval: {%autointerval%: true}\\n // Make sure we get an entire range, even if it has no data\\n extended_bounds: {\\n // Use the current time range's start and end\\n min: {%timefilter%: \\\"min\\\"}\\n max: {%timefilter%: \\\"max\\\"}\\n }\\n // Use this for linear (e.g. line, area) graphs. Without it, empty buckets will not show up\\n min_doc_count: 13\\n }\\n }\\n }\\n // Speed up the response by only including aggregation results\\n size: 0\\n }\\n }\\n/*\\nElasticsearch will return results in this format:\\n\\naggregations: {\\n time_buckets: {\\n buckets: [\\n {\\n key_as_string: 2015-11-30T22:00:00.000Z\\n key: 1448920800000\\n doc_count: 0\\n },\\n {\\n key_as_string: 2015-11-30T23:00:00.000Z\\n key: 1448924400000\\n doc_count: 0\\n }\\n ...\\n ]\\n }\\n}\\n\\nFor our graph, we only need the list of bucket values. Use the format.property to discard everything else.\\n*/\\n format: {property: \\\"aggregations.time_buckets.buckets\\\"}\\n }\\n\\n // \\\"mark\\\" is the graphics element used to show our data. Other mark values are: area, bar, circle, line, point, rect, rule, square, text, and tick. See https://vega.github.io/vega-lite/docs/mark.html\\n mark: line\\n\\n // \\\"encoding\\\" tells the \\\"mark\\\" what data to use and in what way. See https://vega.github.io/vega-lite/docs/encoding.html\\n encoding: {\\n x: {\\n // The \\\"key\\\" value is the timestamp in milliseconds. Use it for X axis.\\n field: key\\n type: temporal\\n axis: {title: false} // Customize X axis format\\n }\\n y: {\\n // The \\\"doc_count\\\" is the count per bucket. Use it for Y axis.\\n field: doc_count\\n type: quantitative\\n axis: {title: \\\"Document count\\\"}\\n }\\n }\\n}\\n\"},\"aggs\":[]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "e461eb20-6245-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMxMSwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "logstash_regionmap", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"logstash_regionmap\",\"type\":\"region_map\",\"params\":{\"addTooltip\":true,\"colorSchema\":\"Yellow to Red\",\"emsHotLink\":\"https://maps.elastic.co/v6.7?locale=en#file/world_countries\",\"isDisplayWarning\":true,\"legendPosition\":\"bottomright\",\"mapCenter\":[0,0],\"mapZoom\":2,\"outlineWeight\":1,\"selectedJoinField\":{\"type\":\"id\",\"name\":\"iso2\",\"description\":\"ISO 3166-1 alpha-2 code\"},\"showAllShapes\":true,\"wms\":{\"enabled\":false,\"options\":{\"format\":\"image/png\",\"transparent\":true},\"selectedTmsLayer\":{\"origin\":\"elastic_maps_service\",\"id\":\"road_map\",\"minZoom\":0,\"maxZoom\":18,\"attribution\":\"

© OpenStreetMap contributors|OpenMapTiles|Elastic Maps Service

\"}},\"selectedLayer\":{\"name\":\"World Countries\",\"origin\":\"elastic_maps_service\",\"id\":\"world_countries\",\"created_at\":\"2017-04-26T17:12:15.978370\",\"attribution\":\"Made with NaturalEarth | Elastic Maps Service\",\"fields\":[{\"type\":\"id\",\"name\":\"iso2\",\"description\":\"ISO 3166-1 alpha-2 code\"},{\"type\":\"id\",\"name\":\"iso3\",\"description\":\"ISO 3166-1 alpha-3 code\"},{\"type\":\"property\",\"name\":\"name\",\"description\":\"name\"}],\"format\":{\"type\":\"geojson\"},\"layerId\":\"elastic_maps_service.World Countries\",\"isEMS\":true}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.dest\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "25bdc750-6242-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMxMiwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "logstash_verticalbarchart", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"logstash_verticalbarchart\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\",\"defaultYExtents\":true},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":true,\"row\":true,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"legendSize\":\"auto\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-09-18T06:38:43.311Z\",\"to\":\"2015-09-26T04:02:51.104Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"h\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{},\"scaleMetricValues\":true}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"response.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Response code\"}}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "71dd7bc0-6248-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMxMywxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "logstash_metricviz", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"logstash_metricviz\",\"type\":\"metric\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"type\":\"metric\",\"metric\":{\"percentageMode\":false,\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"metricColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"labels\":{\"show\":true},\"invertColors\":false,\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"range\",\"schema\":\"group\",\"params\":{\"field\":\"bytes_scripted\",\"ranges\":[{\"from\":0,\"to\":10000},{\"from\":10001,\"to\":300000}]}}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "6aea48a0-6240-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMxNCwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "logstash_piechart", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{},\"schema\":\"metric\",\"type\":\"count\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"field\":\"machine.os.raw\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"size\":5},\"schema\":\"segment\",\"type\":\"terms\"}],\"params\":{\"addTooltip\":true,\"isDonut\":true,\"labels\":{\"last_level\":true,\"show\":false,\"truncate\":100,\"values\":true},\"legendPosition\":\"right\",\"type\":\"pie\",\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"distinctColors\":true,\"legendDisplay\":\"show\",\"legendSize\":\"auto\"},\"title\":\"logstash_piechart\",\"type\":\"pie\"}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "32b681f0-6241-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMxNSwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "logstash_tagcloud", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"logstash_tagcloud\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"log\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.srcdest\",\"size\":23,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "ccca99e0-6244-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMxNiwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}" + }, + "title": "logstash_timelion", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"logstash_timelion\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(q='machine.os.raw:win xp' , index=logstash-*)\",\"interval\":\"auto\"},\"aggs\":[]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "a4d7be80-6245-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMxNywxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{}" + }, + "title": "logstash_tsvb", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"logstash_tsvb\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"timeseries\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"count\"}],\"separate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"split_color_mode\":\"gradient\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"axis_scale\":\"normal\",\"show_legend\":1,\"show_grid\":1,\"annotations\":[{\"fields\":\"machine.os.raw\",\"template\":\"{{machine.os.raw}}\",\"index_pattern\":\"logstash-*\",\"query_string\":{\"query\":\"machine.os.raw :\\\"win xp\\\" \",\"language\":\"lucene\"},\"id\":\"aa43ceb0-6248-11eb-9a82-ef1c6e6c0265\",\"color\":\"#F00\",\"time_field\":\"@timestamp\",\"icon\":\"fa-tag\",\"ignore_global_filters\":1,\"ignore_panel_filters\":1}],\"use_kibana_indexes\":false,\"drop_last_bucket\":1},\"aggs\":[]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "c94d8440-6248-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMxOCwxXQ==" +} + +{ + "attributes": { + "columns": [ + "bytes_scripted" + ], + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"machine.os.raw :\\\"win xp\\\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "sort": [ + [ + "@timestamp", + "desc" + ] + ], + "title": "logstash_scripted_saved_search", + "version": 1 + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "db6226f0-61c0-11eb-aebf-c306684b328d", + "migrationVersion": { + "search": "8.0.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "search", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMxOSwxXQ==" +} + +{ + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[]}" + }, + "optionsJSON": "{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}", + "panelsJSON": "[{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"1\",\"w\":24,\"x\":0,\"y\":0},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"2\",\"w\":24,\"x\":24,\"y\":0},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{},\"vis\":null},\"panelRefName\":\"panel_2\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"3\",\"w\":24,\"x\":0,\"y\":15},\"panelIndex\":\"3\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"4\",\"w\":24,\"x\":24,\"y\":15},\"panelIndex\":\"4\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"5\",\"w\":24,\"x\":0,\"y\":30},\"panelIndex\":\"5\",\"embeddableConfig\":{\"enhancements\":{},\"vis\":null},\"panelRefName\":\"panel_5\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"6\",\"w\":24,\"x\":24,\"y\":30},\"panelIndex\":\"6\",\"embeddableConfig\":{\"enhancements\":{},\"vis\":null},\"panelRefName\":\"panel_6\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"7\",\"w\":24,\"x\":0,\"y\":45},\"panelIndex\":\"7\",\"embeddableConfig\":{\"enhancements\":{},\"vis\":null},\"panelRefName\":\"panel_7\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"8\",\"w\":24,\"x\":24,\"y\":45},\"panelIndex\":\"8\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_8\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"9\",\"w\":24,\"x\":0,\"y\":60},\"panelIndex\":\"9\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"10\",\"w\":24,\"x\":24,\"y\":60},\"panelIndex\":\"10\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_10\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"11\",\"w\":24,\"x\":0,\"y\":75},\"panelIndex\":\"11\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_11\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"12\",\"w\":24,\"x\":24,\"y\":75},\"panelIndex\":\"12\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_12\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"13\",\"w\":24,\"x\":0,\"y\":90},\"panelIndex\":\"13\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"14\",\"w\":24,\"x\":24,\"y\":90},\"panelIndex\":\"14\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_14\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"15\",\"w\":24,\"x\":0,\"y\":105},\"panelIndex\":\"15\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_15\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"16\",\"w\":24,\"x\":24,\"y\":105},\"panelIndex\":\"16\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_16\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"17\",\"w\":24,\"x\":0,\"y\":120},\"panelIndex\":\"17\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_17\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"18\",\"w\":24,\"x\":24,\"y\":120},\"panelIndex\":\"18\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_18\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"19\",\"w\":24,\"x\":0,\"y\":135},\"panelIndex\":\"19\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_19\"},{\"version\":\"7.13.5\",\"type\":\"search\",\"gridData\":{\"h\":15,\"i\":\"20\",\"w\":24,\"x\":24,\"y\":135},\"panelIndex\":\"20\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_20\"}]", + "refreshInterval": { + "pause": true, + "value": 0 + }, + "timeFrom": "2015-09-20T01:56:56.132Z", + "timeRestore": true, + "timeTo": "2015-09-21T11:18:20.471Z", + "title": "logstash_dashboardwithtime", + "version": 1 + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "154944b0-6249-11eb-aebf-c306684b328d", + "migrationVersion": { + "dashboard": "8.6.0" + }, + "references": [ + { + "id": "36b91810-6239-11eb-aebf-c306684b328d", + "name": "1:panel_1", + "type": "visualization" + }, + { + "id": "0a274320-61cc-11eb-aebf-c306684b328d", + "name": "2:panel_2", + "type": "visualization" + }, + { + "id": "e4aef350-623d-11eb-aebf-c306684b328d", + "name": "3:panel_3", + "type": "visualization" + }, + { + "id": "f92e5630-623e-11eb-aebf-c306684b328d", + "name": "4:panel_4", + "type": "visualization" + }, + { + "id": "9853d4d0-623d-11eb-aebf-c306684b328d", + "name": "5:panel_5", + "type": "visualization" + }, + { + "id": "6ecb33b0-623d-11eb-aebf-c306684b328d", + "name": "6:panel_6", + "type": "visualization" + }, + { + "id": "b8e35c80-623c-11eb-aebf-c306684b328d", + "name": "7:panel_7", + "type": "visualization" + }, + { + "id": "f1bc75d0-6239-11eb-aebf-c306684b328d", + "name": "8:panel_8", + "type": "visualization" + }, + { + "id": "0d8a8860-623a-11eb-aebf-c306684b328d", + "name": "9:panel_9", + "type": "visualization" + }, + { + "id": "d79fe3d0-6239-11eb-aebf-c306684b328d", + "name": "10:panel_10", + "type": "visualization" + }, + { + "id": "318375a0-6240-11eb-aebf-c306684b328d", + "name": "11:panel_11", + "type": "visualization" + }, + { + "id": "e461eb20-6245-11eb-aebf-c306684b328d", + "name": "12:panel_12", + "type": "visualization" + }, + { + "id": "25bdc750-6242-11eb-aebf-c306684b328d", + "name": "13:panel_13", + "type": "visualization" + }, + { + "id": "71dd7bc0-6248-11eb-aebf-c306684b328d", + "name": "14:panel_14", + "type": "visualization" + }, + { + "id": "6aea48a0-6240-11eb-aebf-c306684b328d", + "name": "15:panel_15", + "type": "visualization" + }, + { + "id": "32b681f0-6241-11eb-aebf-c306684b328d", + "name": "16:panel_16", + "type": "visualization" + }, + { + "id": "ccca99e0-6244-11eb-aebf-c306684b328d", + "name": "17:panel_17", + "type": "visualization" + }, + { + "id": "a4d7be80-6245-11eb-aebf-c306684b328d", + "name": "18:panel_18", + "type": "visualization" + }, + { + "id": "c94d8440-6248-11eb-aebf-c306684b328d", + "name": "19:panel_19", + "type": "visualization" + }, + { + "id": "db6226f0-61c0-11eb-aebf-c306684b328d", + "name": "20:panel_20", + "type": "search" + } + ], + "type": "dashboard", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMyMCwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "26e2cf99-d931-4320-9e15-9dbc148f3534": { + "columnOrder": [ + "6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e", + "beb72af1-239c-46d8-823b-b00d1e2ace43" + ], + "columns": { + "6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e": { + "dataType": "string", + "isBucketed": true, + "label": "Top values of url.raw", + "operationType": "terms", + "params": { + "missingBucket": false, + "orderBy": { + "columnId": "beb72af1-239c-46d8-823b-b00d1e2ace43", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 20 + }, + "scale": "ordinal", + "sourceField": "url.raw" + }, + "beb72af1-239c-46d8-823b-b00d1e2ace43": { + "dataType": "number", + "isBucketed": false, + "label": "Unique count of geo.srcdest", + "operationType": "unique_count", + "scale": "ratio", + "sourceField": "geo.srcdest" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layers": [ + { + "categoryDisplay": "default", + "layerId": "26e2cf99-d931-4320-9e15-9dbc148f3534", + "layerType": "data", + "legendDisplay": "default", + "legendSize": "auto", + "metrics": [ + "beb72af1-239c-46d8-823b-b00d1e2ace43" + ], + "nestedLegend": false, + "numberDisplay": "percent", + "primaryGroups": [ + "6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e", + "6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e", + "6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e" + ] + } + ], + "shape": "donut" + } + }, + "title": "lens_pie_chart", + "visualizationType": "lnsPie" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "21905950-bd9f-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534", + "type": "index-pattern" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMyMSwxXQ==" +} + +{ + "attributes": { + "description": null, + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "a3ac0e3d-63ec-49b2-882a-b34680a967ba": { + "columnOrder": [ + "352a2c02-aa6f-4a35-b776-45c3715a6c5e", + "8ef68cbb-e039-49d6-b15e-be81559f4b55", + "14fad6b1-6a7c-4ae8-ae4b-d9569e31e04a" + ], + "columns": { + "14fad6b1-6a7c-4ae8-ae4b-d9569e31e04a": { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "scale": "ratio", + "sourceField": "___records___" + }, + "352a2c02-aa6f-4a35-b776-45c3715a6c5e": { + "dataType": "string", + "isBucketed": true, + "label": "Top values of geo.srcdest", + "operationType": "terms", + "params": { + "missingBucket": false, + "orderBy": { + "columnId": "14fad6b1-6a7c-4ae8-ae4b-d9569e31e04a", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 67 + }, + "scale": "ordinal", + "sourceField": "geo.srcdest" + }, + "8ef68cbb-e039-49d6-b15e-be81559f4b55": { + "dataType": "date", + "isBucketed": true, + "label": "@timestamp", + "operationType": "date_histogram", + "params": { + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "layers": [ + { + "accessors": [ + "14fad6b1-6a7c-4ae8-ae4b-d9569e31e04a" + ], + "layerId": "a3ac0e3d-63ec-49b2-882a-b34680a967ba", + "layerType": "data", + "position": "top", + "seriesType": "bar_percentage_stacked", + "showGridlines": false, + "splitAccessor": "352a2c02-aa6f-4a35-b776-45c3715a6c5e", + "xAccessor": "8ef68cbb-e039-49d6-b15e-be81559f4b55" + } + ], + "legend": { + "isVisible": true, + "legendSize": "auto", + "position": "top", + "showSingleSeries": true + }, + "preferredSeriesType": "bar_percentage_stacked", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "lens_bar_verticalpercentage", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "aa4b8da0-bd9f-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-a3ac0e3d-63ec-49b2-882a-b34680a967ba", + "type": "index-pattern" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMyMiwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "037b7937-790b-4d2d-94a5-7f5837a6ef05": { + "columnOrder": [ + "b3d46616-75e0-419e-97ea-91148961ef94", + "025a0fb3-dc44-4f5c-b517-2d71d3f26f14", + "c476db14-0cc1-40ec-863e-d2779256a407" + ], + "columns": { + "025a0fb3-dc44-4f5c-b517-2d71d3f26f14": { + "dataType": "date", + "isBucketed": true, + "label": "@timestamp", + "operationType": "date_histogram", + "params": { + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + }, + "b3d46616-75e0-419e-97ea-91148961ef94": { + "dataType": "string", + "isBucketed": true, + "label": "Top values of geo.srcdest", + "operationType": "terms", + "params": { + "missingBucket": false, + "orderBy": { + "columnId": "c476db14-0cc1-40ec-863e-d2779256a407", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "geo.srcdest" + }, + "c476db14-0cc1-40ec-863e-d2779256a407": { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "scale": "ratio", + "sourceField": "___records___" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "lucene", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "layers": [ + { + "accessors": [ + "c476db14-0cc1-40ec-863e-d2779256a407" + ], + "layerId": "037b7937-790b-4d2d-94a5-7f5837a6ef05", + "layerType": "data", + "position": "top", + "seriesType": "bar_stacked", + "showGridlines": false, + "splitAccessor": "b3d46616-75e0-419e-97ea-91148961ef94", + "xAccessor": "025a0fb3-dc44-4f5c-b517-2d71d3f26f14" + } + ], + "legend": { + "isVisible": true, + "legendSize": "auto", + "position": "right" + }, + "preferredSeriesType": "bar_stacked", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "lens_barchart_vertical", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "2d3f1250-bd9f-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-037b7937-790b-4d2d-94a5-7f5837a6ef05", + "type": "index-pattern" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMyMywxXQ==" +} + +{ + "attributes": { + "description": null, + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "212688dc-e7d7-4875-a221-09e6191bdcf7": { + "columnOrder": [ + "05410186-83c4-460a-82bf-dd7e9d998c9f", + "e8659feb-1db4-4706-9147-ac1fd513a1ba", + "c9a32fd0-a465-44fb-8adc-b957fb72cad5" + ], + "columns": { + "05410186-83c4-460a-82bf-dd7e9d998c9f": { + "dataType": "string", + "isBucketed": true, + "label": "Top values of extension.raw", + "operationType": "terms", + "params": { + "missingBucket": false, + "orderBy": { + "columnId": "c9a32fd0-a465-44fb-8adc-b957fb72cad5", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "extension.raw" + }, + "c9a32fd0-a465-44fb-8adc-b957fb72cad5": { + "dataType": "number", + "isBucketed": false, + "label": "Average of bytes", + "operationType": "average", + "scale": "ratio", + "sourceField": "bytes" + }, + "e8659feb-1db4-4706-9147-ac1fd513a1ba": { + "dataType": "date", + "isBucketed": true, + "label": "@timestamp", + "operationType": "date_histogram", + "params": { + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "layers": [ + { + "accessors": [ + "c9a32fd0-a465-44fb-8adc-b957fb72cad5" + ], + "layerId": "212688dc-e7d7-4875-a221-09e6191bdcf7", + "layerType": "data", + "position": "top", + "seriesType": "bar_horizontal_stacked", + "showGridlines": false, + "splitAccessor": "05410186-83c4-460a-82bf-dd7e9d998c9f", + "xAccessor": "e8659feb-1db4-4706-9147-ac1fd513a1ba" + } + ], + "legend": { + "isVisible": true, + "legendSize": "auto", + "position": "right" + }, + "preferredSeriesType": "bar_horizontal_stacked", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "lens_barhorizontal_stacked", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "edd5a560-bda4-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-212688dc-e7d7-4875-a221-09e6191bdcf7", + "type": "index-pattern" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMyNCwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "7ab04fd4-04da-4023-8899-d94620193607": { + "columnOrder": [ + "0ab2d5f8-11f0-4b25-b8bb-3127a3b8d4c7", + "9eb851dd-31f6-481a-84d1-9ecce53a6ad2", + "f6b271a7-509b-4c37-b7b6-ac5be4bcb49a" + ], + "columns": { + "0ab2d5f8-11f0-4b25-b8bb-3127a3b8d4c7": { + "dataType": "string", + "isBucketed": true, + "label": "Top values of request.raw", + "operationType": "terms", + "params": { + "missingBucket": false, + "orderBy": { + "columnId": "f6b271a7-509b-4c37-b7b6-ac5be4bcb49a", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "request.raw" + }, + "9eb851dd-31f6-481a-84d1-9ecce53a6ad2": { + "dataType": "date", + "isBucketed": true, + "label": "@timestamp", + "operationType": "date_histogram", + "params": { + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + }, + "f6b271a7-509b-4c37-b7b6-ac5be4bcb49a": { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "scale": "ratio", + "sourceField": "___records___" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "layers": [ + { + "accessors": [ + "f6b271a7-509b-4c37-b7b6-ac5be4bcb49a" + ], + "layerId": "7ab04fd4-04da-4023-8899-d94620193607", + "layerType": "data", + "position": "top", + "seriesType": "bar_horizontal_percentage_stacked", + "showGridlines": false, + "splitAccessor": "0ab2d5f8-11f0-4b25-b8bb-3127a3b8d4c7", + "xAccessor": "9eb851dd-31f6-481a-84d1-9ecce53a6ad2" + } + ], + "legend": { + "isVisible": true, + "legendSize": "auto", + "position": "right" + }, + "preferredSeriesType": "bar_horizontal_percentage_stacked", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "lens_barhorizontalpercentage", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "2c25a450-bda5-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-7ab04fd4-04da-4023-8899-d94620193607", + "type": "index-pattern" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMyNSwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "037b7937-790b-4d2d-94a5-7f5837a6ef05": { + "columnOrder": [ + "b3d46616-75e0-419e-97ea-91148961ef94", + "025a0fb3-dc44-4f5c-b517-2d71d3f26f14", + "c476db14-0cc1-40ec-863e-d2779256a407" + ], + "columns": { + "025a0fb3-dc44-4f5c-b517-2d71d3f26f14": { + "dataType": "date", + "isBucketed": true, + "label": "@timestamp", + "operationType": "date_histogram", + "params": { + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + }, + "b3d46616-75e0-419e-97ea-91148961ef94": { + "dataType": "string", + "isBucketed": true, + "label": "Top values of geo.srcdest", + "operationType": "terms", + "params": { + "missingBucket": false, + "orderBy": { + "columnId": "c476db14-0cc1-40ec-863e-d2779256a407", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "geo.srcdest" + }, + "c476db14-0cc1-40ec-863e-d2779256a407": { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "scale": "ratio", + "sourceField": "___records___" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "lucene", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "layers": [ + { + "accessors": [ + "c476db14-0cc1-40ec-863e-d2779256a407" + ], + "layerId": "037b7937-790b-4d2d-94a5-7f5837a6ef05", + "layerType": "data", + "position": "top", + "seriesType": "bar_stacked", + "showGridlines": false, + "splitAccessor": "b3d46616-75e0-419e-97ea-91148961ef94", + "xAccessor": "025a0fb3-dc44-4f5c-b517-2d71d3f26f14" + } + ], + "legend": { + "isVisible": true, + "legendSize": "auto", + "position": "right" + }, + "preferredSeriesType": "bar_stacked", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "lens_visualization", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "e79116e0-bd9e-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-037b7937-790b-4d2d-94a5-7f5837a6ef05", + "type": "index-pattern" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMyNiwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "72783e5f-aa7b-4b8a-b26c-a3e4d051340e": { + "columnOrder": [ + "0f619652-9ff1-453b-ae1f-7371baa82f55" + ], + "columns": { + "0f619652-9ff1-453b-ae1f-7371baa82f55": { + "dataType": "number", + "isBucketed": false, + "label": "Average of phpmemory", + "operationType": "average", + "params": { + "format": { + "id": "percent", + "params": { + "decimals": 10 + } + } + }, + "scale": "ratio", + "sourceField": "phpmemory" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "accessor": "0f619652-9ff1-453b-ae1f-7371baa82f55", + "layerId": "72783e5f-aa7b-4b8a-b26c-a3e4d051340e", + "layerType": "data", + "size": "xl", + "textAlign": "center", + "titlePosition": "bottom" + } + }, + "title": "lens_metric", + "visualizationType": "lnsLegacyMetric" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "974fb950-bda5-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-72783e5f-aa7b-4b8a-b26c-a3e4d051340e", + "type": "index-pattern" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMyNywxXQ==" +} + +{ + "attributes": { + "description": null, + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "bb478774-f9e8-4380-bf3a-f4a89a4d79b5": { + "columnOrder": [ + "4573ae8f-8f9d-4918-b496-c08f7102c6e1", + "cebdc6c5-3587-4f57-879c-dd63ea99cf03" + ], + "columns": { + "4573ae8f-8f9d-4918-b496-c08f7102c6e1": { + "dataType": "string", + "isBucketed": true, + "label": "Top values of machine.os.raw", + "operationType": "terms", + "params": { + "missingBucket": false, + "orderBy": { + "columnId": "cebdc6c5-3587-4f57-879c-dd63ea99cf03", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 5 + }, + "scale": "ordinal", + "sourceField": "machine.os.raw" + }, + "cebdc6c5-3587-4f57-879c-dd63ea99cf03": { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "scale": "ratio", + "sourceField": "___records___" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layers": [ + { + "categoryDisplay": "default", + "layerId": "bb478774-f9e8-4380-bf3a-f4a89a4d79b5", + "layerType": "data", + "legendDisplay": "default", + "legendSize": "auto", + "metrics": [ + "cebdc6c5-3587-4f57-879c-dd63ea99cf03" + ], + "nestedLegend": false, + "numberDisplay": "percent", + "primaryGroups": [ + "4573ae8f-8f9d-4918-b496-c08f7102c6e1" + ] + } + ], + "shape": "pie" + } + }, + "title": "lens_piechart", + "visualizationType": "lnsPie" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "51b63040-bda5-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-bb478774-f9e8-4380-bf3a-f4a89a4d79b5", + "type": "index-pattern" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMyOCwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "a1b85651-db29-441f-8f08-cf1b9b6f7bf1": { + "columnOrder": [ + "2b3bdc32-0be0-49dc-993d-4630b0bd1185", + "b85cc0a7-0b18-4b08-b7f0-c617f80cf903", + "03203126-8286-444d-b5b3-4f399eaf2c26", + "44305317-61e8-4600-9f3c-ac4070e0c529" + ], + "columns": { + "03203126-8286-444d-b5b3-4f399eaf2c26": { + "dataType": "date", + "isBucketed": true, + "label": "@timestamp", + "operationType": "date_histogram", + "params": { + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + }, + "2b3bdc32-0be0-49dc-993d-4630b0bd1185": { + "dataType": "string", + "isBucketed": true, + "label": "Top values of extension.raw", + "operationType": "terms", + "params": { + "missingBucket": false, + "orderBy": { + "columnId": "44305317-61e8-4600-9f3c-ac4070e0c529", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "extension.raw" + }, + "44305317-61e8-4600-9f3c-ac4070e0c529": { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "scale": "ratio", + "sourceField": "___records___" + }, + "b85cc0a7-0b18-4b08-b7f0-c617f80cf903": { + "dataType": "string", + "isBucketed": true, + "label": "Top values of machine.os.raw", + "operationType": "terms", + "params": { + "missingBucket": false, + "orderBy": { + "columnId": "44305317-61e8-4600-9f3c-ac4070e0c529", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "machine.os.raw" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "2b3bdc32-0be0-49dc-993d-4630b0bd1185", + "isTransposed": false + }, + { + "columnId": "b85cc0a7-0b18-4b08-b7f0-c617f80cf903", + "isTransposed": false + }, + { + "columnId": "03203126-8286-444d-b5b3-4f399eaf2c26", + "isTransposed": false + }, + { + "columnId": "44305317-61e8-4600-9f3c-ac4070e0c529", + "isTransposed": false + } + ], + "layerId": "a1b85651-db29-441f-8f08-cf1b9b6f7bf1", + "layerType": "data", + "rowHeight": "single", + "rowHeightLines": 1 + } + }, + "title": "lens_table", + "visualizationType": "lnsDatatable" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "b00679c0-bda5-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-a1b85651-db29-441f-8f08-cf1b9b6f7bf1", + "type": "index-pattern" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMyOSwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "4fbb51e9-1f99-4b5e-b59d-60fcb547b1d9": { + "columnOrder": [ + "08a1af05-743d-480e-9056-3405b1bdda7d", + "bae35990-75c2-487f-94eb-d8e03d2eda33" + ], + "columns": { + "08a1af05-743d-480e-9056-3405b1bdda7d": { + "dataType": "string", + "isBucketed": true, + "label": "Top values of geo.srcdest", + "operationType": "terms", + "params": { + "missingBucket": false, + "orderBy": { + "columnId": "bae35990-75c2-487f-94eb-d8e03d2eda33", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 25 + }, + "scale": "ordinal", + "sourceField": "geo.srcdest" + }, + "bae35990-75c2-487f-94eb-d8e03d2eda33": { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "scale": "ratio", + "sourceField": "___records___" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layers": [ + { + "categoryDisplay": "default", + "layerId": "4fbb51e9-1f99-4b5e-b59d-60fcb547b1d9", + "layerType": "data", + "legendDisplay": "default", + "legendSize": "auto", + "metrics": [ + "bae35990-75c2-487f-94eb-d8e03d2eda33" + ], + "nestedLegend": false, + "numberDisplay": "percent", + "primaryGroups": [ + "08a1af05-743d-480e-9056-3405b1bdda7d", + "08a1af05-743d-480e-9056-3405b1bdda7d", + "08a1af05-743d-480e-9056-3405b1bdda7d" + ] + } + ], + "shape": "treemap" + } + }, + "title": "lens_treemap", + "visualizationType": "lnsPie" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "652ade10-bd9f-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-4fbb51e9-1f99-4b5e-b59d-60fcb547b1d9", + "type": "index-pattern" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMzMCwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "e84503c1-4dbd-4ac6-9ac9-ad938654680f": { + "columnOrder": [ + "38c73fd4-6330-4162-8a7b-1a059f005da8", + "e8d4dad2-ac30-4741-aca0-904eb1fc8455", + "70433aa7-3c2c-4e6c-b8cf-4218c995cff5" + ], + "columns": { + "38c73fd4-6330-4162-8a7b-1a059f005da8": { + "dataType": "string", + "isBucketed": true, + "label": "Top values of url.raw", + "operationType": "terms", + "params": { + "missingBucket": false, + "orderBy": { + "columnId": "70433aa7-3c2c-4e6c-b8cf-4218c995cff5", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "url.raw" + }, + "70433aa7-3c2c-4e6c-b8cf-4218c995cff5": { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "scale": "ratio", + "sourceField": "___records___" + }, + "e8d4dad2-ac30-4741-aca0-904eb1fc8455": { + "dataType": "date", + "isBucketed": true, + "label": "@timestamp", + "operationType": "date_histogram", + "params": { + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "layers": [ + { + "accessors": [ + "70433aa7-3c2c-4e6c-b8cf-4218c995cff5" + ], + "layerId": "e84503c1-4dbd-4ac6-9ac9-ad938654680f", + "layerType": "data", + "position": "top", + "seriesType": "line", + "showGridlines": false, + "splitAccessor": "38c73fd4-6330-4162-8a7b-1a059f005da8", + "xAccessor": "e8d4dad2-ac30-4741-aca0-904eb1fc8455" + } + ], + "legend": { + "isVisible": true, + "legendSize": "auto", + "position": "right" + }, + "preferredSeriesType": "line", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "lens_line_chart", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "7f3b5fb0-be2f-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-e84503c1-4dbd-4ac6-9ac9-ad938654680f", + "type": "index-pattern" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMzMSwxXQ==" +} + +{ + "attributes": { + "fieldAttrs": "{\"speaker\":{\"count\":1},\"text_entry\":{\"count\":6},\"type\":{\"count\":3}}", + "fields": "[]", + "runtimeFieldMap": "{}", + "title": "shakespeare" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "4e937b20-619d-11eb-aebf-c306684b328d", + "migrationVersion": { + "index-pattern": "8.0.0" + }, + "references": [], + "type": "index-pattern", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMzMiwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "d35680ce-c285-4fae-89d6-1245671bbc78": { + "columnOrder": [ + "2bcbffbe-c24d-4e74-8a03-9a6da7db70c0", + "6b00fde6-bfaa-4da1-beeb-bfd85a4cb2ff", + "8319857d-a03b-4158-bdf1-2a788e510445" + ], + "columns": { + "2bcbffbe-c24d-4e74-8a03-9a6da7db70c0": { + "dataType": "date", + "isBucketed": true, + "label": "@timestamp", + "operationType": "date_histogram", + "params": { + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + }, + "6b00fde6-bfaa-4da1-beeb-bfd85a4cb2ff": { + "dataType": "number", + "isBucketed": false, + "label": "Average of bytes", + "operationType": "average", + "scale": "ratio", + "sourceField": "bytes" + }, + "8319857d-a03b-4158-bdf1-2a788e510445": { + "dataType": "number", + "isBucketed": false, + "label": "Sum of bytes_scripted", + "operationType": "sum", + "params": { + "format": { + "id": "number", + "params": { + "decimals": 2 + } + } + }, + "scale": "ratio", + "sourceField": "bytes_scripted" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "layers": [ + { + "accessors": [ + "6b00fde6-bfaa-4da1-beeb-bfd85a4cb2ff", + "8319857d-a03b-4158-bdf1-2a788e510445" + ], + "layerId": "d35680ce-c285-4fae-89d6-1245671bbc78", + "layerType": "data", + "position": "top", + "seriesType": "area", + "showGridlines": false, + "xAccessor": "2bcbffbe-c24d-4e74-8a03-9a6da7db70c0", + "yConfig": [ + { + "axisMode": "auto", + "forAccessor": "8319857d-a03b-4158-bdf1-2a788e510445" + } + ] + } + ], + "legend": { + "isVisible": true, + "legendSize": "auto", + "position": "right" + }, + "preferredSeriesType": "area", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "lens_area_chart", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "4e937b20-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-d35680ce-c285-4fae-89d6-1245671bbc78", + "type": "index-pattern" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMzMywxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "70bd567e-8e67-4696-a406-313b06344fa9": { + "columnOrder": [ + "96ddedfb-043b-479e-a746-600e72ab546e", + "d325b7da-4266-4035-9b13-5f853615149a", + "2fc1391b-17d1-4c49-9ddc-06ff307e3520", + "1cc6f19c-cbcb-4abd-b56d-1a2f9deae5f3" + ], + "columns": { + "1cc6f19c-cbcb-4abd-b56d-1a2f9deae5f3": { + "dataType": "number", + "isBucketed": false, + "label": "Average of machine.ram", + "operationType": "average", + "scale": "ratio", + "sourceField": "machine.ram" + }, + "2fc1391b-17d1-4c49-9ddc-06ff307e3520": { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "scale": "ratio", + "sourceField": "___records___" + }, + "96ddedfb-043b-479e-a746-600e72ab546e": { + "dataType": "string", + "isBucketed": true, + "label": "Top values of machine.os.raw", + "operationType": "terms", + "params": { + "missingBucket": false, + "orderBy": { + "columnId": "2fc1391b-17d1-4c49-9ddc-06ff307e3520", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 3 + }, + "scale": "ordinal", + "sourceField": "machine.os.raw" + }, + "d325b7da-4266-4035-9b13-5f853615149a": { + "dataType": "date", + "isBucketed": true, + "label": "@timestamp", + "operationType": "date_histogram", + "params": { + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "layers": [ + { + "accessors": [ + "2fc1391b-17d1-4c49-9ddc-06ff307e3520", + "1cc6f19c-cbcb-4abd-b56d-1a2f9deae5f3" + ], + "layerId": "70bd567e-8e67-4696-a406-313b06344fa9", + "layerType": "data", + "position": "top", + "seriesType": "area_stacked", + "showGridlines": false, + "splitAccessor": "96ddedfb-043b-479e-a746-600e72ab546e", + "xAccessor": "d325b7da-4266-4035-9b13-5f853615149a" + } + ], + "legend": { + "isVisible": true, + "legendSize": "auto", + "position": "right" + }, + "preferredSeriesType": "area_stacked", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "lens_area_stacked", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "dd315430-be2f-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-70bd567e-8e67-4696-a406-313b06344fa9", + "type": "index-pattern" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMzNCwxXQ==" +} + +{ + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}" + }, + "optionsJSON": "{\"hidePanelTitles\":false,\"useMargins\":true}", + "panelsJSON": "[{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"2e80716f-c1b6-46f2-be2b-35db744b5031\"},\"panelIndex\":\"2e80716f-c1b6-46f2-be2b-35db744b5031\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsPie\",\"state\":{\"datasourceStates\":{\"formBased\":{\"layers\":{\"26e2cf99-d931-4320-9e15-9dbc148f3534\":{\"columns\":{\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\":{\"label\":\"Top values of url.raw\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"url.raw\",\"isBucketed\":true,\"params\":{\"size\":20,\"orderBy\":{\"type\":\"column\",\"columnId\":\"beb72af1-239c-46d8-823b-b00d1e2ace43\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"beb72af1-239c-46d8-823b-b00d1e2ace43\":{\"label\":\"Unique count of geo.srcdest\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"geo.srcdest\",\"isBucketed\":false}},\"columnOrder\":[\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"beb72af1-239c-46d8-823b-b00d1e2ace43\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"shape\":\"donut\",\"layers\":[{\"layerId\":\"26e2cf99-d931-4320-9e15-9dbc148f3534\",\"numberDisplay\":\"percent\",\"categoryDisplay\":\"default\",\"legendDisplay\":\"default\",\"nestedLegend\":false,\"layerType\":\"data\",\"legendSize\":\"auto\",\"primaryGroups\":[\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\"],\"metrics\":[\"beb72af1-239c-46d8-823b-b00d1e2ace43\"]}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534\"}]},\"enhancements\":{},\"type\":\"lens\"},\"panelRefName\":\"panel_2e80716f-c1b6-46f2-be2b-35db744b5031\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"da8843e0-6789-4aae-bcd0-81f270538719\"},\"panelIndex\":\"da8843e0-6789-4aae-bcd0-81f270538719\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_da8843e0-6789-4aae-bcd0-81f270538719\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":15,\"w\":24,\"h\":15,\"i\":\"adcd4418-7299-4efa-b369-5f71a7b4ebe0\"},\"panelIndex\":\"adcd4418-7299-4efa-b369-5f71a7b4ebe0\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_adcd4418-7299-4efa-b369-5f71a7b4ebe0\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"869754a7-edf0-478f-a7f1-80374f63108a\"},\"panelIndex\":\"869754a7-edf0-478f-a7f1-80374f63108a\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_869754a7-edf0-478f-a7f1-80374f63108a\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":30,\"w\":24,\"h\":15,\"i\":\"67111cf4-338e-453f-8621-e8dea64082d1\"},\"panelIndex\":\"67111cf4-338e-453f-8621-e8dea64082d1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_67111cf4-338e-453f-8621-e8dea64082d1\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":30,\"w\":24,\"h\":15,\"i\":\"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\"},\"panelIndex\":\"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":45,\"w\":24,\"h\":15,\"i\":\"88847944-ae1b-45fd-b102-3b45f9bea04b\"},\"panelIndex\":\"88847944-ae1b-45fd-b102-3b45f9bea04b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_88847944-ae1b-45fd-b102-3b45f9bea04b\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":45,\"w\":24,\"h\":15,\"i\":\"5a7924c7-eac0-4573-9199-fecec5b82e9e\"},\"panelIndex\":\"5a7924c7-eac0-4573-9199-fecec5b82e9e\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5a7924c7-eac0-4573-9199-fecec5b82e9e\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":60,\"w\":24,\"h\":15,\"i\":\"f8f49591-f071-4a96-b1ed-cd65daff5648\"},\"panelIndex\":\"f8f49591-f071-4a96-b1ed-cd65daff5648\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_f8f49591-f071-4a96-b1ed-cd65daff5648\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":60,\"w\":24,\"h\":15,\"i\":\"9f357f47-c2a0-421f-a456-9583c40837ab\"},\"panelIndex\":\"9f357f47-c2a0-421f-a456-9583c40837ab\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9f357f47-c2a0-421f-a456-9583c40837ab\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":75,\"w\":24,\"h\":15,\"i\":\"6cb383e9-1e80-44f9-80d5-7b8c585668db\"},\"panelIndex\":\"6cb383e9-1e80-44f9-80d5-7b8c585668db\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6cb383e9-1e80-44f9-80d5-7b8c585668db\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":75,\"w\":24,\"h\":15,\"i\":\"57f5f0bf-6610-4599-aad4-37484640b5e2\"},\"panelIndex\":\"57f5f0bf-6610-4599-aad4-37484640b5e2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_57f5f0bf-6610-4599-aad4-37484640b5e2\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":90,\"w\":24,\"h\":15,\"i\":\"32d3ab66-52e1-44e3-8c1f-1dccff3c5692\"},\"panelIndex\":\"32d3ab66-52e1-44e3-8c1f-1dccff3c5692\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_32d3ab66-52e1-44e3-8c1f-1dccff3c5692\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":90,\"w\":24,\"h\":15,\"i\":\"dd1718fd-74ee-4032-851b-db97e893825d\"},\"panelIndex\":\"dd1718fd-74ee-4032-851b-db97e893825d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_dd1718fd-74ee-4032-851b-db97e893825d\"},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":105,\"w\":24,\"h\":15,\"i\":\"98a556ee-078b-4e03-93a8-29996133cdcb\"},\"panelIndex\":\"98a556ee-078b-4e03-93a8-29996133cdcb\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsXY\",\"state\":{\"datasourceStates\":{\"formBased\":{\"layers\":{\"999a2d60-cb2a-451c-8d71-80d7e92e70fd\":{\"columns\":{\"ce9117a2-773c-474c-8fb1-18940cf58b38\":{\"label\":\"Top values of type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"type\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\"},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false}},\"a3d10552-e352-40d0-a156-e86112c0501a\":{\"label\":\"Top values of _type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"_type\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\"},\"9c5db2f3-9eb0-4667-9a74-3318301de251\":{\"label\":\"Sum of bytes\",\"dataType\":\"number\",\"operationType\":\"sum\",\"sourceField\":\"bytes\",\"isBucketed\":false,\"scale\":\"ratio\"}},\"columnOrder\":[\"ce9117a2-773c-474c-8fb1-18940cf58b38\",\"a3d10552-e352-40d0-a156-e86112c0501a\",\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\",\"9c5db2f3-9eb0-4667-9a74-3318301de251\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\",\"legendSize\":\"auto\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"999a2d60-cb2a-451c-8d71-80d7e92e70fd\",\"accessors\":[\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\",\"9c5db2f3-9eb0-4667-9a74-3318301de251\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"xAccessor\":\"ce9117a2-773c-474c-8fb1-18940cf58b38\",\"splitAccessor\":\"a3d10552-e352-40d0-a156-e86112c0501a\",\"layerType\":\"data\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-999a2d60-cb2a-451c-8d71-80d7e92e70fd\"}]},\"enhancements\":{},\"type\":\"lens\"}},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":105,\"w\":24,\"h\":15,\"i\":\"62a0f0b0-3589-4cef-807b-b1b4258b7a9b\"},\"panelIndex\":\"62a0f0b0-3589-4cef-807b-b1b4258b7a9b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_62a0f0b0-3589-4cef-807b-b1b4258b7a9b\"},{\"version\":\"7.13.1\",\"type\":\"map\",\"gridData\":{\"x\":0,\"y\":120,\"w\":24,\"h\":15,\"i\":\"dcc0defa-3376-465c-9b5b-2ba69528848c\"},\"panelIndex\":\"dcc0defa-3376-465c-9b5b-2ba69528848c\",\"embeddableConfig\":{\"mapCenter\":{\"lat\":19.94277,\"lon\":0,\"zoom\":1.56},\"mapBuffer\":{\"minLon\":-210.32666,\"minLat\":-64.8435,\"maxLon\":210.32666,\"maxLat\":95.13806},\"isLayerTOCOpen\":true,\"openTOCDetails\":[],\"hiddenLayers\":[],\"enhancements\":{}},\"panelRefName\":\"panel_dcc0defa-3376-465c-9b5b-2ba69528848c\"}]", + "refreshInterval": { + "pause": true, + "value": 0 + }, + "timeFrom": "2015-09-20T01:56:56.132Z", + "timeRestore": true, + "timeTo": "2015-09-21T11:18:20.471Z", + "title": "lens_maps_dashboard_logstash", + "version": 1 + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "16d86080-be5c-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "dashboard": "8.6.0" + }, + "references": [ + { + "id": "21905950-bd9f-11eb-9520-1b4c3ca6a781", + "name": "2e80716f-c1b6-46f2-be2b-35db744b5031:panel_2e80716f-c1b6-46f2-be2b-35db744b5031", + "type": "lens" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "2e80716f-c1b6-46f2-be2b-35db744b5031:indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "2e80716f-c1b6-46f2-be2b-35db744b5031:indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534", + "type": "index-pattern" + }, + { + "id": "aa4b8da0-bd9f-11eb-9520-1b4c3ca6a781", + "name": "da8843e0-6789-4aae-bcd0-81f270538719:panel_da8843e0-6789-4aae-bcd0-81f270538719", + "type": "lens" + }, + { + "id": "2d3f1250-bd9f-11eb-9520-1b4c3ca6a781", + "name": "adcd4418-7299-4efa-b369-5f71a7b4ebe0:panel_adcd4418-7299-4efa-b369-5f71a7b4ebe0", + "type": "lens" + }, + { + "id": "edd5a560-bda4-11eb-9520-1b4c3ca6a781", + "name": "869754a7-edf0-478f-a7f1-80374f63108a:panel_869754a7-edf0-478f-a7f1-80374f63108a", + "type": "lens" + }, + { + "id": "2c25a450-bda5-11eb-9520-1b4c3ca6a781", + "name": "67111cf4-338e-453f-8621-e8dea64082d1:panel_67111cf4-338e-453f-8621-e8dea64082d1", + "type": "lens" + }, + { + "id": "e79116e0-bd9e-11eb-9520-1b4c3ca6a781", + "name": "13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d:panel_13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d", + "type": "lens" + }, + { + "id": "974fb950-bda5-11eb-9520-1b4c3ca6a781", + "name": "88847944-ae1b-45fd-b102-3b45f9bea04b:panel_88847944-ae1b-45fd-b102-3b45f9bea04b", + "type": "lens" + }, + { + "id": "21905950-bd9f-11eb-9520-1b4c3ca6a781", + "name": "5a7924c7-eac0-4573-9199-fecec5b82e9e:panel_5a7924c7-eac0-4573-9199-fecec5b82e9e", + "type": "lens" + }, + { + "id": "51b63040-bda5-11eb-9520-1b4c3ca6a781", + "name": "f8f49591-f071-4a96-b1ed-cd65daff5648:panel_f8f49591-f071-4a96-b1ed-cd65daff5648", + "type": "lens" + }, + { + "id": "b00679c0-bda5-11eb-9520-1b4c3ca6a781", + "name": "9f357f47-c2a0-421f-a456-9583c40837ab:panel_9f357f47-c2a0-421f-a456-9583c40837ab", + "type": "lens" + }, + { + "id": "652ade10-bd9f-11eb-9520-1b4c3ca6a781", + "name": "6cb383e9-1e80-44f9-80d5-7b8c585668db:panel_6cb383e9-1e80-44f9-80d5-7b8c585668db", + "type": "lens" + }, + { + "id": "7f3b5fb0-be2f-11eb-9520-1b4c3ca6a781", + "name": "57f5f0bf-6610-4599-aad4-37484640b5e2:panel_57f5f0bf-6610-4599-aad4-37484640b5e2", + "type": "lens" + }, + { + "id": "bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781", + "name": "32d3ab66-52e1-44e3-8c1f-1dccff3c5692:panel_32d3ab66-52e1-44e3-8c1f-1dccff3c5692", + "type": "lens" + }, + { + "id": "dd315430-be2f-11eb-9520-1b4c3ca6a781", + "name": "dd1718fd-74ee-4032-851b-db97e893825d:panel_dd1718fd-74ee-4032-851b-db97e893825d", + "type": "lens" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "98a556ee-078b-4e03-93a8-29996133cdcb:indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "98a556ee-078b-4e03-93a8-29996133cdcb:indexpattern-datasource-layer-999a2d60-cb2a-451c-8d71-80d7e92e70fd", + "type": "index-pattern" + }, + { + "id": "0dbbf8b0-be3c-11eb-9520-1b4c3ca6a781", + "name": "62a0f0b0-3589-4cef-807b-b1b4258b7a9b:panel_62a0f0b0-3589-4cef-807b-b1b4258b7a9b", + "type": "lens" + }, + { + "id": "0c5974f0-be5c-11eb-9520-1b4c3ca6a781", + "name": "dcc0defa-3376-465c-9b5b-2ba69528848c:panel_dcc0defa-3376-465c-9b5b-2ba69528848c", + "type": "map" + }, + { + "id": "e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "name": "tag-e6994960-bd9e-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "dashboard", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMzNSwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "shakespeare_areachart", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"shakespeare_areachart\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"mode\":\"stacked\",\"type\":\"histogram\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"data\":{\"id\":\"2\",\"label\":\"Count\"},\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"legendSize\":\"auto\"},\"aggs\":[{\"id\":\"2\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"play_name\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"2\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"play_name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"2\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "185283c0-619e-11eb-aebf-c306684b328d", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "4e937b20-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMzNiwxXQ==" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "by_reference_logstash", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"by_reference_logstash\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{},\"style\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"},\"style\":{}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"radiusRatio\":0,\"addTooltip\":true,\"detailedTooltip\":true,\"palette\":{\"type\":\"palette\",\"name\":\"default\"},\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"legendSize\":\"auto\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2014-07-15T12:33:21.084Z\",\"to\":\"2019-01-28T03:18:12.440Z\"},\"useNormalizedEsInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"response.raw\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"},\"schema\":\"group\"}]}" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "1885abb0-ca2b-11eb-bf5e-3de94e83d4f0", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "56b34100-619d-11eb-aebf-c306684b328d", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMzNywxXQ==" +} + +{ + "attributes": { + "color": "#f44fcf", + "description": "", + "name": "shakespeare" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "42b4cec0-be32-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "tag": "8.0.0" + }, + "references": [], + "type": "tag", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMzOCwxXQ==" +} + +{ + "attributes": { + "description": "", + "state": { + "datasourceStates": { + "formBased": { + "layers": { + "3338dd55-4007-4be5-908d-25722b6174cb": { + "columnOrder": [ + "6c83b0c2-5834-4619-888c-9e8a08e47d42", + "b25e7497-c188-4c25-b002-1fd5bd69e76d" + ], + "columns": { + "6c83b0c2-5834-4619-888c-9e8a08e47d42": { + "dataType": "string", + "isBucketed": true, + "label": "Top values of speaker", + "operationType": "terms", + "params": { + "missingBucket": false, + "orderBy": { + "columnId": "b25e7497-c188-4c25-b002-1fd5bd69e76d", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": false, + "parentFormat": { + "id": "terms" + }, + "size": 90 + }, + "scale": "ordinal", + "sourceField": "speaker" + }, + "b25e7497-c188-4c25-b002-1fd5bd69e76d": { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "scale": "ratio", + "sourceField": "___records___" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layers": [ + { + "categoryDisplay": "default", + "layerId": "3338dd55-4007-4be5-908d-25722b6174cb", + "layerType": "data", + "legendDisplay": "default", + "legendSize": "auto", + "metrics": [ + "b25e7497-c188-4c25-b002-1fd5bd69e76d" + ], + "nestedLegend": false, + "numberDisplay": "percent", + "primaryGroups": [ + "6c83b0c2-5834-4619-888c-9e8a08e47d42", + "6c83b0c2-5834-4619-888c-9e8a08e47d42", + "6c83b0c2-5834-4619-888c-9e8a08e47d42" + ] + } + ], + "palette": { + "name": "complimentary", + "type": "palette" + }, + "shape": "treemap" + } + }, + "title": "lens_shakespeare_treemap", + "visualizationType": "lnsPie" + }, + "coreMigrationVersion": "8.7.0", + "created_at": "2022-12-15T11:42:57.737Z", + "id": "31e9f2f0-be32-11eb-9520-1b4c3ca6a781", + "migrationVersion": { + "lens": "8.6.0" + }, + "references": [ + { + "id": "4e937b20-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "4e937b20-619d-11eb-aebf-c306684b328d", + "name": "indexpattern-datasource-layer-3338dd55-4007-4be5-908d-25722b6174cb", + "type": "index-pattern" + }, + { + "id": "42b4cec0-be32-11eb-9520-1b4c3ca6a781", + "name": "tag-ref-42b4cec0-be32-11eb-9520-1b4c3ca6a781", + "type": "tag" + } + ], + "type": "lens", + "updated_at": "2022-12-15T11:42:57.737Z", + "version": "WzMzOSwxXQ==" +} diff --git a/x-pack/test/functional/services/dashboard/index.ts b/x-pack/test/functional/services/dashboard/index.ts index 21f4bd2f84965..8a97912563aaf 100644 --- a/x-pack/test/functional/services/dashboard/index.ts +++ b/x-pack/test/functional/services/dashboard/index.ts @@ -5,6 +5,4 @@ * 2.0. */ -export { DashboardDrilldownPanelActionsProvider } from './panel_drilldown_actions'; -export { DashboardDrilldownsManageProvider } from './drilldowns_manage'; export { DashboardPanelTimeRangeProvider } from './panel_time_range'; diff --git a/x-pack/test/functional/services/index.ts b/x-pack/test/functional/services/index.ts index 57bedddde13c3..aef5bb6523ac6 100644 --- a/x-pack/test/functional/services/index.ts +++ b/x-pack/test/functional/services/index.ts @@ -61,11 +61,7 @@ import { InfraSourceConfigurationFormProvider } from './infra_source_configurati import { LogsUiProvider } from './logs_ui'; import { MachineLearningProvider } from './ml'; import { TransformProvider } from './transform'; -import { - DashboardDrilldownPanelActionsProvider, - DashboardDrilldownsManageProvider, - DashboardPanelTimeRangeProvider, -} from './dashboard'; +import { DashboardPanelTimeRangeProvider } from './dashboard'; import { SearchSessionsService } from './search_sessions'; import { ObservabilityProvider } from './observability'; import { CasesServiceProvider } from './cases'; @@ -125,8 +121,6 @@ export const services = { logsUi: LogsUiProvider, ml: MachineLearningProvider, transform: TransformProvider, - dashboardDrilldownPanelActions: DashboardDrilldownPanelActionsProvider, - dashboardDrilldownsManage: DashboardDrilldownsManageProvider, dashboardPanelTimeRange: DashboardPanelTimeRangeProvider, reporting: ReportingFunctionalProvider, searchSessions: SearchSessionsService, diff --git a/x-pack/test/functional_with_es_ssl/apps/discover/search_source_alert.ts b/x-pack/test/functional_with_es_ssl/apps/discover/search_source_alert.ts index 58ce577c23fba..f583abef81994 100644 --- a/x-pack/test/functional_with_es_ssl/apps/discover/search_source_alert.ts +++ b/x-pack/test/functional_with_es_ssl/apps/discover/search_source_alert.ts @@ -258,8 +258,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await toasts.getToastCount()).to.be(0); } else { expect(await toasts.getToastCount()).to.be(1); - expect(await toasts.getToastContent(1)).to.equal( - `Displayed documents may vary\nThe displayed documents might differ from the documents that triggered the alert. Some documents might have been added or deleted.` + expect((await toasts.getToastContent(1)).startsWith('Displayed documents may vary')).to.be( + true ); } expect(await filterBar.getFilterCount()).to.be(0); @@ -306,16 +306,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await titleElem.getVisibleText()).to.equal(dataView); }; - // Failing: See https://github.com/elastic/kibana/issues/148388 - // Failing: See https://github.com/elastic/kibana/issues/148386 - // Failing: https://github.com/elastic/kibana/issues/147958 - // Failing: https://github.com/elastic/kibana/issues/148367 - // Failing: https://github.com/elastic/kibana/issues/148385 - // Failing: https://github.com/elastic/kibana/issues/148387 - // Failing: https://github.com/elastic/kibana/issues/148389 - // Failing: https://github.com/elastic/kibana/issues/148390 - // Failing: https://github.com/elastic/kibana/issues/148391 - describe.skip('Search source Alert', () => { + describe('Search source Alert', () => { before(async () => { await security.testUser.setRoles(['discover_alert']); @@ -372,6 +363,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await input.type('search-source-alert-o*'); await testSubjects.click('explore-matching-indices-button'); + await retry.waitFor('selection to happen', async () => { + const dataViewSelector = await testSubjects.find('selectDataViewExpression'); + return (await dataViewSelector.getVisibleText()) === 'DATA VIEW\nsearch-source-alert-o*'; + }); + await testSubjects.click('saveRuleButton'); const errorElem = await testSubjects.find('esQueryAlertExpressionError'); @@ -382,6 +378,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should navigate to alert results via view in app link', async () => { await testSubjects.click('selectDataViewExpression'); await testSubjects.click('indexPattern-switcher--input'); + if (await testSubjects.exists('clearSearchButton')) { + await testSubjects.click('clearSearchButton'); + } const dataViewsElem = await testSubjects.find('euiSelectableList'); const sourceDataViewOption = await dataViewsElem.findByCssSelector( `[title="${SOURCE_DATA_VIEW}"]` diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/opsgenie.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/opsgenie.ts index e88c776f498c6..27cd136cb40c7 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/opsgenie.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/opsgenie.ts @@ -138,7 +138,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await find.clickByCssSelector('[data-test-subj="testConnectorTab"]'); - expect(await (await testSubjects.find('executeActionButton')).isEnabled()).to.be(false); + expect(await testSubjects.isEnabled('executeActionButton')).to.be(false); }); describe('test page', () => { diff --git a/x-pack/test/osquery_cypress/artifact_manager.ts b/x-pack/test/osquery_cypress/artifact_manager.ts index 74097deb442cc..7ee2680e21f83 100644 --- a/x-pack/test/osquery_cypress/artifact_manager.ts +++ b/x-pack/test/osquery_cypress/artifact_manager.ts @@ -6,5 +6,5 @@ */ export async function getLatestVersion(): Promise { - return '8.5.1-SNAPSHOT'; + return '8.6.0-SNAPSHOT'; } diff --git a/x-pack/test/scalability/apis/api.core.capabilities.json b/x-pack/test/scalability/apis/api.core.capabilities.json new file mode 100644 index 0000000000000..cf1f50e306191 --- /dev/null +++ b/x-pack/test/scalability/apis/api.core.capabilities.json @@ -0,0 +1,46 @@ +{ + "journeyName": "POST /api/core/capabilities", + "scalabilitySetup": { + "warmup": [ + { + "action": "constantUsersPerSec", + "userCount": 10, + "duration": "30s" + } + ], + "test": [ + { + "action": "rampUsersPerSec", + "minUsersCount": 10, + "maxUsersCount": 250, + "duration": "4m" + } + ], + "maxDuration": "6m" + }, + "testData": { + "esArchives": [], + "kbnArchives": [] + }, + "streams": [ + { + "requests": [ + { + "http": { + "method": "POST", + "path": "/api/core/capabilities", + "query": "?useDefaultCapabilities=true", + "body": "{\"applications\":[\"error\",\"status\",\"kibana\",\"dev_tools\",\"r\",\"short_url_redirect\",\"home\",\"management\",\"space_selector\",\"security_access_agreement\",\"security_capture_url\",\"security_login\",\"security_logout\",\"security_logged_out\",\"security_overwritten_session\",\"security_account\",\"reportingRedirect\",\"graph\",\"discover\",\"integrations\",\"fleet\",\"ingestManager\",\"visualize\",\"canvas\",\"dashboards\",\"lens\",\"maps\",\"osquery\",\"observability-overview\",\"ml\",\"uptime\",\"synthetics\",\"securitySolutionUI\",\"siem\",\"logs\",\"metrics\",\"infra\",\"monitoring\",\"enterpriseSearch\",\"enterpriseSearchContent\",\"enterpriseSearchAnalytics\",\"elasticsearch\",\"appSearch\",\"workplaceSearch\",\"searchExperiences\",\"apm\",\"ux\",\"kibanaOverview\"]}", + "headers": { + "Cookie": "", + "Kbn-Version": "", + "Accept-Encoding": "gzip, deflate, br", + "Content-Type": "application/json" + }, + "statusCode": 200 + } + } + ] + } + ] +} diff --git a/x-pack/test/scalability/apis/api.metrics.vis.data.json b/x-pack/test/scalability/apis/api.metrics.vis.data.json new file mode 100644 index 0000000000000..d8b8d5e7ddbe9 --- /dev/null +++ b/x-pack/test/scalability/apis/api.metrics.vis.data.json @@ -0,0 +1,50 @@ +{ + "journeyName": "POST /api/metrics/vis/data", + "scalabilitySetup": { + "responseTimeThreshold": { + "threshold1": 5000, + "threshold2": 10000, + "threshold3": 30000 + }, + "warmup": [ + { + "action": "constantUsersPerSec", + "userCount": 10, + "duration": "30s" + } + ], + "test": [ + { + "action": "rampUsersPerSec", + "minUsersCount": 10, + "maxUsersCount": 250, + "duration": "4m" + } + ], + "maxDuration": "6m" + }, + "testData": { + "esArchives": ["x-pack/performance/es_archives/sample_data_ecommerce"], + "kbnArchives": ["x-pack/performance/kbn_archives/promotion_tracking_dashboard"] + }, + "streams": [ + { + "requests": [ + { + "http": { + "method": "POST", + "path": "/api/metrics/vis/data", + "headers": { + "Cookie": "", + "Kbn-Version": "", + "Accept-Encoding": "gzip, deflate, br", + "Content-Type": "application/json" + }, + "body": "{\"timerange\":{\"timezone\":\"UTC\",\"min\":\"2022-11-14T00:00:00.000Z\",\"max\":\"2022-12-14T17:17:09.931Z\"},\"query\":[{\"query\":\"\",\"language\":\"kuery\"}],\"filters\":[],\"panels\":[{\"time_range_mode\":\"entire_time_range\",\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"timeseries\",\"series\":[{\"id\":\"ea20ae70-b88d-11e8-a451-f37365e9f268\",\"color\":\"rgba(211,96,134,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"ea20ae71-b88d-11e8-a451-f37365e9f268\",\"type\":\"sum\",\"field\":\"taxful_total_price\"}],\"separate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":\"2\",\"point_size\":\"5\",\"fill\":\"0\",\"stacked\":\"none\",\"filter\":{\"query\":\"products.product_name:*trouser*\",\"language\":\"lucene\"},\"label\":\"Revenue Trousers\",\"value_template\":\"${{value}}\",\"split_color_mode\":\"gradient\"},{\"id\":\"062d77b0-b88e-11e8-a451-f37365e9f268\",\"color\":\"rgba(84,179,153,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"062d77b1-b88e-11e8-a451-f37365e9f268\",\"type\":\"sum\",\"field\":\"taxful_total_price\"}],\"separate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":\"2\",\"point_size\":\"05\",\"fill\":\"0\",\"stacked\":\"none\",\"filter\":{\"query\":\"products.product_name:*watch*\",\"language\":\"lucene\"},\"label\":\"Revenue Watches\",\"value_template\":\"${{value}}\",\"split_color_mode\":\"gradient\"},{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"rgba(96,146,192,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"sum\",\"field\":\"taxful_total_price\"}],\"separate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":\"2\",\"point_size\":\"5\",\"fill\":\"0\",\"stacked\":\"none\",\"filter\":{\"query\":\"products.product_name:*bag*\",\"language\":\"lucene\"},\"label\":\"Revenue Bags\",\"value_template\":\"${{value}}\",\"split_color_mode\":\"gradient\"},{\"id\":\"faa2c170-b88d-11e8-a451-f37365e9f268\",\"color\":\"rgba(202,142,174,1)\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"faa2c171-b88d-11e8-a451-f37365e9f268\",\"type\":\"sum\",\"field\":\"taxful_total_price\"}],\"separate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":\"2\",\"point_size\":\"5\",\"fill\":\"0\",\"stacked\":\"none\",\"filter\":{\"query\":\"products.product_name:*cocktail dress*\",\"language\":\"lucene\"},\"label\":\"Revenue Cocktail Dresses\",\"value_template\":\"${{value}}\",\"split_color_mode\":\"gradient\"}],\"time_field\":\"order_date\",\"interval\":\"12h\",\"use_kibana_indexes\":true,\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"axis_scale\":\"normal\",\"show_legend\":1,\"show_grid\":1,\"legend_position\":\"bottom\",\"annotations\":[{\"fields\":\"taxful_total_price\",\"template\":\"Ring the bell! ${{taxful_total_price}}\",\"query_string\":{\"query\":\"taxful_total_price:>250\",\"language\":\"lucene\"},\"id\":\"c8c30be0-b88f-11e8-a451-f37365e9f268\",\"color\":\"rgba(25,77,51,1)\",\"time_field\":\"order_date\",\"icon\":\"fa-bell\",\"ignore_global_filters\":1,\"ignore_panel_filters\":1,\"index_pattern\":{\"id\":\"ff959d40-b880-11e8-a6d9-e546fe2bba5f\"}}],\"tooltip_mode\":\"show_all\",\"drop_last_bucket\":0,\"isModelInvalid\":false,\"index_pattern\":{\"id\":\"ff959d40-b880-11e8-a6d9-e546fe2bba5f\"},\"truncate_legend\":1,\"max_lines_legend\":1}],\"state\":{},\"searchSession\":{\"sessionId\":\"8c3dfba6-dcf9-4402-aa7c-3b36fd9bda0c\",\"isRestore\":false,\"isStored\":false}}", + "statusCode": 200 + } + } + ] + } + ] +} diff --git a/x-pack/test/scalability/apis/api.saved_objects_tagging.tags.json b/x-pack/test/scalability/apis/api.saved_objects_tagging.tags.json new file mode 100644 index 0000000000000..8fdd63609e742 --- /dev/null +++ b/x-pack/test/scalability/apis/api.saved_objects_tagging.tags.json @@ -0,0 +1,51 @@ +{ + "journeyName": "GET /api/saved_objects_tagging/tags", + "scalabilitySetup": { + "warmup": [ + { + "action": "constantUsersPerSec", + "userCount": 10, + "duration": "30s" + } + ], + "test": [ + { + "action": "rampUsersPerSec", + "minUsersCount": 10, + "maxUsersCount": 600, + "duration": "275s" + } + ], + "maxDuration": "7m" + }, + "testData": { + "esArchives": [], + "kbnArchives": [ + "x-pack/test/functional/fixtures/kbn_archiver/saved_objects_management/saved_objects_mix.json" + ] + }, + "streams": [ + { + "requests": [ + { + "date": "2022-11-14T09:31:49.963Z", + "http": { + "method": "GET", + "path": "/api/saved_objects_tagging/tags", + "headers": { + "Cookie": "sid=Fe26.2**b4f51707bfe081641d5680f3564a6294e67", + "Kbn-Version": "8.7.0-SNAPSHOT", + "Kbn-System-Request": "true", + "Referer": "http://localhost:5620/app/home", + "X-Kbn-Context": "%7B%22name%22%3A%22home%22%2C%22url%22%3A%22%2Fapp%2Fhome%22%7D", + "Host": "localhost:5620", + "Accept-Encoding": "gzip, deflate, br", + "Content-Type": "application/json" + }, + "statusCode": 200 + } + } + ] + } + ] +} diff --git a/x-pack/test/scalability/apis/api.telemetry.cluster_stats.json b/x-pack/test/scalability/apis/api.telemetry.cluster_stats.json new file mode 100644 index 0000000000000..8d70cf1b677cc --- /dev/null +++ b/x-pack/test/scalability/apis/api.telemetry.cluster_stats.json @@ -0,0 +1,45 @@ +{ + "journeyName": "POST /api/telemetry/v2/clusters/_stats", + "scalabilitySetup": { + "warmup": [ + { + "action": "constantUsersPerSec", + "userCount": 10, + "duration": "30s" + } + ], + "test": [ + { + "action": "rampUsersPerSec", + "minUsersCount": 10, + "maxUsersCount": 490, + "duration": "4m" + } + ], + "maxDuration": "6m" + }, + "testData": { + "esArchives": [], + "kbnArchives": [] + }, + "streams": [ + { + "requests": [ + { + "http": { + "method": "POST", + "path": "/api/telemetry/v2/clusters/_stats", + "body": "{}", + "headers": { + "Cookie": "", + "Kbn-Version": "", + "Accept-Encoding": "gzip, deflate, br", + "Content-Type": "application/json" + }, + "statusCode": 200 + } + } + ] + } + ] +} diff --git a/x-pack/test/scalability/apis/bundles.core.entry.json b/x-pack/test/scalability/apis/bundles.core.entry.json new file mode 100644 index 0000000000000..8d0bc666d88f3 --- /dev/null +++ b/x-pack/test/scalability/apis/bundles.core.entry.json @@ -0,0 +1,46 @@ +{ + "journeyName": "GET /{buildNumber}/bundles/core/core.entry.js", + "scalabilitySetup": { + "responseTimeThreshold": { + "threshold1": 1000, + "threshold2": 3000, + "threshold3": 5000 + }, + "warmup": [ + { + "action": "constantUsersPerSec", + "userCount": 10, + "duration": "30s" + } + ], + "test": [ + { + "action": "rampUsersPerSec", + "minUsersCount": 10, + "maxUsersCount": 1400, + "duration": "278s" + } + ], + "maxDuration": "6m" + }, + "testData": { + "esArchives": [], + "kbnArchives": [] + }, + "streams": [ + { + "requests": [ + { + "http": { + "method": "GET", + "path": "/{buildNumber}/bundles/core/core.entry.js", + "headers": { + "Accept-Encoding": "gzip, deflate, br" + }, + "statusCode": 200 + } + } + ] + } + ] +} diff --git a/x-pack/test/scalability/apis/internal.security.session.json b/x-pack/test/scalability/apis/internal.security.session.json new file mode 100644 index 0000000000000..453ae2da989ad --- /dev/null +++ b/x-pack/test/scalability/apis/internal.security.session.json @@ -0,0 +1,44 @@ +{ + "journeyName": "GET /internal/security/session", + "scalabilitySetup": { + "warmup": [ + { + "action": "constantUsersPerSec", + "userCount": 10, + "duration": "30s" + } + ], + "test": [ + { + "action": "rampUsersPerSec", + "minUsersCount": 10, + "maxUsersCount": 700, + "duration": "345s" + } + ], + "maxDuration": "8m" + }, + "testData": { + "esArchives": [], + "kbnArchives": [] + }, + "streams": [ + { + "requests": [ + { + "http": { + "method": "GET", + "path": "/internal/security/session", + "headers": { + "Cookie": "", + "Kbn-Version": "", + "Accept-Encoding": "gzip, deflate, br", + "Content-Type": "application/json" + }, + "statusCode": 200 + } + } + ] + } + ] +} diff --git a/x-pack/test/scalability/apis/internal.security.user_profile.json b/x-pack/test/scalability/apis/internal.security.user_profile.json new file mode 100644 index 0000000000000..a80f578dc7c44 --- /dev/null +++ b/x-pack/test/scalability/apis/internal.security.user_profile.json @@ -0,0 +1,45 @@ +{ + "journeyName": "GET /internal/security/user_profile", + "scalabilitySetup": { + "warmup": [ + { + "action": "constantUsersPerSec", + "userCount": 10, + "duration": "30s" + } + ], + "test": [ + { + "action": "rampUsersPerSec", + "minUsersCount": 10, + "maxUsersCount": 700, + "duration": "345s" + } + ], + "maxDuration": "8m" + }, + "testData": { + "esArchives": [], + "kbnArchives": [] + }, + "streams": [ + { + "requests": [ + { + "http": { + "method": "GET", + "path": "/internal/security/user_profile", + "query": "?dataPath=avatar", + "headers": { + "Cookie": "", + "Kbn-Version": "", + "Accept-Encoding": "gzip, deflate, br", + "Content-Type": "application/json" + }, + "statusCode": 200 + } + } + ] + } + ] +} diff --git a/x-pack/test/scalability/apis/security.me.json b/x-pack/test/scalability/apis/security.me.json new file mode 100644 index 0000000000000..23111ecef3564 --- /dev/null +++ b/x-pack/test/scalability/apis/security.me.json @@ -0,0 +1,44 @@ +{ + "journeyName": "GET /internal/security/me", + "scalabilitySetup": { + "warmup": [ + { + "action": "constantUsersPerSec", + "userCount": 10, + "duration": "30s" + } + ], + "test": [ + { + "action": "rampUsersPerSec", + "minUsersCount": 10, + "maxUsersCount": 1000, + "duration": "198s" + } + ], + "maxDuration": "5m" + }, + "testData": { + "esArchives": [], + "kbnArchives": [] + }, + "streams": [ + { + "requests": [ + { + "http": { + "method": "GET", + "path": "/internal/security/me", + "headers": { + "Cookie": "", + "Kbn-Version": "", + "Accept-Encoding": "gzip, deflate, br", + "Content-Type": "application/json" + }, + "statusCode": 200 + } + } + ] + } + ] +} diff --git a/x-pack/test/scalability/config.ts b/x-pack/test/scalability/config.ts index 490b44705bb18..615a111195831 100644 --- a/x-pack/test/scalability/config.ts +++ b/x-pack/test/scalability/config.ts @@ -12,10 +12,15 @@ import path from 'path'; import { REPO_ROOT } from '@kbn/repo-info'; import { createFlagError } from '@kbn/dev-cli-errors'; import { commonFunctionalServices } from '@kbn/ftr-common-functional-services'; +import { v4 as uuidV4 } from 'uuid'; import { ScalabilityTestRunner } from './runner'; import { FtrProviderContext } from './ftr_provider_context'; +import { ScalabilityJourney } from './types'; // These "secret" values are intentionally written in the source. +const APM_SERVER_URL = 'https://142fea2d3047486e925eb8b223559cae.apm.europe-west1.gcp.cloud.es.io'; +const APM_PUBLIC_TOKEN = 'pWFFEym07AKBBhUE2i'; + const AGGS_SHARD_DELAY = process.env.LOAD_TESTING_SHARD_DELAY; const DISABLE_PLUGINS = process.env.LOAD_TESTING_DISABLE_PLUGINS; const scalabilityJsonPath = process.env.SCALABILITY_JOURNEY_PATH; @@ -36,6 +41,8 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ); } + const journey: ScalabilityJourney = JSON.parse(fs.readFileSync(scalabilityJsonPath, 'utf8')); + const baseConfig = ( await readConfigFile(require.resolve('../../performance/journeys/login.ts')) ).getAll(); @@ -63,6 +70,29 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...(!!AGGS_SHARD_DELAY ? ['--data.search.aggs.shardDelay.enabled=true'] : []), ...(!!DISABLE_PLUGINS ? ['--plugins.initialize=false'] : []), ], + env: { + ELASTIC_APM_ACTIVE: true, + ELASTIC_APM_CENTRAL_CONFIG: false, + ELASTIC_APM_TRANSACTION_SAMPLE_RATE: '0.1', + ELASTIC_APM_BREAKDOWN_METRICS: false, + ELASTIC_APM_CAPTURE_SPAN_STACK_TRACES: false, + ELASTIC_APM_METRICS_INTERVAL: '120s', + ELASTIC_APM_MAX_QUEUE_SIZE: 20480, + ELASTIC_APM_ENVIRONMENT: process.env.CI ? 'ci' : 'development', + ELASTIC_APM_SERVER_URL: APM_SERVER_URL, + ELASTIC_APM_SECRET_TOKEN: APM_PUBLIC_TOKEN, + ELASTIC_APM_GLOBAL_LABELS: Object.entries({ + testBuildId: process.env.BUILDKITE_BUILD_ID ?? `local-${uuidV4()}`, + testJobId: process.env.BUILDKITE_JOB_ID ?? `local-${uuidV4()}`, + journeyName: journey.journeyName, + ftrConfig: path.basename(scalabilityJsonPath), + branch: process.env.BUILDKITE_BRANCH, + gitRev: process.env.BUILDKITE_COMMIT, + ciBuildName: process.env.BUILDKITE_PIPELINE_SLUG, + }) + .flatMap(([key, value]) => (value == null ? [] : `${key}=${value}`)) + .join(','), + }, }, }; } diff --git a/x-pack/test/scalability/events_shipper.ts b/x-pack/test/scalability/events_shipper.ts new file mode 100644 index 0000000000000..e0a4e91736ae9 --- /dev/null +++ b/x-pack/test/scalability/events_shipper.ts @@ -0,0 +1,54 @@ +/* + * 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 { ToolingLog } from '@kbn/tooling-log'; +import fetch from 'node-fetch'; +import { MetricEvent } from './types'; + +const eventsToNDJSON = (events: MetricEvent[]) => { + return `${events.map((event) => JSON.stringify(event)).join('\n')}\n`; +}; + +const buildHeaders = (clusterUuid: string, version: string) => { + return { + 'content-type': 'application/x-ndjson', + 'x-elastic-cluster-id': clusterUuid, + 'x-elastic-stack-version': version, + }; +}; + +export class EventsShipper { + url: string; + clusterUuid: string; + version: string; + log: ToolingLog; + + constructor(url: string, clusterUuid: string, version: string, log: ToolingLog) { + this.url = url; + this.clusterUuid = clusterUuid; + this.version = version; + this.log = log; + } + + async send(events: MetricEvent[]) { + const body = eventsToNDJSON(events); + + if (process.env.BUILDKITE_BUILD_ID) { + const response = await fetch(this.url, { + method: 'POST', + body, + headers: buildHeaders(this.clusterUuid, this.version), + }); + + if (!response.ok) { + throw new Error(`Telemetry sending error: ${response.status} - ${await response.text()}`); + } else { + this.log.debug(`Telemetry cluster response status: ${response.status}`); + } + } + } +} diff --git a/x-pack/test/scalability/report_parser.ts b/x-pack/test/scalability/report_parser.ts new file mode 100644 index 0000000000000..796c732f6a932 --- /dev/null +++ b/x-pack/test/scalability/report_parser.ts @@ -0,0 +1,210 @@ +/* + * 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 { ToolingLog } from '@kbn/tooling-log'; +import fs from 'fs'; +import { ScalabilitySetup, ResponseTimeMetric } from '@kbn/journeys'; +import { CapacityMetrics, DataPoint, ResponseMetric, RpsMetric } from './types'; + +const RESPONSE_METRICS_NAMES = [ + 'min', + '25%', + '50%', + '75%', + '80%', + '85%', + '90%', + '95%', + '99%', + 'max', +]; +const DEFAULT_THRESHOLD = { + threshold1: 3000, + threshold2: 6000, + threshold3: 12000, +}; +const DEFAULT_METRIC = '85%'; +const REQUESTS_REGEXP = /(?<=var requests = unpack\(\[)(.*)(?=\]\);)/g; +const RESPONSES_PERCENTILES_REGEXP = + /(?<=var responsetimepercentilesovertimeokPercentiles = unpack\(\[)(.*)(?=\]\);)/g; + +/** + * Returns Rps value for time point when response time is over threshold first time for specific metric + * @param rpsData Rps dataset + * @param responseTimeData Response time dataset + * @param responseTimeThreshold Response time threshold + * @param metricName Gatling response metric to compare with threshold + * @param log logger + * @returns + */ +const getRPSByResponseTime = ( + rpsData: RpsMetric[], + responseTimeData: ResponseMetric[], + responseTimeThreshold: number, + metricName: ResponseTimeMetric, + log: ToolingLog +) => { + const timestamp = getTimePoint(responseTimeData, metricName, responseTimeThreshold, log); + if (timestamp === -1) { + // Data point was not found, most likely 'responseTimeThreshold' should be adjusted + // Returning '0' as invalid result + return 0; + } else { + const rps = rpsData.find((i) => i.timestamp === timestamp)?.value; + // In edge case Gatling might fail to report requests for specific timestamp, returning '0' as invalid result + return !rps ? 0 : rps; + } +}; + +const parseData = (str: string, regex: RegExp) => { + const found = str.match(regex); + if (found == null) { + throw Error('Failed to parse Html string'); + } + return found[0] + .replaceAll('],[', '].[') + .split('.') + .map((i) => { + const pair = i + .replaceAll(',[', '.[') + .replaceAll(/^\[/g, '') + .replaceAll(/\]$/g, '') + .split('.'); + const arr = pair[1]?.replaceAll(/^\[/g, '')?.replaceAll(/\]$/g, ''); + const values: number[] = !arr ? [] : arr.split(',').map(Number); + return { timestamp: parseInt(pair[0], 10), values }; + }); +}; + +/** + * Returns timestamp for the first response time entry above the threshold + * @param data Response time dataset + * @param metricName Gatling response metric to compare with threshold + * @param responseTimeValue Response time threshold + * @param log logger + * @returns + */ +const getTimePoint = ( + data: ResponseMetric[], + metricName: ResponseTimeMetric, + responseTimeValue: number, + log: ToolingLog +) => { + const resultsAboveThreshold = data.filter((i) => i.metrics[metricName] >= responseTimeValue); + if (resultsAboveThreshold.length === data.length) { + log.debug(`Threshold '${responseTimeValue} is too low for '${metricName}' metric'`); + return -1; + } else if (resultsAboveThreshold.length === 0) { + log.debug(`Threshold '${responseTimeValue} is too high for '${metricName}' metric'`); + return -1; + } else { + return resultsAboveThreshold[0].timestamp; + } +}; + +const mapValuesWithMetrics = (data: DataPoint[], metrics: string[]) => { + return data + .filter((i) => i.values.length === metrics.length) + .map((i) => { + return { + timestamp: i.timestamp, + metrics: Object.fromEntries(metrics.map((_, index) => [metrics[index], i.values[index]])), + }; + }); +}; + +export function getCapacityMetrics( + htmlReportPath: string, + scalabilitySetup: ScalabilitySetup, + log: ToolingLog +): CapacityMetrics { + const htmlContent = fs.readFileSync(htmlReportPath, 'utf-8'); + // [timestamp, [activeUsers,requests,0]], e.g. [1669026394,[6,6,0]] + const requests = parseData(htmlContent, REQUESTS_REGEXP); + // [timestamp, [min, 25%, 50%, 75%, 80%, 85%, 90%, 95%, 99%, max]], e.g. 1669026394,[9,11,11,12,13,13,14,15,15,16] + const responsePercentiles = parseData(htmlContent, RESPONSES_PERCENTILES_REGEXP); + + const metricName = scalabilitySetup.responseTimeMetric || DEFAULT_METRIC; + // warmup phase duration in seconds + const warmupDuration = scalabilitySetup.warmup + .map((action) => { + const parsedValue = parseInt(action.duration.replace(/s|m/, ''), 10); + return action.duration.endsWith('m') ? parsedValue * 60 : parsedValue; + }) + .reduce((a, b) => a + b, 0); + + const warmupData = mapValuesWithMetrics( + responsePercentiles.slice(0, warmupDuration), + RESPONSE_METRICS_NAMES + ); + const testData = mapValuesWithMetrics( + responsePercentiles.slice(warmupDuration, responsePercentiles.length - 1), + RESPONSE_METRICS_NAMES + ); + const rpsData = requests.map((r) => { + return { timestamp: r.timestamp, value: r.values.length > 0 ? r.values[0] : 0 }; + }); + + const rpsMax = Math.max(...rpsData.map((i) => i.value)); + + const warmupAvgResponseTime = Math.round( + warmupData + .map((i) => i.metrics[metricName]) + .reduce((avg, value, _, { length }) => { + return avg + value / length; + }, 0) + ); + const rpsAtWarmup = Math.round( + rpsData.slice(0, warmupDuration).reduce((avg, rps, _, { length }) => { + return avg + rps.value / length; + }, 0) + ); + log.info( + `Warmup: Avg ${metricName} pct response time - ${warmupAvgResponseTime} ms, avg rps=${rpsAtWarmup}` + ); + + // Collected response time metrics: 3 pre-defined thresholds + const thresholds = scalabilitySetup.responseTimeThreshold || DEFAULT_THRESHOLD; + + const rpsAtThreshold1 = getRPSByResponseTime( + rpsData, + testData, + thresholds.threshold1, + metricName, + log + ); + + const rpsAtThreshold2 = getRPSByResponseTime( + rpsData, + testData, + thresholds.threshold2, + metricName, + log + ); + + const rpsAtThreshold3 = getRPSByResponseTime( + rpsData, + testData, + thresholds.threshold3, + metricName, + log + ); + + return { + warmupAvgResponseTime, + rpsAtWarmup, + warmupDuration, + rpsMax, + responseTimeMetric: metricName, + threshold1ResponseTime: thresholds.threshold1, + rpsAtThreshold1, + threshold2ResponseTime: thresholds.threshold2, + rpsAtThreshold2, + threshold3ResponseTime: thresholds.threshold3, + rpsAtThreshold3, + }; +} diff --git a/x-pack/test/scalability/runner.ts b/x-pack/test/scalability/runner.ts index 5882237ade467..e9468f698b22a 100644 --- a/x-pack/test/scalability/runner.ts +++ b/x-pack/test/scalability/runner.ts @@ -6,8 +6,58 @@ */ import { withProcRunner } from '@kbn/dev-proc-runner'; +// @ts-expect-error we have to check types with "allowJs: false" for now, causing this import to fail +import { kibanaPackageJson } from '@kbn/repo-info'; import path from 'path'; +import fs from 'fs'; +import { ToolingLog } from '@kbn/tooling-log'; import { FtrProviderContext } from './ftr_provider_context'; +import { EventsShipper } from './events_shipper'; +import { getCapacityMetrics } from './report_parser'; +import { ScalabilityJourney, MetricEvent } from './types'; + +const telemetryChannel = 'scalability-metrics'; + +async function sendReportMetricsToTelemetry( + gatlingProjectRootPath: string, + scalabilityJsonPath: string, + log: ToolingLog +) { + const reportRootPath = path.resolve(gatlingProjectRootPath, 'target', 'gatling'); + const fileName = path.basename(scalabilityJsonPath, path.extname(scalabilityJsonPath)); + const journeyReportDir = fs.readdirSync(reportRootPath).filter((f) => f.startsWith(fileName)); + const lastReportPath = journeyReportDir.pop(); + if (lastReportPath) { + const journeyHtmlReportPath = path.resolve(reportRootPath, lastReportPath, 'index.html'); + + const journey: ScalabilityJourney = JSON.parse(fs.readFileSync(scalabilityJsonPath, 'utf8')); + const metrics = getCapacityMetrics(journeyHtmlReportPath, journey.scalabilitySetup, log); + const events: MetricEvent[] = [ + { + ...metrics, + eventType: 'scalability_metric', + eventName: 'capacity_test_summary', + journeyName: journey.journeyName, + kibanaVersion: kibanaPackageJson.version, + branch: process.env.BUILDKITE_BRANCH, + ciBuildId: process.env.BUILDKITE_BUILD_ID, + ciBuildJobId: process.env.BUILDKITE_JOB_ID, + ciBuildNumber: Number(process.env.BUILDKITE_BUILD_NUMBER) || 0, + ciBuildName: process.env.BUILDKITE_PIPELINE_SLUG, + gitRev: process.env.BUILDKITE_COMMIT, + }, + ]; + log.info(`Sending event: ${JSON.stringify(events)}`); + const shipper = new EventsShipper( + `https://telemetry-staging.elastic.co/v3/send/${telemetryChannel}?debug=true`, + 'scalability-test', + '1', + log + ); + + await shipper.send(events); + } +} /** * ScalabilityTestRunner is used to run load simulation against local Kibana instance @@ -41,4 +91,6 @@ export async function ScalabilityTestRunner( wait: true, }); }); + + await sendReportMetricsToTelemetry(gatlingProjectRootPath, scalabilityJsonPath, log); } diff --git a/x-pack/test/scalability/types.ts b/x-pack/test/scalability/types.ts new file mode 100644 index 0000000000000..1b57ad519a8a4 --- /dev/null +++ b/x-pack/test/scalability/types.ts @@ -0,0 +1,61 @@ +/* + * 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 { ScalabilitySetup } from '@kbn/journeys'; + +export interface ScalabilityJourney { + journeyName: string; + scalabilitySetup: ScalabilitySetup; + testData?: { + esArchives: string[]; + kbnArchives: string[]; + }; +} + +export interface CapacityMetrics { + warmupAvgResponseTime: number; + rpsAtWarmup: number; + warmupDuration: number; + rpsMax: number; + responseTimeMetric: string; + threshold1ResponseTime: number; + rpsAtThreshold1: number; + threshold2ResponseTime: number; + rpsAtThreshold2: number; + threshold3ResponseTime: number; + rpsAtThreshold3: number; +} + +export interface MetricEvent extends CapacityMetrics { + eventName: string; + eventType: string; + journeyName: string; + kibanaVersion: string; + branch: string | undefined; + ciBuildId: string | undefined; + ciBuildJobId: string | undefined; + ciBuildName: string | undefined; + ciBuildNumber: number; + gitRev: string | undefined; +} + +export interface RpsMetric { + timestamp: number; + value: number; +} + +export interface ResponseMetric { + timestamp: number; + metrics: { + [k: string]: number; + }; +} + +export interface DataPoint { + timestamp: number; + values: number[]; +} diff --git a/x-pack/test/security_functional/screenshots/baseline/reset_session_page.png b/x-pack/test/security_functional/screenshots/baseline/reset_session_page.png new file mode 100644 index 0000000000000..8ef70d4bf357a Binary files /dev/null and b/x-pack/test/security_functional/screenshots/baseline/reset_session_page.png differ diff --git a/x-pack/test/security_functional/tests/login_selector/index.ts b/x-pack/test/security_functional/tests/login_selector/index.ts index bf3cc557f0bd7..ae81b307987cc 100644 --- a/x-pack/test/security_functional/tests/login_selector/index.ts +++ b/x-pack/test/security_functional/tests/login_selector/index.ts @@ -11,5 +11,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('security app - login selector', function () { loadTestFile(require.resolve('./basic_functionality')); loadTestFile(require.resolve('./auth_provider_hint')); + loadTestFile(require.resolve('./reset_session_page')); }); } diff --git a/x-pack/test/security_functional/tests/login_selector/reset_session_page.ts b/x-pack/test/security_functional/tests/login_selector/reset_session_page.ts new file mode 100644 index 0000000000000..e4a9321b4b6f7 --- /dev/null +++ b/x-pack/test/security_functional/tests/login_selector/reset_session_page.ts @@ -0,0 +1,55 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects, updateBaselines }: FtrProviderContext) { + const screenshots = getService('screenshots'); + const browser = getService('browser'); + const security = getService('security'); + const PageObjects = getPageObjects(['security', 'common']); + + describe('reset session page', function () { + const userWithoutPermissions = { username: 'user_without_permissions', password: 'changeme' }; + + before(async () => { + // We use a really small window to minimize differences across os's and browsers. + await browser.setScreenshotSize(1000, 500); + + await security.user.create(userWithoutPermissions.username, { + password: userWithoutPermissions.password, + roles: [], + }); + }); + + beforeEach(async () => { + // Logout needs to happen before anything else to avoid flaky behavior + await PageObjects.security.forceLogout(); + }); + + after(async () => { + // Clean up after ourselves + await security.user.delete(userWithoutPermissions.username); + await PageObjects.security.forceLogout(); + }); + + it('compare screenshot', async () => { + await PageObjects.security.loginSelector.login('basic', 'basic1', { + username: userWithoutPermissions.username, + password: userWithoutPermissions.password, + expectedLoginResult: 'error', + }); + + const percentDifference = await screenshots.compareAgainstBaseline( + 'reset_session_page', + updateBaselines + ); + expect(percentDifference).to.be.lessThan(0.022); + }); + }); +} diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts index 92ce0a8aaf6d9..2d33467b2dfb5 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts @@ -82,7 +82,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { return tableData; }; - describe('endpoint list', function () { + // Failing: See https://github.com/elastic/kibana/issues/148111 + describe.skip('endpoint list', function () { const sleep = (ms = 100) => new Promise((resolve) => setTimeout(resolve, ms)); let indexedData: IndexedHostsAndAlertsResponse; describe('when initially navigating to page', () => { diff --git a/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts b/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts index db2f12694ac7c..45d7b4226cf00 100644 --- a/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts +++ b/x-pack/test/security_solution_endpoint/services/endpoint_policy.ts @@ -14,9 +14,10 @@ import { PACKAGE_POLICY_SAVED_OBJECT_TYPE, DeleteAgentPolicyRequest, DeletePackagePoliciesRequest, + epmRouteService, GetPackagePoliciesResponse, GetFullAgentPolicyResponse, - GetPackagesResponse, + type GetInfoResponse, } from '@kbn/fleet-plugin/common'; import { policyFactory } from '@kbn/security-solution-plugin/common/endpoint/models/policy_config'; import { Immutable } from '@kbn/security-solution-plugin/common/endpoint/types'; @@ -31,9 +32,6 @@ const INGEST_API_AGENT_POLICIES = `${INGEST_API_ROOT}/agent_policies`; const INGEST_API_AGENT_POLICIES_DELETE = `${INGEST_API_AGENT_POLICIES}/delete`; const INGEST_API_PACKAGE_POLICIES = `${INGEST_API_ROOT}/package_policies`; const INGEST_API_PACKAGE_POLICIES_DELETE = `${INGEST_API_PACKAGE_POLICIES}/delete`; -const INGEST_API_EPM_PACKAGES = `${INGEST_API_ROOT}/epm/packages`; - -const SECURITY_PACKAGES_ROUTE = `${INGEST_API_EPM_PACKAGES}?category=security&prerelease=true`; /** * Holds information about the test resources created to support an Endpoint Policy @@ -48,7 +46,7 @@ export interface PolicyTestResourceInfo { /** * Information about the endpoint package */ - packageInfo: Immutable; + packageInfo: Immutable; /** will clean up (delete) the objects created (Agent Policy + Package Policy) */ cleanup: () => Promise; } @@ -72,18 +70,19 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC // so we'll retrieve a list of packages for a category of Security, and will then find the // endpoint package info. in the list. The request is kicked off here, but handled below after // Agent Policy creation so that they can be executed concurrently - let apiRequest: Promise; + let apiRequest: Promise; + const path = epmRouteService.getInfoPath('endpoint'); return () => { if (!apiRequest) { - log.info(`Setting up call to retrieve Endpoint package from ${SECURITY_PACKAGES_ROUTE}`); + log.info(`Setting up call to retrieve Endpoint package from ${path}`); // Currently (as of 2020-june) the package registry used in CI is the public one and // at times it encounters network connection issues. We use `retry.try` below to see if // subsequent requests get through. apiRequest = retry.try(() => { return supertest - .get(SECURITY_PACKAGES_ROUTE) + .get(path) .set('kbn-xsrf', 'xxx') .expect(200) .catch((error) => { @@ -92,15 +91,10 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC error ); }) - .then((response: { body: GetPackagesResponse }) => { - const { body: secPackages } = response; - const endpointPackageInfo = secPackages.items.find( - (epmPackage) => epmPackage.name === 'endpoint' - ); + .then((response: { body: GetInfoResponse }) => { + const endpointPackageInfo = response.body.item; if (!endpointPackageInfo) { - throw new Error( - `Endpoint package was not in response from ${SECURITY_PACKAGES_ROUTE}` - ); + throw new Error(`Endpoint package was not in response from ${path}`); } log.info(`Endpoint package version: ${endpointPackageInfo.version}`); @@ -127,7 +121,7 @@ export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderC /** * Retrieves the currently installed endpoint package */ - async getEndpointPackage(): Promise> { + async getEndpointPackage(): Promise> { const endpointPackage = await retrieveEndpointPackageInfo(); if (!endpointPackage) { diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 54b4f17f6ef5c..17b6452344166 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -112,5 +112,6 @@ "@kbn/user-profile-components", "@kbn/apm-synthtrace-client", "@kbn/utils", + "@kbn/journeys", ] } diff --git a/yarn.lock b/yarn.lock index 40ebc66b80d16..ce8e8cf546f8c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3773,10 +3773,18 @@ version "0.0.0" uid "" +"@kbn/ml-is-defined@link:x-pack/packages/ml/is_defined": + version "0.0.0" + uid "" + "@kbn/ml-is-populated-object@link:x-pack/packages/ml/is_populated_object": version "0.0.0" uid "" +"@kbn/ml-local-storage@link:x-pack/packages/ml/local_storage": + version "0.0.0" + uid "" + "@kbn/ml-nested-property@link:x-pack/packages/ml/nested_property": version "0.0.0" uid "" @@ -7104,12 +7112,14 @@ "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/json5@^0.0.30": - version "0.0.30" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.30.tgz#44cb52f32a809734ca562e685c6473b5754a7818" - integrity sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA== +"@types/json5@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-2.2.0.tgz#afff29abf9182a7d4a7e39105ca051f11c603d13" + integrity sha512-NrVug5woqbvNZ0WX+Gv4R+L4TGddtmFek2u8RtccAgFZWtS9QXF2xCXY22/M4nzkaKF0q9Fc6M/5rxLDhfwc/A== + dependencies: + json5 "*" "@types/jsonwebtoken@^8.5.6": version "8.5.6" @@ -7691,10 +7701,10 @@ resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.28.tgz#9ce8fa048c1e8c85cb71d7fe4d704e000226036f" integrity sha512-SMA+fUwULwK7sd/ZJicUztiPs8F1yCPwF3O23Z9uQ32ME5Ha0NmDK9+QTsYE4O2tHXChzXomSWWeIhCnoN1LqA== -"@types/selenium-webdriver@^4.1.9": - version "4.1.9" - resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-4.1.9.tgz#90b24668bf1ec0a049fbc7aeebd4f7ab672440fa" - integrity sha512-QNCYI3Rgjf3bZ2GZwXnUpOJUPR8p7+c9Um9MEKggLaUaF8UfjitH5aPCV1PF0DHVEiPYsXayGVS6+67DO3VILw== +"@types/selenium-webdriver@^4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-4.1.10.tgz#a33299c40afa8dfbd948c8dd338608b163f7c062" + integrity sha512-o6ARpkBI8J0b+jhLjXF46rYc8Vsb5CLrRetyA3V3qUPVDwNjPDyHZsZOCFSXH0KPZ6lIn2BfP1xVEPnO+AQy5w== dependencies: "@types/ws" "*" @@ -11227,7 +11237,7 @@ core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.9: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== -core-js@^3.0.4, core-js@^3.27.0, core-js@^3.6.5, core-js@^3.8.2, core-js@^3.8.3: +core-js@^3.0.4, core-js@^3.27.1, core-js@^3.6.5, core-js@^3.8.2, core-js@^3.8.3: version "3.27.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.27.1.tgz#23cc909b315a6bb4e418bf40a52758af2103ba46" integrity sha512-GutwJLBChfGCpwwhbYoqfv03LAfmiz7e7D/BNxzeMxwQf10GRSzqiOjx7AmtEk+heiD/JWmBuyBPgFtx0Sg1ww== @@ -11659,20 +11669,20 @@ cyclist@~0.2.2: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= -cypress-axe@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cypress-axe/-/cypress-axe-1.0.0.tgz#ab4e9486eaa3bb956a90a1ae40d52df42827b4f0" - integrity sha512-QBlNMAd5eZoyhG8RGGR/pLtpHGkvgWXm2tkP68scJ+AjYiNNOlJihxoEwH93RT+rWOLrefw4iWwEx8kpEcrvJA== +cypress-axe@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/cypress-axe/-/cypress-axe-1.2.0.tgz#224936a3346055f6c22636e645746cc903aaa947" + integrity sha512-mK7rxc8+e0IM519efgkzVBQRYLapy55TOVNbWZsbX3495xFzf8NnkMddUaHAGgAnF+kcyJU7zNPu3lTiOD58WQ== cypress-file-upload@^5.0.8: version "5.0.8" resolved "https://registry.yarnpkg.com/cypress-file-upload/-/cypress-file-upload-5.0.8.tgz#d8824cbeaab798e44be8009769f9a6c9daa1b4a1" integrity sha512-+8VzNabRk3zG6x8f8BWArF/xA/W0VK4IZNx3MV0jFWrJS/qKn8eHfa5nU73P9fOQAgwHFJx7zjg4lwOnljMO8g== -cypress-multi-reporters@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/cypress-multi-reporters/-/cypress-multi-reporters-1.6.1.tgz#515b891f6c80e0700068efb03ab9d55388399c95" - integrity sha512-FPeC0xWF1N6Myrwc2m7KC0xxlrtG8+x4hlsPFBDRWP8u/veR2x90pGaH3BuJfweV7xoQ4Zo85Qjhu3fgZGrBQQ== +cypress-multi-reporters@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/cypress-multi-reporters/-/cypress-multi-reporters-1.6.2.tgz#129dfeffa00d4deca3e9f58d84570b9962c28c2b" + integrity sha512-lvwGwHqZG5CwGxBJ6UJXWaxlWGkJgxBjP0h+IVLrrwRlJpT4coSwwt+UzMdeqEMrzT4IDfhbtmUNOiDleisOYA== dependencies: debug "^4.1.1" lodash "^4.17.15" @@ -11689,22 +11699,22 @@ cypress-react-selector@^3.0.0: dependencies: resq "1.10.2" -cypress-real-events@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/cypress-real-events/-/cypress-real-events-1.7.4.tgz#87780ee0f6669ee30ce52016c4bfc94d094a6e3d" - integrity sha512-bAlIf3w6uJa72hcbLFpQIl/hBoNGYnSVzFMgohefWcooyZz2WbFZdFAEDOl5qOPATtAU01o92sWvc2QW9eT8aA== +cypress-real-events@^1.7.6: + version "1.7.6" + resolved "https://registry.yarnpkg.com/cypress-real-events/-/cypress-real-events-1.7.6.tgz#6f17e0b2ceea1d6dc60f6737d8f84cc517bbbb4c" + integrity sha512-yP6GnRrbm6HK5q4DH6Nnupz37nOfZu/xn1xFYqsE2o4G73giPWQOdu6375QYpwfU1cvHNCgyD2bQ2hPH9D7NMw== -cypress-recurse@^1.24.0: - version "1.24.0" - resolved "https://registry.yarnpkg.com/cypress-recurse/-/cypress-recurse-1.24.0.tgz#d2d24024629573c84ee73b57955a728d6607046c" - integrity sha512-yH2XF71go+muxWjUbF7onNK0rzoVn27gzOPMTV3thg+Nv//jK2tV/z4hF0FWv88O3CAtmh7JZWhVNqFq4ghMZg== +cypress-recurse@^1.26.0: + version "1.26.0" + resolved "https://registry.yarnpkg.com/cypress-recurse/-/cypress-recurse-1.26.0.tgz#e897b8c849af25214ce8785c57479a7fd98d20a5" + integrity sha512-FioASB4kPgO8G0l4SkjPyFnm2VMvfG0zbjr3N/FqOiiq+YRtsXqGvFIYK9jKay90Ciqq3hKVLTuMCaNpniXYfA== dependencies: humanize-duration "^3.27.3" -cypress@^11.2.0: - version "11.2.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-11.2.0.tgz#63edef8c387b687066c5493f6f0ad7b9ced4b2b7" - integrity sha512-u61UGwtu7lpsNWLUma/FKNOsrjcI6wleNmda/TyKHe0dOBcVjbCPlp1N6uwFZ0doXev7f/91YDpU9bqDCFeBLA== +cypress@^12.3.0: + version "12.3.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-12.3.0.tgz#ae3fb0540aef4b5eab1ef2bcd0760caf2992b8bf" + integrity sha512-ZQNebibi6NBt51TRxRMYKeFvIiQZ01t50HSy7z/JMgRVqBUey3cdjog5MYEbzG6Ktti5ckDt1tfcC47lmFwXkw== dependencies: "@cypress/request" "^2.88.10" "@cypress/xvfb" "^1.2.4" @@ -18215,18 +18225,18 @@ json-stringify-safe@5.0.1, json-stringify-safe@^5.0.1, json-stringify-safe@~5.0. resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json5@*, json5@^2.1.2, json5@^2.1.3, json5@^2.2.1, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" -json5@^2.1.2, json5@^2.1.3, json5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== - jsondiffpatch@0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/jsondiffpatch/-/jsondiffpatch-0.4.1.tgz#9fb085036767f03534ebd46dcd841df6070c5773" @@ -19093,14 +19103,14 @@ lru-queue@0.1: es5-ext "~0.10.2" luxon@^1.21.3, luxon@^1.25.0: - version "1.28.0" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.0.tgz#e7f96daad3938c06a62de0fb027115d251251fbf" - integrity sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ== + version "1.28.1" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.1.tgz#528cdf3624a54506d710290a2341aa8e6e6c61b0" + integrity sha512-gYHAa180mKrNIUJCbwpmD0aTu9kV0dREDrwNnuyFAsO1Wt0EVYSZelPnJlbj9HplzXX/YWXHFTL45kvZ53M0pw== -luxon@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-2.3.2.tgz#5f2f3002b8c39b60a7b7ad24b2a85d90dc5db49c" - integrity sha512-MlAQQVMFhGk4WUA6gpfsy0QycnKP0+NlCBJRVRNPxxSIbjrCbQ65nrpJD3FVyJNZLuJ0uoqL57ye6BmDYgHaSw== +luxon@^2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-2.5.2.tgz#17ed497f0277e72d58a4756d6a9abee4681457b6" + integrity sha512-Yg7/RDp4nedqmLgyH0LwgGRvMEKVzKbUdkBYyCosbHgJ+kaOUx0qzSiSatVc3DFygnirTPYnMM2P5dg2uH1WvA== lz-string@^1.4.4: version "1.4.4" @@ -22840,10 +22850,10 @@ react-grid-layout@^1.3.4: react-draggable "^4.0.0" react-resizable "^3.0.4" -react-hook-form@^7.41.1: - version "7.41.3" - resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.41.3.tgz#1b85e95e70cb743d41cd9230ea2df71359d00151" - integrity sha512-5QNTmqJtDb88WV5n41b6+AmcDMVyaJ3tccPgHAgS215w3jZ3bmJhDO27kNTr8u4YHNYXmS7p1/4/KachBAlUtw== +react-hook-form@^7.41.3: + version "7.41.5" + resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.41.5.tgz#dcd0e7438c15044eadc99df6deb889da5858a03b" + integrity sha512-DAKjSJ7X9f16oQrP3TW2/eD9N6HOgrmIahP4LOdFphEWVfGZ2LulFd6f6AQ/YS/0cx/5oc4j8a1PXxuaurWp/Q== react-input-autosize@^3.0.0: version "3.0.0"