From 61a187224d982cd303a9f252a8dacc3bb42944ba Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:31:06 -0500 Subject: [PATCH 1/9] skip failing test suite (#173165) --- .../observability/observability_log_explorer/header_menu.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/header_menu.ts b/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/header_menu.ts index 0e7527bc76887..fe0c0c9fea197 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/header_menu.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/header_menu.ts @@ -22,7 +22,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'svlCommonNavigation', ]); - describe('Header menu', () => { + // Failing: See https://github.com/elastic/kibana/issues/173165 + describe.skip('Header menu', () => { before(async () => { await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover'); await esArchiver.load( From 95025129a791c7a2fd24d323a5bd240c6af495a6 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 12 Dec 2023 12:40:43 -0500 Subject: [PATCH 2/9] skip failing test suite (#173165) --- .../observability/observability_log_explorer/header_menu.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/header_menu.ts b/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/header_menu.ts index fe0c0c9fea197..41a75282e22e9 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/header_menu.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/header_menu.ts @@ -22,6 +22,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'svlCommonNavigation', ]); + // Failing: See https://github.com/elastic/kibana/issues/173165 // Failing: See https://github.com/elastic/kibana/issues/173165 describe.skip('Header menu', () => { before(async () => { From 156c8f2323a65153397bbddd308bfd23901d50ba Mon Sep 17 00:00:00 2001 From: Adam Demjen Date: Tue, 12 Dec 2023 12:42:16 -0500 Subject: [PATCH 3/9] [Enterprise Search] Disallow creating pipeline with placeholder of model (#172988) ## Summary This PR adds validation to model selection when creating an inference pipeline. Pipelines cannot be created with a non-deployed placeholder of a model (e.g. E5, ELSER) as this would break other Search UIs and functionality. If such an item is selected, an error message is displayed and the Continue button is disabled. Note this feature is independent of the changing of the model selection component. Valid selection: Screenshot 2023-12-08 at 14 03 59 Invalid selection: Screenshot 2023-12-08 at 14 04 04 ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../ml_inference/configure_pipeline.tsx | 31 +++++++++++++------ .../ml_inference/ml_inference_logic.test.ts | 19 ++++++++++++ .../ml_inference/model_select.test.tsx | 17 ++++++++++ .../pipelines/ml_inference/model_select.tsx | 1 + .../pipelines/ml_inference/types.ts | 2 ++ .../pipelines/ml_inference/utils.ts | 8 +++++ 6 files changed, 69 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/configure_pipeline.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/configure_pipeline.tsx index cc318831555af..52d4f38b45408 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/configure_pipeline.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/configure_pipeline.tsx @@ -19,6 +19,7 @@ import { EuiTabbedContentTab, EuiTitle, EuiText, + EuiTextColor, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -130,15 +131,27 @@ export const ConfigurePipeline: React.FC = () => { )} - - - + + +
+ {i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.titleSelectTrainedModel', + { defaultMessage: 'Select a trained ML Model' } + )} +
+
+ {formErrors.modelStatus !== undefined && ( + <> + + +

+ {formErrors.modelStatus} +

+
+ + )} + + ), diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/ml_inference_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/ml_inference_logic.test.ts index a725371de0242..7412d861d7136 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/ml_inference_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/ml_inference_logic.test.ts @@ -550,6 +550,25 @@ describe('MlInferenceLogic', () => { pipelineName: 'Name already used by another pipeline.', }); }); + it('has errors when non-deployed model is selected', () => { + MLInferenceLogic.actions.setInferencePipelineConfiguration({ + ...MLInferenceLogic.values.addInferencePipelineModal.configuration, + pipelineName: 'unit-test-pipeline', + modelID: 'unit-test-model', + existingPipeline: false, + fieldMappings: [ + { + sourceField: 'body', + targetField: 'ml.inference.body', + }, + ], + isModelPlaceholderSelected: true, + }); + + expect(MLInferenceLogic.values.formErrors).toEqual({ + modelStatus: 'Model must be deployed before use.', + }); + }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/model_select.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/model_select.test.tsx index 15fb492fae56d..9bd006f65883e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/model_select.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/model_select.test.tsx @@ -98,6 +98,23 @@ describe('ModelSelect', () => { }) ); }); + it('sets placeholder flag on selecting a placeholder item', () => { + setMockValues(DEFAULT_VALUES); + + const wrapper = shallow(); + expect(wrapper.find(EuiSelectable)).toHaveLength(1); + const selectable = wrapper.find(EuiSelectable); + selectable.simulate('change', [ + { modelId: 'model_1' }, + { modelId: 'model_2', isPlaceholder: true, checked: 'on' }, + ]); + expect(MOCK_ACTIONS.setInferencePipelineConfiguration).toHaveBeenCalledWith( + expect.objectContaining({ + modelID: 'model_2', + isModelPlaceholderSelected: true, + }) + ); + }); it('generates pipeline name on selecting an item', () => { setMockValues(DEFAULT_VALUES); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/model_select.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/model_select.tsx index 86c91c483702f..ac3900b6ed662 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/model_select.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/model_select.tsx @@ -44,6 +44,7 @@ export const ModelSelect: React.FC = () => { ...configuration, inferenceConfig: undefined, modelID: selectedOption?.modelId ?? '', + isModelPlaceholderSelected: selectedOption?.isPlaceholder ?? false, fieldMappings: undefined, pipelineName: isPipelineNameUserSupplied ? pipelineName diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/types.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/types.ts index 3a645dcbba3b4..87aed3eb4d714 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/types.ts @@ -13,6 +13,7 @@ export interface InferencePipelineConfiguration { existingPipeline?: boolean; inferenceConfig?: InferencePipelineInferenceConfig; isPipelineNameUserSupplied?: boolean; + isModelPlaceholderSelected?: boolean; modelID: string; pipelineName: string; fieldMappings?: FieldMapping[]; @@ -21,6 +22,7 @@ export interface InferencePipelineConfiguration { export interface AddInferencePipelineFormErrors { modelID?: string; + modelStatus?: string; fieldMappings?: string; pipelineName?: string; } diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/utils.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/utils.ts index 02cf5a7463dde..5a01a3823a71d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/utils.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/utils.ts @@ -37,6 +37,12 @@ const PIPELINE_NAME_EXISTS_ERROR = i18n.translate( defaultMessage: 'Name already used by another pipeline.', } ); +const MODEL_NOT_DEPLOYED_ERROR = i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.modelNotDeployedError', + { + defaultMessage: 'Model must be deployed before use.', + } +); export const validateInferencePipelineConfiguration = ( config: InferencePipelineConfiguration @@ -55,6 +61,8 @@ export const validateInferencePipelineConfiguration = ( } if (config.modelID.trim().length === 0) { errors.modelID = FIELD_REQUIRED_ERROR; + } else if (config.isModelPlaceholderSelected) { + errors.modelStatus = MODEL_NOT_DEPLOYED_ERROR; } return errors; From 13434dc28e926b4ffb10570189b624230a5f723e Mon Sep 17 00:00:00 2001 From: "Christiane (Tina) Heiligers" Date: Tue, 12 Dec 2023 11:22:02 -0700 Subject: [PATCH 4/9] Adds run without basepath configured to examples readme (#173086) Kibana crashes when running the examples with a basepath configured with too many redirects during auth. This PR warns about that in the examples/README Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- examples/README.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/README.asciidoc b/examples/README.asciidoc index d33c5e825ce12..3f2c58a173304 100644 --- a/examples/README.asciidoc +++ b/examples/README.asciidoc @@ -1,7 +1,7 @@ [[example-plugins]] == Example plugins -This folder contains example plugins. To run the plugins in this folder, use the `--run-examples` flag, via +This folder contains example plugins. To run the plugins in this folder, use the `--run-examples` flag (without a basepath), via [source,bash] ---- From c15c29490caca68e483a67e9f91f5575722f540d Mon Sep 17 00:00:00 2001 From: Ramon Butter Date: Tue, 12 Dec 2023 19:23:39 +0100 Subject: [PATCH 5/9] Set explicit resource requests in the QG (#173189) Kibana is fairly large, we should explicitly set in the gate what we are expecting in terms of resource for each individual step. --- .../pipelines/quality-gates/pipeline.kibana-tests.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.buildkite/pipelines/quality-gates/pipeline.kibana-tests.yaml b/.buildkite/pipelines/quality-gates/pipeline.kibana-tests.yaml index 467df501bc9ca..1217853275914 100644 --- a/.buildkite/pipelines/quality-gates/pipeline.kibana-tests.yaml +++ b/.buildkite/pipelines/quality-gates/pipeline.kibana-tests.yaml @@ -10,6 +10,11 @@ # # Docs: https://docs.elastic.dev/serverless/qualitygates +agents: + cpu: 2 + ephemeralStorage: "20G" + memory: "8G" + env: TEAM_CHANNEL: "#kibana-mission-control" ENVIRONMENT: ${ENVIRONMENT?} From fe0ad5adad7610d73cd108d0a76eacfbdfbdc0d7 Mon Sep 17 00:00:00 2001 From: "Quynh Nguyen (Quinn)" <43350163+qn895@users.noreply.github.com> Date: Tue, 12 Dec 2023 13:17:36 -0600 Subject: [PATCH 6/9] [ML] Fix View in Discover option in Anomaly explorer not handling multiple field values or values with quotation marks (#172897) ## Summary This PR addresses https://github.com/elastic/kibana/issues/172872 and https://github.com/elastic/kibana/issues/172461. Previously, clicking `View in Discover` option in Anomaly explorer for an anomaly with influencers containing quotation marks would lead to an error in Discover. Likewise, if the influencer has multiple field values, the link only brings over the first field value and not all. This PR fixes both issues. After: https://github.com/elastic/kibana/assets/43350163/d60055e6-04ec-4882-81ea-02c04f73d16b ### Checklist Delete any items that are not applicable to this PR. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### Risk Matrix Delete this section if it is not applicable to this PR. Before closing this PR, invite QA, stakeholders, and other developers to identify risks that should be tested prior to the change/feature release. When forming the risk matrix, consider some of the following examples and how they may potentially impact the change: | Risk | Probability | Severity | Mitigation/Notes | |---------------------------|-------------|----------|-------------------------| | Multiple Spaces—unexpected behavior in non-default Kibana Space. | Low | High | Integration tests will verify that all features are still supported in non-default Kibana Space and when user switches between spaces. | | Multiple nodes—Elasticsearch polling might have race conditions when multiple Kibana nodes are polling for the same tasks. | High | Low | Tasks are idempotent, so executing them multiple times will not result in logical error, but will degrade performance. To test for this case we add plenty of unit tests around this logic and document manual testing procedure. | | Code should gracefully handle cases when feature X or plugin Y are disabled. | Medium | High | Unit tests will verify that any feature flag or plugin combination still results in our service operational. | | [See more potential risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) | ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/anomalies_table/links_menu.tsx | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.tsx b/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.tsx index bf7df6091177d..b81f632c9a62c 100644 --- a/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.tsx +++ b/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.tsx @@ -34,6 +34,8 @@ import { formatHumanReadableDateTimeSeconds, timeFormatter } from '@kbn/ml-date- import { SEARCH_QUERY_LANGUAGE } from '@kbn/ml-query-utils'; import type { DataView, DataViewField } from '@kbn/data-views-plugin/common'; import { CATEGORIZE_FIELD_TRIGGER } from '@kbn/ml-ui-actions'; +import { isDefined } from '@kbn/ml-is-defined'; +import { escapeQuotes } from '@kbn/es-query'; import { PLUGIN_ID } from '../../../../common/constants/app'; import { mlJobService } from '../../services/job_service'; import { findMessageField, getDataViewIdFromName } from '../../util/index_utils'; @@ -265,12 +267,19 @@ export const LinksMenuUI = (props: LinksMenuProps) => { if (record.influencers) { kqlQuery = record.influencers - .map( - (influencer) => - `"${influencer.influencer_field_name}":"${ - influencer.influencer_field_values[0] ?? '' - }"` - ) + .filter((influencer) => isDefined(influencer)) + .map((influencer) => { + const values = influencer.influencer_field_values; + + if (values.length > 0) { + const fieldName = escapeQuotes(influencer.influencer_field_name); + const escapedVals = values + .filter((value) => isDefined(value)) + .map((value) => `"${fieldName}":"${escapeQuotes(value)}"`); + // Ensure there's enclosing () if there are multiple field values, + return escapedVals.length > 1 ? `(${escapedVals.join(' OR ')})` : escapedVals[0]; + } + }) .join(' AND '); } From c2003d9f83f6d437ec9ce46943a402b38c07ece5 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 12 Dec 2023 12:36:20 -0700 Subject: [PATCH 7/9] [SLO] Reset UI for updating outdated SLOs (#172883) ## Summary This PR is a follow up to #172224, it adds a UI for resetting the SLO definitions from the previous model. Once #179473 is merged I will rebase this against `main` and convert it from a "draft" PR to "ready to review". ![image](https://github.com/elastic/kibana/assets/41702/daf0591c-272f-40c2-9831-658d7b9b1378) ![image](https://github.com/elastic/kibana/assets/41702/d385396d-d840-4574-942a-b8e51ce66066) ![image](https://github.com/elastic/kibana/assets/41702/729df2a0-61e6-41b3-aaa5-8501e7aa7797) ### Testing 1. Start by loading `main` 2. Ingest some data 3. Create some SLOs 4. Change Kibana from `main` to this PR 5. Visit the SLO page, you should see a banner similar to the screen shot above. 6. Do your best to break this --------- Co-authored-by: shahzad31 Co-authored-by: Dominique Clarke --- .../observability/common/locators/paths.ts | 2 + .../slo_delete_confirmation_modal.tsx | 4 +- .../slo_reset_confirmation_modal.tsx | 49 ++++++ .../slo/slo_outdated_callout/index.tsx | 62 ++++++++ .../public/hooks/slo/query_key_factory.ts | 3 +- .../hooks/slo/use_fetch_slo_definitions.ts | 19 ++- .../public/hooks/slo/use_reset_slo.ts | 52 +++++++ .../pages/slo_outdated_definitions/index.tsx | 141 ++++++++++++++++++ .../slo_outdated_definitions/outdated_slo.tsx | 124 +++++++++++++++ .../outdated_slo_search_bar.tsx | 82 ++++++++++ .../badges/slo_indicator_type_badge.tsx | 7 +- .../badges/slo_time_window_badge.tsx | 4 +- .../observability/public/pages/slos/slos.tsx | 5 +- .../pages/slos_welcome/slos_welcome.tsx | 2 + .../observability/public/routes/routes.tsx | 9 ++ 15 files changed, 550 insertions(+), 15 deletions(-) create mode 100644 x-pack/plugins/observability/public/components/slo/reset_confirmation_modal/slo_reset_confirmation_modal.tsx create mode 100644 x-pack/plugins/observability/public/components/slo/slo_outdated_callout/index.tsx create mode 100644 x-pack/plugins/observability/public/hooks/slo/use_reset_slo.ts create mode 100644 x-pack/plugins/observability/public/pages/slo_outdated_definitions/index.tsx create mode 100644 x-pack/plugins/observability/public/pages/slo_outdated_definitions/outdated_slo.tsx create mode 100644 x-pack/plugins/observability/public/pages/slo_outdated_definitions/outdated_slo_search_bar.tsx diff --git a/x-pack/plugins/observability/common/locators/paths.ts b/x-pack/plugins/observability/common/locators/paths.ts index dcd3c361c0e36..5db834c867b9c 100644 --- a/x-pack/plugins/observability/common/locators/paths.ts +++ b/x-pack/plugins/observability/common/locators/paths.ts @@ -20,6 +20,7 @@ export const SLOS_WELCOME_PATH = '/slos/welcome' as const; export const SLO_DETAIL_PATH = '/slos/:sloId' as const; export const SLO_CREATE_PATH = '/slos/create' as const; export const SLO_EDIT_PATH = '/slos/edit/:sloId' as const; +export const SLOS_OUTDATED_DEFINITIONS_PATH = '/slos/outdated-definitions' as const; export const CASES_PATH = '/cases' as const; export const paths = { @@ -31,6 +32,7 @@ export const paths = { ruleDetails: (ruleId: string) => `${OBSERVABILITY_BASE_PATH}${RULES_PATH}/${encodeURI(ruleId)}`, slos: `${OBSERVABILITY_BASE_PATH}${SLOS_PATH}`, slosWelcome: `${OBSERVABILITY_BASE_PATH}${SLOS_WELCOME_PATH}`, + slosOutdatedDefinitions: `${OBSERVABILITY_BASE_PATH}${SLOS_OUTDATED_DEFINITIONS_PATH}`, sloCreate: `${OBSERVABILITY_BASE_PATH}${SLO_CREATE_PATH}`, sloCreateWithEncodedForm: (encodedParams: string) => `${OBSERVABILITY_BASE_PATH}${SLO_CREATE_PATH}?_a=${encodedParams}`, diff --git a/x-pack/plugins/observability/public/components/slo/delete_confirmation_modal/slo_delete_confirmation_modal.tsx b/x-pack/plugins/observability/public/components/slo/delete_confirmation_modal/slo_delete_confirmation_modal.tsx index 0822758859d60..eee88b8daf9cb 100644 --- a/x-pack/plugins/observability/public/components/slo/delete_confirmation_modal/slo_delete_confirmation_modal.tsx +++ b/x-pack/plugins/observability/public/components/slo/delete_confirmation_modal/slo_delete_confirmation_modal.tsx @@ -7,11 +7,11 @@ import { EuiConfirmModal } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ALL_VALUE, SLOWithSummaryResponse } from '@kbn/slo-schema'; +import { ALL_VALUE, SLOResponse, SLOWithSummaryResponse } from '@kbn/slo-schema'; import React from 'react'; export interface SloDeleteConfirmationModalProps { - slo: SLOWithSummaryResponse; + slo: SLOWithSummaryResponse | SLOResponse; onCancel: () => void; onConfirm: () => void; } diff --git a/x-pack/plugins/observability/public/components/slo/reset_confirmation_modal/slo_reset_confirmation_modal.tsx b/x-pack/plugins/observability/public/components/slo/reset_confirmation_modal/slo_reset_confirmation_modal.tsx new file mode 100644 index 0000000000000..9fabcb61efc96 --- /dev/null +++ b/x-pack/plugins/observability/public/components/slo/reset_confirmation_modal/slo_reset_confirmation_modal.tsx @@ -0,0 +1,49 @@ +/* + * 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 { EuiConfirmModal } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { SLOResponse, SLOWithSummaryResponse } from '@kbn/slo-schema'; +import React from 'react'; + +export interface SloResetConfirmationModalProps { + slo: SLOWithSummaryResponse | SLOResponse; + onCancel: () => void; + onConfirm: () => void; +} + +export function SloResetConfirmationModal({ + slo, + onCancel, + onConfirm, +}: SloResetConfirmationModalProps) { + const { name } = slo; + return ( + + {i18n.translate('xpack.observability.slo.resetConfirmationModal.descriptionText', { + defaultMessage: 'Resetting this SLO will also regenerate the historical data.', + })} + + ); +} diff --git a/x-pack/plugins/observability/public/components/slo/slo_outdated_callout/index.tsx b/x-pack/plugins/observability/public/components/slo/slo_outdated_callout/index.tsx new file mode 100644 index 0000000000000..dae8f76fb85a5 --- /dev/null +++ b/x-pack/plugins/observability/public/components/slo/slo_outdated_callout/index.tsx @@ -0,0 +1,62 @@ +/* + * 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, EuiCallOut } from '@elastic/eui'; +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { useFetchSloDefinitions } from '../../../hooks/slo/use_fetch_slo_definitions'; +import { useKibana } from '../../../utils/kibana_react'; +import { paths } from '../../../../common/locators/paths'; + +export function SloOutdatedCallout() { + const { + application: { navigateToUrl }, + http: { basePath }, + } = useKibana().services; + + const handleClick = () => { + navigateToUrl(basePath.prepend(paths.observability.slosOutdatedDefinitions)); + }; + + const { isLoading, data } = useFetchSloDefinitions({ includeOutdatedOnly: true }); + if (!isLoading && data && data.total > 0) { + return ( + +

+ +

+

+ + + +

+
+ ); + } + return null; +} diff --git a/x-pack/plugins/observability/public/hooks/slo/query_key_factory.ts b/x-pack/plugins/observability/public/hooks/slo/query_key_factory.ts index b56a0576396f9..96d1b55a7cd31 100644 --- a/x-pack/plugins/observability/public/hooks/slo/query_key_factory.ts +++ b/x-pack/plugins/observability/public/hooks/slo/query_key_factory.ts @@ -28,7 +28,8 @@ export const sloKeys = { historicalSummaries: () => [...sloKeys.all, 'historicalSummary'] as const, historicalSummary: (list: Array<{ sloId: string; instanceId: string }>) => [...sloKeys.historicalSummaries(), list] as const, - definitions: (search: string) => [...sloKeys.all, 'definitions', search] as const, + definitions: (search: string, page: number, perPage: number, includeOutdatedOnly: boolean) => + [...sloKeys.all, 'definitions', search, page, perPage, includeOutdatedOnly] as const, globalDiagnosis: () => [...sloKeys.all, 'globalDiagnosis'] as const, burnRates: (sloId: string, instanceId: string | undefined) => [...sloKeys.all, 'burnRates', sloId, instanceId] as const, diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_definitions.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_definitions.ts index b3b7f59dd37cf..6b6893afb1189 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_definitions.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_definitions.ts @@ -15,23 +15,32 @@ export interface UseFetchSloDefinitionsResponse { isLoading: boolean; isSuccess: boolean; isError: boolean; + refetch: () => void; } interface Params { name?: string; + includeOutdatedOnly?: boolean; + page?: number; + perPage?: number; } -export function useFetchSloDefinitions({ name = '' }: Params): UseFetchSloDefinitionsResponse { +export function useFetchSloDefinitions({ + name = '', + includeOutdatedOnly = false, + page = 1, + perPage = 100, +}: Params): UseFetchSloDefinitionsResponse { const { http } = useKibana().services; const search = name.endsWith('*') ? name : `${name}*`; - const { isLoading, isError, isSuccess, data } = useQuery({ - queryKey: sloKeys.definitions(search), + const { isLoading, isError, isSuccess, data, refetch } = useQuery({ + queryKey: sloKeys.definitions(search, page, perPage, includeOutdatedOnly), queryFn: async ({ signal }) => { try { const response = await http.get( '/api/observability/slos/_definitions', - { query: { search }, signal } + { query: { search, includeOutdatedOnly, page, perPage }, signal } ); return response; @@ -43,5 +52,5 @@ export function useFetchSloDefinitions({ name = '' }: Params): UseFetchSloDefini refetchOnWindowFocus: false, }); - return { isLoading, isError, isSuccess, data }; + return { isLoading, isError, isSuccess, data, refetch }; } diff --git a/x-pack/plugins/observability/public/hooks/slo/use_reset_slo.ts b/x-pack/plugins/observability/public/hooks/slo/use_reset_slo.ts new file mode 100644 index 0000000000000..35f166e89b766 --- /dev/null +++ b/x-pack/plugins/observability/public/hooks/slo/use_reset_slo.ts @@ -0,0 +1,52 @@ +/* + * 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 { useMutation } from '@tanstack/react-query'; +import { i18n } from '@kbn/i18n'; +import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public'; +import { useKibana } from '../../utils/kibana_react'; + +type ServerError = IHttpFetchError; + +export function useResetSlo() { + const { + http, + notifications: { toasts }, + } = useKibana().services; + return useMutation( + ['resetSlo'], + ({ id, name }) => { + try { + return http.post(`/api/observability/slos/${id}/_reset`); + } catch (error) { + return Promise.reject( + i18n.translate('xpack.observability.slo.slo.reset.errorMessage', { + defaultMessage: 'Failed to reset {name} (id: {id}), something went wrong: {error}', + values: { error: String(error), name, id }, + }) + ); + } + }, + { + onError: (error, { name, id }) => { + toasts.addError(new Error(error.body?.message ?? error.message), { + title: i18n.translate('xpack.observability.slo.slo.reset.errorNotification', { + defaultMessage: 'Failed to reset {name} (id: {id})', + values: { name, id }, + }), + }); + }, + onSuccess: (_data, { name }) => { + toasts.addSuccess( + i18n.translate('xpack.observability.slo.slo.reset.successNotification', { + defaultMessage: '{name} reset successfully', + values: { name }, + }) + ); + }, + } + ); +} diff --git a/x-pack/plugins/observability/public/pages/slo_outdated_definitions/index.tsx b/x-pack/plugins/observability/public/pages/slo_outdated_definitions/index.tsx new file mode 100644 index 0000000000000..a16e1a604956b --- /dev/null +++ b/x-pack/plugins/observability/public/pages/slo_outdated_definitions/index.tsx @@ -0,0 +1,141 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTablePagination, EuiText } from '@elastic/eui'; +import { useBreadcrumbs } from '@kbn/observability-shared-plugin/public'; +import { useKibana } from '../../utils/kibana_react'; +import { useLicense } from '../../hooks/use_license'; +import { usePluginContext } from '../../hooks/use_plugin_context'; +import { useCapabilities } from '../../hooks/slo/use_capabilities'; +import { useFetchSloGlobalDiagnosis } from '../../hooks/slo/use_fetch_global_diagnosis'; +import { HeaderMenu } from '../overview/components/header_menu/header_menu'; +import { useFetchSloDefinitions } from '../../hooks/slo/use_fetch_slo_definitions'; +import { paths } from '../../../common/locators/paths'; +import { SloListEmpty } from '../slos/components/slo_list_empty'; +import { OutdatedSlo } from './outdated_slo'; +import { OutdatedSloSearchBar } from './outdated_slo_search_bar'; + +export function SlosOutdatedDefinitions() { + const { + http: { basePath }, + } = useKibana().services; + const { hasWriteCapabilities } = useCapabilities(); + const { data: globalDiagnosis } = useFetchSloGlobalDiagnosis(); + const { ObservabilityPageTemplate } = usePluginContext(); + + useBreadcrumbs([ + { + href: basePath.prepend(paths.observability.slos), + text: i18n.translate('xpack.observability.breadcrumbs.slosLinkText', { + defaultMessage: 'SLOs', + }), + deepLinkId: 'observability-overview:slos', + }, + { + text: i18n.translate('xpack.observability.breadcrumbs.slosOutdatedDefinitions', { + defaultMessage: 'Outdated SLO Definitions', + }), + }, + ]); + + const [search, setSearch] = useState(''); + const [activePage, setActivePage] = useState(0); + const [perPage, setPerPage] = useState(10); + + const handlePerPageChange = (perPageNumber: number) => { + setPerPage(perPageNumber); + setActivePage(0); + }; + + const { hasAtLeast } = useLicense(); + + const { isLoading, data, refetch } = useFetchSloDefinitions({ + name: search, + includeOutdatedOnly: true, + page: activePage + 1, + perPage, + }); + const { total } = data ?? { total: 0 }; + + const hasRequiredWritePrivileges = + !!globalDiagnosis?.userPrivileges.write.has_all_requested && hasWriteCapabilities; + + const hasPlatinumLicense = hasAtLeast('platinum') === true; + + const hasSlosAndHasPermissions = hasPlatinumLicense && hasRequiredWritePrivileges; + + const errors = !hasRequiredWritePrivileges ? ( + + {i18n.translate('xpack.observability.slo.slosOutdatedDefinitions.sloPermissionsError', { + defaultMessage: 'You must have write permissions for SLOs to access this page', + })} + + ) : !hasPlatinumLicense ? ( + + {i18n.translate('xpack.observability.slo.slosOutdatedDefinitions.licenseError', { + defaultMessage: 'You must have atleast a platinum license to access this page', + })} + + ) : null; + + return ( + + + + {!hasSlosAndHasPermissions ? ( + errors + ) : ( + <> +

+ {i18n.translate('xpack.observability.slo.slosOutdatedDefinitions.description', { + defaultMessage: + 'The following SLOs are from a previous version and need to either be reset to upgrade to the latest version OR deleted and removed from the system. When you reset the SLO, the transform will be updated to the latest version and the historical data will be regenerated from the source data.', + })} +

+ + + + + + {!isLoading && total === 0 && } + {!isLoading && + total > 0 && + data && + data.results.map((slo) => ( + + ))} + + + {!isLoading && data && ( + + )} + + )} +
+ ); +} diff --git a/x-pack/plugins/observability/public/pages/slo_outdated_definitions/outdated_slo.tsx b/x-pack/plugins/observability/public/pages/slo_outdated_definitions/outdated_slo.tsx new file mode 100644 index 0000000000000..f8f5cfeb46848 --- /dev/null +++ b/x-pack/plugins/observability/public/pages/slo_outdated_definitions/outdated_slo.tsx @@ -0,0 +1,124 @@ +/* + * 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 { FormattedMessage } from '@kbn/i18n-react'; +import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText, EuiButton } from '@elastic/eui'; +import { SLOResponse } from '@kbn/slo-schema'; +import { SloDeleteConfirmationModal } from '../../components/slo/delete_confirmation_modal/slo_delete_confirmation_modal'; +import { SloTimeWindowBadge } from '../slos/components/badges/slo_time_window_badge'; +import { SloIndicatorTypeBadge } from '../slos/components/badges/slo_indicator_type_badge'; +import { useDeleteSlo } from '../../hooks/slo/use_delete_slo'; +import { useResetSlo } from '../../hooks/slo/use_reset_slo'; +import { SloResetConfirmationModal } from '../../components/slo/reset_confirmation_modal/slo_reset_confirmation_modal'; + +interface OutdatedSloProps { + slo: SLOResponse; + onReset: () => void; + onDelete: () => void; +} + +export function OutdatedSlo({ slo, onReset, onDelete }: OutdatedSloProps) { + const { mutateAsync: resetSlo, isLoading: isResetLoading } = useResetSlo(); + const { mutateAsync: deleteSlo, isLoading: isDeleteLoading } = useDeleteSlo(); + const [isDeleteConfirmationModalOpen, setDeleteConfirmationModalOpen] = useState(false); + const [isResetConfirmationModalOpen, setResetConfirmationModalOpen] = useState(false); + + const handleDelete = () => { + setDeleteConfirmationModalOpen(true); + }; + + const handleDeleteConfirm = async () => { + setDeleteConfirmationModalOpen(false); + await deleteSlo({ id: slo.id, name: slo.name }); + onDelete(); + }; + + const handleDeleteCancel = () => { + setDeleteConfirmationModalOpen(false); + }; + + const handleReset = () => { + setResetConfirmationModalOpen(true); + }; + + const handleResetConfirm = async () => { + setResetConfirmationModalOpen(false); + await resetSlo({ id: slo.id, name: slo.name }); + onReset(); + }; + + const handleResetCancel = () => { + setResetConfirmationModalOpen(false); + }; + return ( + + + + + + + {slo.name} + + + + + + + + + + + + + + + + + + + + {isDeleteConfirmationModalOpen ? ( + + ) : null} + {isResetConfirmationModalOpen ? ( + + ) : null} + + ); +} diff --git a/x-pack/plugins/observability/public/pages/slo_outdated_definitions/outdated_slo_search_bar.tsx b/x-pack/plugins/observability/public/pages/slo_outdated_definitions/outdated_slo_search_bar.tsx new file mode 100644 index 0000000000000..7e491f4933e20 --- /dev/null +++ b/x-pack/plugins/observability/public/pages/slo_outdated_definitions/outdated_slo_search_bar.tsx @@ -0,0 +1,82 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { EuiFlexGroup, EuiFlexItem, EuiButton, EuiFieldSearch } from '@elastic/eui'; + +interface OutdatedSloSearchBarProps { + initialSearch?: string; + onRefresh: () => void; + onSearch: (search: string) => void; +} + +export function OutdatedSloSearchBar({ + onSearch, + onRefresh, + initialSearch = '', +}: OutdatedSloSearchBarProps) { + const [tempSearch, setTempSearch] = useState(initialSearch); + const [search, setSearch] = useState(initialSearch); + + const refreshOrUpdateSearch = () => { + if (tempSearch !== search) { + setSearch(tempSearch); + onSearch(tempSearch); + } else { + onRefresh(); + } + }; + + const handleClick = (event: React.ChangeEvent) => + setTempSearch(event.target.value); + + const handleKeyPress = (event: React.KeyboardEvent) => { + if (event.key === 'Enter') { + refreshOrUpdateSearch(); + } + }; + + return ( + + + + + + {search === tempSearch && ( + + {i18n.translate('xpack.observability.slosOutdatedDefinitions.refreshButtonLabel', { + defaultMessage: 'Refresh', + })} + + )} + {search !== tempSearch && ( + + {i18n.translate('xpack.observability.slosOutdatedDefinitions.updateButtonLabel', { + defaultMessage: 'Update', + })} + + )} + + + ); +} diff --git a/x-pack/plugins/observability/public/pages/slos/components/badges/slo_indicator_type_badge.tsx b/x-pack/plugins/observability/public/pages/slos/components/badges/slo_indicator_type_badge.tsx index c85eb6776680b..316298cd8d44c 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/badges/slo_indicator_type_badge.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/badges/slo_indicator_type_badge.tsx @@ -7,10 +7,9 @@ import React from 'react'; import { EuiBadge, EuiFlexItem, EuiToolTip, EuiBadgeProps } from '@elastic/eui'; -import { SLOWithSummaryResponse } from '@kbn/slo-schema'; -import { i18n } from '@kbn/i18n'; - +import { SLOResponse, SLOWithSummaryResponse } from '@kbn/slo-schema'; import { euiLightVars } from '@kbn/ui-theme'; +import { i18n } from '@kbn/i18n'; import { useKibana } from '../../../../utils/kibana_react'; import { convertSliApmParamsToApmAppDeeplinkUrl } from '../../../../utils/slo/convert_sli_apm_params_to_apm_app_deeplink_url'; import { isApmIndicatorType } from '../../../../utils/slo/indicator'; @@ -18,7 +17,7 @@ import { toIndicatorTypeLabel } from '../../../../utils/slo/labels'; export interface Props { color?: EuiBadgeProps['color']; - slo: SLOWithSummaryResponse; + slo: SLOWithSummaryResponse | SLOResponse; } export function SloIndicatorTypeBadge({ slo, color }: Props) { diff --git a/x-pack/plugins/observability/public/pages/slos/components/badges/slo_time_window_badge.tsx b/x-pack/plugins/observability/public/pages/slos/components/badges/slo_time_window_badge.tsx index b5d4ecd0224fe..384c17f251b01 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/badges/slo_time_window_badge.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/badges/slo_time_window_badge.tsx @@ -7,7 +7,7 @@ import { EuiBadge, EuiBadgeProps, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { rollingTimeWindowTypeSchema, SLOWithSummaryResponse } from '@kbn/slo-schema'; +import { rollingTimeWindowTypeSchema, SLOResponse, SLOWithSummaryResponse } from '@kbn/slo-schema'; import { euiLightVars } from '@kbn/ui-theme'; import moment from 'moment'; import React from 'react'; @@ -16,7 +16,7 @@ import { toDurationLabel } from '../../../../utils/slo/labels'; export interface Props { color?: EuiBadgeProps['color']; - slo: SLOWithSummaryResponse; + slo: SLOWithSummaryResponse | SLOResponse; } export function SloTimeWindowBadge({ slo, color }: Props) { diff --git a/x-pack/plugins/observability/public/pages/slos/slos.tsx b/x-pack/plugins/observability/public/pages/slos/slos.tsx index e010df224ce1c..4ea3f27fade3c 100644 --- a/x-pack/plugins/observability/public/pages/slos/slos.tsx +++ b/x-pack/plugins/observability/public/pages/slos/slos.tsx @@ -6,7 +6,7 @@ */ import React, { useEffect, useState } from 'react'; -import { EuiButton } from '@elastic/eui'; +import { EuiButton, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useBreadcrumbs } from '@kbn/observability-shared-plugin/public'; @@ -22,6 +22,7 @@ import { FeedbackButton } from '../../components/slo/feedback_button/feedback_bu import { paths } from '../../../common/locators/paths'; import { useAutoRefreshStorage } from '../../components/slo/auto_refresh_button/hooks/use_auto_refresh_storage'; import { HeaderMenu } from '../overview/components/header_menu/header_menu'; +import { SloOutdatedCallout } from '../../components/slo/slo_outdated_callout'; export function SlosPage() { const { @@ -90,6 +91,8 @@ export function SlosPage() { data-test-subj="slosPage" > + + ); diff --git a/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.tsx b/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.tsx index 16f4a75974453..a27762d8553f9 100644 --- a/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.tsx +++ b/x-pack/plugins/observability/public/pages/slos_welcome/slos_welcome.tsx @@ -27,6 +27,7 @@ import { paths } from '../../../common/locators/paths'; import illustration from './assets/illustration.svg'; import { useFetchSloGlobalDiagnosis } from '../../hooks/slo/use_fetch_global_diagnosis'; import { HeaderMenu } from '../overview/components/header_menu/header_menu'; +import { SloOutdatedCallout } from '../../components/slo/slo_outdated_callout'; export function SlosWelcomePage() { const { @@ -62,6 +63,7 @@ export function SlosWelcomePage() { return hasSlosAndHasPermissions || isLoading ? null : ( + diff --git a/x-pack/plugins/observability/public/routes/routes.tsx b/x-pack/plugins/observability/public/routes/routes.tsx index 87fc22c094344..7bfd2c2b25e08 100644 --- a/x-pack/plugins/observability/public/routes/routes.tsx +++ b/x-pack/plugins/observability/public/routes/routes.tsx @@ -31,6 +31,7 @@ import { RULES_LOGS_PATH, RULES_PATH, RULE_DETAIL_PATH, + SLOS_OUTDATED_DEFINITIONS_PATH, SLOS_PATH, SLOS_WELCOME_PATH, SLO_CREATE_PATH, @@ -38,6 +39,7 @@ import { SLO_EDIT_PATH, } from '../../common/locators/paths'; import { HasDataContextProvider } from '../context/has_data_context/has_data_context'; +import { SlosOutdatedDefinitions } from '../pages/slo_outdated_definitions'; // Note: React Router DOM component was not working here // so I've recreated this simple version for this purpose. @@ -158,6 +160,13 @@ export const routes = { params: {}, exact: true, }, + [SLOS_OUTDATED_DEFINITIONS_PATH]: { + handler: () => { + return ; + }, + params: {}, + exact: true, + }, [SLO_EDIT_PATH]: { handler: () => { return ; From e52fb76d2e3b5042d4e8b9e875a0e64ac20f2e79 Mon Sep 17 00:00:00 2001 From: Jared Burgett <147995946+jaredburgettelastic@users.noreply.github.com> Date: Tue, 12 Dec 2023 13:58:49 -0600 Subject: [PATCH 8/9] Small typo corrections in entity-analytics (#172994) ## Summary Corrects typos within entity-analytics comments --------- Co-authored-by: Ryland Herrick Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/lib/entity_analytics/utils/create_datastream.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/utils/create_datastream.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/utils/create_datastream.ts index 3ca4572d945ed..491cb5e61122b 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/utils/create_datastream.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/utils/create_datastream.ts @@ -6,8 +6,7 @@ */ // This file is a copy of x-pack/plugins/alerting/server/alerts_service/lib/create_concrete_write_index.ts -// original function create index instead of datastream, and their have plan to use datastream in the future -// so we probably should remove this file and use the original when datastream will be supported +// The original function created an index, while here we create a datastream. If and when responseOps develops first-party code to work with datastreams (https://github.com/elastic/kibana/issues/140403), this file should be removed. import { get } from 'lodash'; import type { IndicesSimulateIndexTemplateResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; From 849e3d4309d5a7db61955f6bb46b87d74ddfc464 Mon Sep 17 00:00:00 2001 From: Kyle Pollich Date: Tue, 12 Dec 2023 15:44:44 -0500 Subject: [PATCH 9/9] [Fleet] Cleanup some noisier logs (#173199) ## Summary Cleans up a few logging calls added in https://github.com/elastic/kibana/pull/172657 that are just a bit noisy, like logging package archive paths and full handlebars template contents. e.g. ![image](https://github.com/elastic/kibana/assets/6766512/90ca4a2d-e640-4899-9316-e0e786db7f8c) ![image](https://github.com/elastic/kibana/assets/6766512/af079c3a-71f1-4cdb-82ac-84fd0402bd75) --- x-pack/plugins/fleet/server/services/epm/agent/agent.ts | 1 - .../fleet/server/services/epm/packages/_install_package.ts | 2 +- x-pack/plugins/fleet/server/services/epm/packages/install.ts | 4 +--- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/epm/agent/agent.ts b/x-pack/plugins/fleet/server/services/epm/agent/agent.ts index 22d00451ce231..b58ab3e3fca0c 100644 --- a/x-pack/plugins/fleet/server/services/epm/agent/agent.ts +++ b/x-pack/plugins/fleet/server/services/epm/agent/agent.ts @@ -21,7 +21,6 @@ export function compileTemplate(variables: PackagePolicyConfigRecord, templateSt const { vars, yamlValues } = buildTemplateVariables(logger, variables); let compiledTemplate: string; try { - logger.debug(`Compiling agent template: ${templateStr}`); const template = handlebars.compile(templateStr, { noEscape: true }); compiledTemplate = template(vars); } catch (err) { diff --git a/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts index 5039891eef59d..8f45e8eee6b13 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts @@ -381,7 +381,7 @@ export async function _installPackage({ await packagePolicyService.upgrade(savedObjectsClient, esClient, policyIdsToUpgrade.items); }); } - logger.debug(`Package install - Installation complete}`); + logger.debug(`Package install - Installation complete`); return [...installedKibanaAssetsRefs, ...esReferences]; } catch (err) { if (SavedObjectsErrorHelpers.isConflictError(err)) { diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.ts index d4f9cd249177d..33f1b3a6ab73e 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.ts @@ -516,9 +516,7 @@ async function installPackageCommon(options: { } = options; let { telemetryEvent } = options; const logger = appContextService.getLogger(); - logger.info( - `Install - Starting installation of ${pkgName}@${pkgVersion} from ${installSource}, paths: ${paths}` - ); + logger.info(`Install - Starting installation of ${pkgName}@${pkgVersion} from ${installSource} `); // Workaround apm issue with async spans: https://github.com/elastic/apm-agent-nodejs/issues/2611 await Promise.resolve();