From cdbe901c62c019568a6919210a1d71278b580fce Mon Sep 17 00:00:00 2001 From: Nick Peihl Date: Tue, 20 Apr 2021 21:15:56 -0700 Subject: [PATCH 01/18] [Maps] Update to EMS v7.13 (#97732) (#97772) * Update to EMS 7.13 * Fix topojson typings Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> # Conflicts: # package.json --- package.json | 2 +- src/plugins/maps_ems/common/ems_defaults.ts | 2 +- x-pack/plugins/maps/public/util.ts | 4 +-- yarn.lock | 31 +++++++++++++++++---- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 9b8c6ac306f6a..94d357d117927 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "@elastic/charts": "28.2.0", "@elastic/datemath": "link:bazel-bin/packages/elastic-datemath/npm_module", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@7.13.0-canary.1", - "@elastic/ems-client": "7.12.0", + "@elastic/ems-client": "7.13.0", "@elastic/eui": "32.1.0", "@elastic/filesaver": "1.1.2", "@elastic/good": "^9.0.1-kibana3", diff --git a/src/plugins/maps_ems/common/ems_defaults.ts b/src/plugins/maps_ems/common/ems_defaults.ts index d29d47fb19dbb..a494386b100b7 100644 --- a/src/plugins/maps_ems/common/ems_defaults.ts +++ b/src/plugins/maps_ems/common/ems_defaults.ts @@ -9,7 +9,7 @@ // Default config for the elastic hosted EMS endpoints export const DEFAULT_EMS_FILE_API_URL = 'https://vector.maps.elastic.co'; export const DEFAULT_EMS_TILE_API_URL = 'https://tiles.maps.elastic.co'; -export const DEFAULT_EMS_LANDING_PAGE_URL = 'https://maps.elastic.co/v7.12'; +export const DEFAULT_EMS_LANDING_PAGE_URL = 'https://maps.elastic.co/v7.13'; export const DEFAULT_EMS_FONT_LIBRARY_URL = 'https://tiles.maps.elastic.co/fonts/{fontstack}/{range}.pbf'; diff --git a/x-pack/plugins/maps/public/util.ts b/x-pack/plugins/maps/public/util.ts index 2745f9274f119..7cae3d4d5e936 100644 --- a/x-pack/plugins/maps/public/util.ts +++ b/x-pack/plugins/maps/public/util.ts @@ -8,8 +8,8 @@ import { i18n } from '@kbn/i18n'; import { EMSClient, FileLayer, TMSService } from '@elastic/ems-client'; import { FeatureCollection } from 'geojson'; -// @ts-expect-error import * as topojson from 'topojson-client'; +import { GeometryCollection } from 'topojson-specification'; import _ from 'lodash'; import fetch from 'node-fetch'; @@ -145,7 +145,7 @@ export async function fetchGeoJson( } if (format === FORMAT_TYPE.TOPOJSON) { - const features = _.get(fetchedJson, `objects.${featureCollectionPath}`); + const features = _.get(fetchedJson, `objects.${featureCollectionPath}`) as GeometryCollection; return topojson.feature(fetchedJson, features); } diff --git a/yarn.lock b/yarn.lock index 73b53f4ea24ad..b536cde8ff6bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1400,13 +1400,19 @@ pump "^3.0.0" secure-json-parse "^2.3.1" -"@elastic/ems-client@7.12.0": - version "7.12.0" - resolved "https://registry.yarnpkg.com/@elastic/ems-client/-/ems-client-7.12.0.tgz#cf83f5ad76e26cedfa6f5b91277d2d919b9423d1" - integrity sha512-Svv3boWL1n14nIt6tL9gaA9Ym1B4AwWl6ISZT62+uKM2G+imZxWLkqpQc/HHcf7TfuAmleF2NFwnT5vw2vZTpA== +"@elastic/ems-client@7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@elastic/ems-client/-/ems-client-7.13.0.tgz#de291a6eb25523e5844a9e74ae72fd2e81a1f4d9" + integrity sha512-VdK5jZdnC+5BSkMRQsqHqrsZ9HttnPjQmCjRlAGuV8y6g0eKVP9ZiMRQFKFKmuSKpx0kHGsSV/1kBglTmSl/3g== dependencies: + "@types/geojson" "^7946.0.7" + "@types/lru-cache" "^5.1.0" + "@types/topojson-client" "^3.0.0" + "@types/topojson-specification" "^1.0.1" lodash "^4.17.15" + lru-cache "^6.0.0" semver "7.3.2" + topojson-client "^3.1.0" "@elastic/eslint-config-kibana@link:packages/elastic-eslint-config-kibana": version "0.0.0" @@ -4827,7 +4833,7 @@ dependencies: "@types/node" "*" -"@types/geojson@*", "@types/geojson@7946.0.7": +"@types/geojson@*", "@types/geojson@7946.0.7", "@types/geojson@^7946.0.7": version "7946.0.7" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.7.tgz#c8fa532b60a0042219cdf173ca21a975ef0666ad" integrity sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ== @@ -5879,6 +5885,21 @@ resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.2.tgz#721ca5c5d1a2988b4a886e35c2ffc5735b6afbdf" integrity sha512-PeHg/AtdW6aaIO2a+98Xj7rWY4KC1E6yOy7AFknJQ7VXUGNrMlyxDFxJo7HqLtjQms/ZhhQX52mLVW/EX3JGOw== +"@types/topojson-client@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/topojson-client/-/topojson-client-3.1.0.tgz#2fd96d5e64f4f512742f22194f3e1e0443c27233" + integrity sha512-wmjTmMkF6k6m3Tn4mIyRjw8KUQZLHB1TxNcpGYirvV/aCINkC0eMJsUO/OPMkKIB6VO5iA6Vp39bmAq6QgvSfA== + dependencies: + "@types/geojson" "*" + "@types/topojson-specification" "*" + +"@types/topojson-specification@*", "@types/topojson-specification@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/topojson-specification/-/topojson-specification-1.0.1.tgz#a80cb294290b79f2d674d3f5938c544ed2bd9d80" + integrity sha512-ZZYZUgkmUls9Uhxx2WZNt9f/h2+H3abUUjOVmq+AaaDFckC5oAwd+MDp95kBirk+XCXrYj0hfpI6DSUiJMrpYQ== + dependencies: + "@types/geojson" "*" + "@types/tough-cookie@*": version "2.3.5" resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.5.tgz#9da44ed75571999b65c37b60c9b2b88db54c585d" From cba89b242cbd10acbca61b88af13366dd41fa0d2 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 21 Apr 2021 03:35:19 -0400 Subject: [PATCH 02/18] [Security-Solution] Adds warning message for selected ML jobs not running, adds tooltip to combobox (#97764) (#97775) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Security-Solution] Adds warning message for selected ML jobs not running, adds tooltip to combobox * updates i18n * update strings * updates strings * fixes i18n error Co-authored-by: Ece Özalp --- .../rules/ml_job_select/help_text.test.tsx | 22 ++++++ .../rules/ml_job_select/help_text.tsx | 68 +++++++++++++++++ .../components/rules/ml_job_select/index.tsx | 74 +++++++------------ .../rules/step_define_rule/translations.tsx | 8 -- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 6 files changed, 115 insertions(+), 59 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/help_text.test.tsx create mode 100644 x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/help_text.tsx diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/help_text.test.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/help_text.test.tsx new file mode 100644 index 0000000000000..3db1beb5bb743 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/help_text.test.tsx @@ -0,0 +1,22 @@ +/* + * 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 { shallow } from 'enzyme'; +import { HelpText } from './help_text'; + +describe('MlJobSelect help text', () => { + it('does not show warning if all jobs are running', () => { + const wrapper = shallow(); + expect(wrapper.find('[data-test-subj="ml-warning-not-running-jobs"]')).toHaveLength(0); + }); + + it('shows warning if there are jobs not running', () => { + const wrapper = shallow(); + expect(wrapper.find('[data-test-subj="ml-warning-not-running-jobs"]')).toHaveLength(1); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/help_text.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/help_text.tsx new file mode 100644 index 0000000000000..5195679c13d2a --- /dev/null +++ b/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/help_text.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 React from 'react'; +import { EuiIcon, EuiLink, EuiText } from '@elastic/eui'; +import styled from 'styled-components'; + +import { FormattedMessage } from '@kbn/i18n/react'; + +const HelpTextWarningContainer = styled.div` + margin-top: 10px; +`; + +const HelpTextComponent: React.FC<{ href: string; notRunningJobIds: string[] }> = ({ + href, + notRunningJobIds, +}) => ( + <> + + + + ), + }} + /> + {notRunningJobIds.length > 0 && ( + + + + + {notRunningJobIds.length === 1 ? ( + + ) : ( + acc + (i < array.length - 1 ? ', ' : ', and ') + value + ), + }} + /> + )} + + + + )} + +); + +export const HelpText = React.memo(HelpTextComponent); diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/index.tsx index e5521492d3b5e..6d7b5d4acc5b8 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/index.tsx @@ -6,15 +6,13 @@ */ import React, { useCallback, useMemo } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; import { EuiComboBox, EuiComboBoxOptionOption, EuiFlexGroup, EuiFlexItem, EuiFormRow, - EuiIcon, - EuiLink, + EuiToolTip, EuiText, } from '@elastic/eui'; @@ -23,63 +21,36 @@ import { isJobStarted } from '../../../../../common/machine_learning/helpers'; import { FieldHook, getFieldValidityAndErrorMessage } from '../../../../shared_imports'; import { useSecurityJobs } from '../../../../common/components/ml_popover/hooks/use_security_jobs'; import { useKibana } from '../../../../common/lib/kibana'; -import { - ML_JOB_SELECT_PLACEHOLDER_TEXT, - ENABLE_ML_JOB_WARNING, -} from '../step_define_rule/translations'; +import { ML_JOB_SELECT_PLACEHOLDER_TEXT } from '../step_define_rule/translations'; +import { HelpText } from './help_text'; interface MlJobValue { id: string; description: string; } -type MlJobOption = EuiComboBoxOptionOption; - -const HelpTextWarningContainer = styled.div` - margin-top: 10px; +const JobDisplayContainer = styled.div` + width: 100%; + height: 100%; + display: flex; + flex-direction: column; `; +type MlJobOption = EuiComboBoxOptionOption; + const MlJobSelectEuiFlexGroup = styled(EuiFlexGroup)` margin-bottom: 5px; `; -const HelpText: React.FC<{ href: string; showEnableWarning: boolean }> = ({ - href, - showEnableWarning = false, -}) => ( - <> - - - - ), - }} - /> - {showEnableWarning && ( - - - - {ENABLE_ML_JOB_WARNING} - - - )} - -); - const JobDisplay: React.FC = ({ id, description }) => ( - <> + {id} - -

{description}

-
- + + +

{description}

+
+
+
); interface MlJobSelectProps { @@ -114,9 +85,14 @@ export const MlJobSelect: React.FC = ({ describedByIds = [], f const selectedJobOptions = jobOptions.filter((option) => jobIds.includes(option.value.id)); - const allJobsRunning = useMemo(() => { + const notRunningJobIds = useMemo(() => { const selectedJobs = jobs.filter(({ id }) => jobIds.includes(id)); - return selectedJobs.every((job) => isJobStarted(job.jobState, job.datafeedState)); + return selectedJobs.reduce((acc, job) => { + if (!isJobStarted(job.jobState, job.datafeedState)) { + acc.push(job.id); + } + return acc; + }, [] as string[]); }, [jobs, jobIds]); return ( @@ -124,7 +100,7 @@ export const MlJobSelect: React.FC = ({ describedByIds = [], f } + helpText={} isInvalid={isInvalid} error={errorMessage} data-test-subj="mlJobSelect" diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/translations.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/translations.tsx index 273c8cf28a18a..7b5342d85f82a 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/translations.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/translations.tsx @@ -64,14 +64,6 @@ export const ML_JOB_SELECT_PLACEHOLDER_TEXT = i18n.translate( } ); -export const ENABLE_ML_JOB_WARNING = i18n.translate( - 'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.mlEnableJobWarningTitle', - { - defaultMessage: - 'One or more selected ML jobs are not currently running. Please set these job(s) to run via "ML job settings" before activating this rule.', - } -); - export const QUERY_BAR_LABEL = i18n.translate( 'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.fieldQuerBarLabel', { diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a2460e51aa5c8..1369b79313093 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -18323,7 +18323,6 @@ "xpack.securitySolution.detectionEngine.createRule.stepDefineRule.indicesHelperDescription": "このルールを実行するElasticsearchインデックスのパターンを入力します。デフォルトでは、セキュリティソリューション詳細設定で定義されたインデックスパターンが含まれます。", "xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningJobIdHelpText": "手始めに使えるように、一般的なジョブがいくつか提供されています。独自のカスタムジョブを追加するには、{machineLearning} アプリケーションでジョブに「security」のグループを割り当て、ここに表示されるようにします。", "xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningJobIdRequired": "機械学習ジョブが必要です。", - "xpack.securitySolution.detectionEngine.createRule.stepDefineRule.mlEnableJobWarningTitle": "このMLジョブは現在実行されていません。このルールを有効にする前に、このジョブを「MLジョブ設定」で実行するように設定してください。", "xpack.securitySolution.detectionEngine.createRule.stepDefineRule.mlJobSelectPlaceholderText": "ジョブを選択してください", "xpack.securitySolution.detectionEngine.createRule.stepDefineRule.outputIndiceNameFieldRequiredError": "インデックスパターンが最低1つ必要です。", "xpack.securitySolution.detectionEngine.createRule.stepDefineRule.referencesUrlInvalidError": "URLの形式が無効です", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 2f587f1ac6ed7..482924f50f5de 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -18591,7 +18591,6 @@ "xpack.securitySolution.detectionEngine.createRule.stepDefineRule.indicesHelperDescription": "输入要运行此规则的 Elasticsearch 索引的模式。默认情况下,将包括 Security Solution 高级设置中定义的索引模式。", "xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningJobIdHelpText": "我们提供了一些常见作业来帮助您入门。要添加自己的定制规则,请在 {machineLearning} 应用程序中将一组“security”分配给这些作业,以使其显示在此处。", "xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningJobIdRequired": "Machine Learning 作业必填。", - "xpack.securitySolution.detectionEngine.createRule.stepDefineRule.mlEnableJobWarningTitle": "此 ML 作业当前未运行。在激活此规则之前请通过“ML 作业设置”设置此作业以使其运行。", "xpack.securitySolution.detectionEngine.createRule.stepDefineRule.mlJobSelectPlaceholderText": "选择作业", "xpack.securitySolution.detectionEngine.createRule.stepDefineRule.outputIndiceNameFieldRequiredError": "至少需要一个索引模式。", "xpack.securitySolution.detectionEngine.createRule.stepDefineRule.referencesUrlInvalidError": "Url 的格式无效", From eca56f345084e8abeb98aad167336787d9bc49b9 Mon Sep 17 00:00:00 2001 From: Angela Chuang <6295984+angorayc@users.noreply.github.com> Date: Wed, 21 Apr 2021 09:03:24 +0100 Subject: [PATCH 03/18] [SecuritySolution] remove files that are not in used (#97740) (#97779) * remove files that are not in used * remove files that are not in used --- .../plugins/security_solution/.gitattributes | 6 - x-pack/plugins/security_solution/package.json | 1 - .../server/lib/framework/types.ts | 2 - .../server/utils/build_query/field.mock.ts | 172 ------------------ .../server/utils/build_query/fields.test.ts | 27 --- .../server/utils/build_query/fields.ts | 34 ---- .../server/utils/build_query/index.ts | 1 - .../server/utils/typed_resolvers.ts | 108 ----------- 8 files changed, 351 deletions(-) delete mode 100644 x-pack/plugins/security_solution/.gitattributes delete mode 100644 x-pack/plugins/security_solution/server/utils/build_query/field.mock.ts delete mode 100644 x-pack/plugins/security_solution/server/utils/build_query/fields.test.ts delete mode 100644 x-pack/plugins/security_solution/server/utils/build_query/fields.ts delete mode 100644 x-pack/plugins/security_solution/server/utils/typed_resolvers.ts diff --git a/x-pack/plugins/security_solution/.gitattributes b/x-pack/plugins/security_solution/.gitattributes deleted file mode 100644 index 431f25be5e78e..0000000000000 --- a/x-pack/plugins/security_solution/.gitattributes +++ /dev/null @@ -1,6 +0,0 @@ -# Auto-collapse generated files in GitHub -# https://help.github.com/en/articles/customizing-how-changed-files-appear-on-github -x-pack/plugins/security_solution/server/graphql/types.ts linguist-generated=true -x-pack/plugins/security_solution/public/graphql/types.ts linguist-generated=true -x-pack/plugins/security_solution/public/graphql/introspection.json linguist-generated=true - diff --git a/x-pack/plugins/security_solution/package.json b/x-pack/plugins/security_solution/package.json index 211e6986e19a7..f35974d84164e 100644 --- a/x-pack/plugins/security_solution/package.json +++ b/x-pack/plugins/security_solution/package.json @@ -7,7 +7,6 @@ "scripts": { "extract-mitre-attacks": "node scripts/extract_tactics_techniques_mitre.js && node ../../../scripts/eslint ./public/detections/mitre/mitre_tactics_techniques.ts --fix", "build-beat-doc": "node scripts/beat_docs/build.js && node ../../../scripts/eslint ./server/utils/beat_schema/fields.ts --fix", - "build-graphql-types": "node scripts/generate_types_from_graphql.js", "cypress:open": "../../../node_modules/.bin/cypress open --config-file ./cypress/cypress.json", "cypress:open-as-ci": "node ../../../scripts/functional_tests --config ../../test/security_solution_cypress/visual_config.ts", "cypress:run": "../../../node_modules/.bin/cypress run --browser chrome --headless --spec ./cypress/integration/**/*.spec.ts --config-file ./cypress/cypress.json --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=./cypress/reporter_config.json; status=$?; ../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-security-solution/cypress/results/mochawesome*.json > ../../../target/kibana-security-solution/cypress/results/output.json; ../../../node_modules/.bin/marge ../../../target/kibana-security-solution/cypress/results/output.json --reportDir ../../../target/kibana-security-solution/cypress/results; mkdir -p ../../../target/junit && cp ../../../target/kibana-security-solution/cypress/results/*.xml ../../../target/junit/ && exit $status;", diff --git a/x-pack/plugins/security_solution/server/lib/framework/types.ts b/x-pack/plugins/security_solution/server/lib/framework/types.ts index 34012f8f15d16..6665468a27125 100644 --- a/x-pack/plugins/security_solution/server/lib/framework/types.ts +++ b/x-pack/plugins/security_solution/server/lib/framework/types.ts @@ -20,8 +20,6 @@ import { } from '../../../common/search_strategy'; import { SourceConfiguration } from '../sources'; -export * from '../../utils/typed_resolvers'; - export const internalFrameworkRequest = Symbol('internalFrameworkRequest'); export interface FrameworkAdapter { diff --git a/x-pack/plugins/security_solution/server/utils/build_query/field.mock.ts b/x-pack/plugins/security_solution/server/utils/build_query/field.mock.ts deleted file mode 100644 index 3c8d1b4c1d6b3..0000000000000 --- a/x-pack/plugins/security_solution/server/utils/build_query/field.mock.ts +++ /dev/null @@ -1,172 +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 { FieldNode } from 'graphql'; - -export const mockFields: FieldNode = { - kind: 'Field', - name: { - kind: 'Name', - value: 'Hosts', - }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { - kind: 'Name', - value: 'totalCount', - }, - arguments: [], - directives: [], - }, - { - kind: 'Field', - name: { - kind: 'Name', - value: 'edges', - }, - arguments: [], - directives: [], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { - kind: 'Name', - value: 'host', - }, - arguments: [], - directives: [], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { - kind: 'Name', - value: '_id', - }, - arguments: [], - directives: [], - }, - { - kind: 'Field', - name: { - kind: 'Name', - value: 'name', - }, - arguments: [], - directives: [], - }, - { - kind: 'Field', - name: { - kind: 'Name', - value: 'os', - }, - arguments: [], - directives: [], - }, - { - kind: 'Field', - name: { - kind: 'Name', - value: 'version', - }, - arguments: [], - directives: [], - }, - { - kind: 'Field', - name: { - kind: 'Name', - value: 'firstSeen', - }, - arguments: [], - directives: [], - }, - ], - }, - }, - { - kind: 'Field', - name: { - kind: 'Name', - value: 'cursor', - }, - arguments: [], - directives: [], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { - kind: 'Name', - value: 'value', - }, - arguments: [], - directives: [], - }, - ], - }, - }, - ], - }, - }, - { - kind: 'Field', - name: { - kind: 'Name', - value: 'pageInfo', - }, - arguments: [], - directives: [], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { - kind: 'Name', - value: 'endCursor', - }, - arguments: [], - directives: [], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { - kind: 'Name', - value: 'value', - }, - arguments: [], - directives: [], - }, - ], - }, - }, - { - kind: 'Field', - name: { - kind: 'Name', - value: 'hasNextPage', - }, - arguments: [], - directives: [], - }, - ], - }, - }, - ], - }, -}; diff --git a/x-pack/plugins/security_solution/server/utils/build_query/fields.test.ts b/x-pack/plugins/security_solution/server/utils/build_query/fields.test.ts deleted file mode 100644 index b34a3f7ed63a6..0000000000000 --- a/x-pack/plugins/security_solution/server/utils/build_query/fields.test.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 { mockFields } from './field.mock'; -import { getFields } from './fields'; - -describe('the ConfigurationSourcesAdapter', () => { - test('adds the default source when no sources are configured', async () => { - const expectedData = [ - 'totalCount', - 'edges.host._id', - 'edges.host.name', - 'edges.host.os', - 'edges.host.version', - 'edges.host.firstSeen', - 'edges.cursor.value', - 'pageInfo.endCursor.value', - 'pageInfo.hasNextPage', - ]; - - expect(getFields(mockFields)).toEqual(expectedData); - }); -}); diff --git a/x-pack/plugins/security_solution/server/utils/build_query/fields.ts b/x-pack/plugins/security_solution/server/utils/build_query/fields.ts deleted file mode 100644 index da7fb1e2af819..0000000000000 --- a/x-pack/plugins/security_solution/server/utils/build_query/fields.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FieldNode, SelectionNode, SelectionSetNode } from 'graphql'; -import { isEmpty } from 'lodash/fp'; - -export const getFields = ( - data: SelectionSetNode | FieldNode, - fields: string[] = [], - postFields: string[] = [] -): string[] => { - if (data.kind === 'Field' && data.selectionSet && !isEmpty(data.selectionSet.selections)) { - return getFields(data.selectionSet, fields); - } else if (data.kind === 'SelectionSet') { - return data.selections.reduce((res: string[], item: SelectionNode) => { - if (item.kind === 'Field') { - const field: FieldNode = item as FieldNode; - if (field.name.kind === 'Name' && field.name.value.includes('kpi')) { - return [...res, field.name.value]; - } else if (field.selectionSet && !isEmpty(field.selectionSet.selections)) { - return getFields(field.selectionSet, res, postFields.concat(field.name.value)); - } - return [...res, [...postFields, field.name.value].join('.')]; - } - return res; - }, fields as string[]); - } - - return fields; -}; diff --git a/x-pack/plugins/security_solution/server/utils/build_query/index.ts b/x-pack/plugins/security_solution/server/utils/build_query/index.ts index 7e06b6dbaa89a..61c4831f7f72f 100644 --- a/x-pack/plugins/security_solution/server/utils/build_query/index.ts +++ b/x-pack/plugins/security_solution/server/utils/build_query/index.ts @@ -5,7 +5,6 @@ * 2.0. */ -export * from './fields'; export * from './filters'; export * from './merge_fields_with_hits'; export * from './calculate_timeseries_interval'; diff --git a/x-pack/plugins/security_solution/server/utils/typed_resolvers.ts b/x-pack/plugins/security_solution/server/utils/typed_resolvers.ts deleted file mode 100644 index 96156797892dc..0000000000000 --- a/x-pack/plugins/security_solution/server/utils/typed_resolvers.ts +++ /dev/null @@ -1,108 +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 { GraphQLResolveInfo } from 'graphql'; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export type Resolver = ( - parent: Parent, - args: Args, - context: TContext, - info: GraphQLResolveInfo -) => Promise | Result; - -type ResolverResult = R | Promise; - -type AppResolverResult = - | Promise - | Promise<{ [P in keyof R]: () => Promise }> - | { [P in keyof R]: () => Promise } - | { [P in keyof R]: () => R[P] } - | R; - -export type ResultOf = Resolver_ extends Resolver> - ? Result - : never; - -export type SubsetResolverWithFields = R extends Resolver< - Array, - infer ParentInArray, - infer ContextInArray, - infer ArgsInArray -> - ? Resolver< - Array>>, - ParentInArray, - ContextInArray, - ArgsInArray - > - : R extends Resolver - ? Resolver>, Parent, Context, Args> - : never; - -export type SubsetResolverWithoutFields = R extends Resolver< - Array, - infer ParentInArray, - infer ContextInArray, - infer ArgsInArray -> - ? Resolver< - Array>>, - ParentInArray, - ContextInArray, - ArgsInArray - > - : R extends Resolver - ? Resolver>, Parent, Context, Args> - : never; - -export type ResolverWithParent = Resolver_ extends Resolver< - infer Result, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - any, - infer Context, - infer Args -> - ? Resolver - : never; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export type AppResolver = Resolver< - AppResolverResult, - Parent, - Context, - Args ->; - -export type AppResolverOf = Resolver_ extends Resolver< - ResolverResult, - never, - infer ContextWithNeverParent, - infer ArgsWithNeverParent -> - ? AppResolver - : Resolver_ extends Resolver< - ResolverResult, - infer Parent, - infer Context, - infer Args - > - ? AppResolver - : never; - -export type AppResolverWithFields = AppResolverOf< - SubsetResolverWithFields ->; - -export type AppResolverWithoutFields = AppResolverOf< - SubsetResolverWithoutFields ->; - -export type ChildResolverOf = ResolverWithParent< - Resolver_, - ResultOf ->; From 4036a0c3758deb9be16e6c7f1d588ce81483fd55 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Wed, 21 Apr 2021 11:09:31 +0300 Subject: [PATCH 04/18] [TSVB] Fix working with kibana rollup indexes which includes wildcard symbol (*) (#97594) (#97640) * Fix working with kibana rollup indexes which includes wildcard in tsvb * Fix CI --- .../search_strategies/strategies/rollup_search_strategy.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts index ec6f2a7c21af6..0ac00863d0a73 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts @@ -58,8 +58,8 @@ export class RollupSearchStrategy extends AbstractSearchStrategy { if ( indexPatternString && - !isIndexPatternContainsWildcard(indexPatternString) && - (!indexPattern || indexPattern.type === 'rollup') + ((!indexPattern && !isIndexPatternContainsWildcard(indexPatternString)) || + indexPattern?.type === 'rollup') ) { const rollupData = await this.getRollupData(requestContext, indexPatternString); const rollupIndices = getRollupIndices(rollupData); From efe6371cf218b931ba7190f131a6cf4b3014ecb1 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Wed, 21 Apr 2021 11:47:41 +0200 Subject: [PATCH 05/18] Fix missing localization in Discover options (#97670) (#97781) --- .../top_nav/open_options_popover.tsx | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/plugins/discover/public/application/components/top_nav/open_options_popover.tsx b/src/plugins/discover/public/application/components/top_nav/open_options_popover.tsx index 6eb7fccd3aaa8..fb8d061bcf4a6 100644 --- a/src/plugins/discover/public/application/components/top_nav/open_options_popover.tsx +++ b/src/plugins/discover/public/application/components/top_nav/open_options_popover.tsx @@ -14,6 +14,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { EuiSpacer, EuiButton, EuiText, EuiWrappingPopover, EuiCode } from '@elastic/eui'; import { getServices } from '../../../kibana_services'; import './open_options_popover.scss'; +import { DOC_TABLE_LEGACY } from '../../../../common'; let isOpen = false; @@ -27,7 +28,7 @@ export function OptionsPopover(props: OptionsPopoverProps) { core: { uiSettings }, addBasePath, } = getServices(); - const isLegacy = uiSettings.get('doc_table:legacy'); + const isLegacy = uiSettings.get(DOC_TABLE_LEGACY); const mode = isLegacy ? i18n.translate('discover.openOptionsPopover.legacyTableText', { @@ -42,8 +43,21 @@ export function OptionsPopover(props: OptionsPopoverProps) {

- Current view mode:{' '} - {mode} + + + + ), + currentViewMode: {mode}, + }} + />

@@ -57,7 +71,7 @@ export function OptionsPopover(props: OptionsPopoverProps) { {i18n.translate('discover.openOptionsPopover.goToAdvancedSettings', { defaultMessage: 'Go to Advanced Settings', From 8fbc19b367c4ae19ca310d15022f4737f2204949 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Wed, 21 Apr 2021 12:24:20 +0200 Subject: [PATCH 06/18] [Discover] Increase default pagination size to 100 (#97742) (#97783) --- .../public/application/components/discover_grid/constants.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/discover/public/application/components/discover_grid/constants.ts b/src/plugins/discover/public/application/components/discover_grid/constants.ts index de2781cf159c3..34e6ca20740ad 100644 --- a/src/plugins/discover/public/application/components/discover_grid/constants.ts +++ b/src/plugins/discover/public/application/components/discover_grid/constants.ts @@ -15,8 +15,8 @@ export const gridStyle = { rowHover: 'none', }; -export const pageSizeArr = [25, 50, 100]; -export const defaultPageSize = 25; +export const pageSizeArr = [25, 50, 100, 250]; +export const defaultPageSize = 100; export const toolbarVisibility = { showColumnSelector: { allowHide: false, From 64c37c75cc9731ac725fb6e23a05984bec7e3fd9 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 21 Apr 2021 06:27:48 -0400 Subject: [PATCH 07/18] [Lens] Improve error message for scripted (and runtime) fields (#96611) (#97785) * :sparkles: Improve error message for scripted fields * :ok_hand: Extract nested error info * :lipstick: Use word break * :recycle: reworked code to better use data types * :bug: Fix i18n issue * :pencil2: Fix typo * :memo: Update data plugin API * :bug: Fix react issue * :white_check_mark: Check more error scenarios and add tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Marco Liberati --- ...ana-plugin-plugins-data-public.ieserror.md | 11 ++ ...na-plugin-plugins-data-public.iseserror.md | 24 +++ .../kibana-plugin-plugins-data-public.md | 3 + ...in-plugins-data-public.reason.caused_by.md | 14 ++ ...-plugin-plugins-data-public.reason.lang.md | 11 ++ ...ibana-plugin-plugins-data-public.reason.md | 24 +++ ...gin-plugins-data-public.reason.position.md | 15 ++ ...lugin-plugins-data-public.reason.reason.md | 11 ++ ...lugin-plugins-data-public.reason.script.md | 11 ++ ...plugins-data-public.reason.script_stack.md | 11 ++ ...-plugin-plugins-data-public.reason.type.md | 11 ++ src/plugins/data/public/index.ts | 3 + src/plugins/data/public/public.api.md | 69 +++++-- .../data/public/search/errors/types.ts | 1 + .../workspace_panel/workspace_panel.tsx | 22 ++- .../embeddable/expression_wrapper.tsx | 8 +- .../editor_frame_service/error_helper.test.ts | 179 ++++++++++++++++++ .../editor_frame_service/error_helper.ts | 127 +++++++++---- 18 files changed, 492 insertions(+), 63 deletions(-) create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ieserror.md create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iseserror.md create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.caused_by.md create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.lang.md create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.md create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.position.md create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.reason.md create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.script.md create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.script_stack.md create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.type.md create mode 100644 x-pack/plugins/lens/public/editor_frame_service/error_helper.test.ts diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ieserror.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ieserror.md new file mode 100644 index 0000000000000..df571e4ed4961 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ieserror.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IEsError](./kibana-plugin-plugins-data-public.ieserror.md) + +## IEsError type + +Signature: + +```typescript +export declare type IEsError = KibanaServerError; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iseserror.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iseserror.md new file mode 100644 index 0000000000000..379877c9b5c0a --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iseserror.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [isEsError](./kibana-plugin-plugins-data-public.iseserror.md) + +## isEsError() function + +Checks if a given errors originated from Elasticsearch. Those params are assigned to the attributes property of an error. + +Signature: + +```typescript +export declare function isEsError(e: any): e is IEsError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| e | any | | + +Returns: + +`e is IEsError` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md index 4429f45f55645..58a225a3a4bc3 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md @@ -46,6 +46,7 @@ | [getEsPreference(uiSettings, sessionId)](./kibana-plugin-plugins-data-public.getespreference.md) | | | [getSearchParamsFromRequest(searchRequest, dependencies)](./kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md) | | | [getTime(indexPattern, timeRange, options)](./kibana-plugin-plugins-data-public.gettime.md) | | +| [isEsError(e)](./kibana-plugin-plugins-data-public.iseserror.md) | Checks if a given errors originated from Elasticsearch. Those params are assigned to the attributes property of an error. | | [plugin(initializerContext)](./kibana-plugin-plugins-data-public.plugin.md) | | | [waitUntilNextSessionCompletes$(sessionService, { waitForIdle })](./kibana-plugin-plugins-data-public.waituntilnextsessioncompletes_.md) | Creates an observable that emits when next search session completes. This utility is helpful to use in the application to delay some tasks until next session completes. | @@ -86,6 +87,7 @@ | [QuerySuggestionField](./kibana-plugin-plugins-data-public.querysuggestionfield.md) | \* | | [QuerySuggestionGetFnArgs](./kibana-plugin-plugins-data-public.querysuggestiongetfnargs.md) | \* | | [RangeFilterParams](./kibana-plugin-plugins-data-public.rangefilterparams.md) | | +| [Reason](./kibana-plugin-plugins-data-public.reason.md) | | | [RefreshInterval](./kibana-plugin-plugins-data-public.refreshinterval.md) | | | [SavedQuery](./kibana-plugin-plugins-data-public.savedquery.md) | | | [SavedQueryService](./kibana-plugin-plugins-data-public.savedqueryservice.md) | | @@ -161,6 +163,7 @@ | [Filter](./kibana-plugin-plugins-data-public.filter.md) | | | [IAggConfig](./kibana-plugin-plugins-data-public.iaggconfig.md) | AggConfig This class represents an aggregation, which is displayed in the left-hand nav of the Visualize app. | | [IAggType](./kibana-plugin-plugins-data-public.iaggtype.md) | | +| [IEsError](./kibana-plugin-plugins-data-public.ieserror.md) | | | [IEsSearchResponse](./kibana-plugin-plugins-data-public.iessearchresponse.md) | | | [IFieldFormat](./kibana-plugin-plugins-data-public.ifieldformat.md) | | | [IFieldFormatsRegistry](./kibana-plugin-plugins-data-public.ifieldformatsregistry.md) | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.caused_by.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.caused_by.md new file mode 100644 index 0000000000000..f1df7f98aad4c --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.caused_by.md @@ -0,0 +1,14 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Reason](./kibana-plugin-plugins-data-public.reason.md) > [caused\_by](./kibana-plugin-plugins-data-public.reason.caused_by.md) + +## Reason.caused\_by property + +Signature: + +```typescript +caused_by?: { + type: string; + reason: string; + }; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.lang.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.lang.md new file mode 100644 index 0000000000000..095142cf0f05b --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.lang.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Reason](./kibana-plugin-plugins-data-public.reason.md) > [lang](./kibana-plugin-plugins-data-public.reason.lang.md) + +## Reason.lang property + +Signature: + +```typescript +lang?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.md new file mode 100644 index 0000000000000..a1a76f2d2a295 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Reason](./kibana-plugin-plugins-data-public.reason.md) + +## Reason interface + +Signature: + +```typescript +export interface Reason +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [caused\_by](./kibana-plugin-plugins-data-public.reason.caused_by.md) | {
type: string;
reason: string;
} | | +| [lang](./kibana-plugin-plugins-data-public.reason.lang.md) | string | | +| [position](./kibana-plugin-plugins-data-public.reason.position.md) | {
offset: number;
start: number;
end: number;
} | | +| [reason](./kibana-plugin-plugins-data-public.reason.reason.md) | string | | +| [script\_stack](./kibana-plugin-plugins-data-public.reason.script_stack.md) | string[] | | +| [script](./kibana-plugin-plugins-data-public.reason.script.md) | string | | +| [type](./kibana-plugin-plugins-data-public.reason.type.md) | string | | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.position.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.position.md new file mode 100644 index 0000000000000..fc727f0aaf59e --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.position.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Reason](./kibana-plugin-plugins-data-public.reason.md) > [position](./kibana-plugin-plugins-data-public.reason.position.md) + +## Reason.position property + +Signature: + +```typescript +position?: { + offset: number; + start: number; + end: number; + }; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.reason.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.reason.md new file mode 100644 index 0000000000000..0e435cc7c5b85 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.reason.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Reason](./kibana-plugin-plugins-data-public.reason.md) > [reason](./kibana-plugin-plugins-data-public.reason.reason.md) + +## Reason.reason property + +Signature: + +```typescript +reason: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.script.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.script.md new file mode 100644 index 0000000000000..09451d51f087a --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.script.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Reason](./kibana-plugin-plugins-data-public.reason.md) > [script](./kibana-plugin-plugins-data-public.reason.script.md) + +## Reason.script property + +Signature: + +```typescript +script?: string; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.script_stack.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.script_stack.md new file mode 100644 index 0000000000000..e322481147ae9 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.script_stack.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Reason](./kibana-plugin-plugins-data-public.reason.md) > [script\_stack](./kibana-plugin-plugins-data-public.reason.script_stack.md) + +## Reason.script\_stack property + +Signature: + +```typescript +script_stack?: string[]; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.type.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.type.md new file mode 100644 index 0000000000000..482f191ae4aab --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.reason.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Reason](./kibana-plugin-plugins-data-public.reason.md) > [type](./kibana-plugin-plugins-data-public.reason.type.md) + +## Reason.type property + +Signature: + +```typescript +type: string; +``` diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index e86b64d135d59..f2a61e94a07d9 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -380,14 +380,17 @@ export { EsdslExpressionFunctionDefinition, EsRawResponseExpressionTypeDefinition, // errors + IEsError, SearchError, SearchTimeoutError, TimeoutErrorMode, PainlessError, + Reason, noSearchSessionStorageCapabilityMessage, SEARCH_SESSIONS_MANAGEMENT_ID, waitUntilNextSessionCompletes$, WaitUntilNextSessionCompletesOptions, + isEsError, } from './search'; export type { diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 2b502bcb89938..ff76f550368f3 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1132,6 +1132,13 @@ export interface IDataPluginServices extends Partial { usageCollection?: UsageCollectionStart; } +// Warning: (ae-forgotten-export) The symbol "KibanaServerError" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "IEsErrorAttributes" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "IEsError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type IEsError = KibanaServerError; + // Warning: (ae-missing-release-tag) "IEsSearchRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1738,6 +1745,11 @@ export interface ISearchStartSearchSource { // @public (undocumented) export const isErrorResponse: (response?: IKibanaSearchResponse | undefined) => boolean; +// Warning: (ae-missing-release-tag) "isEsError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function isEsError(e: any): e is IEsError; + // Warning: (ae-forgotten-export) The symbol "SessionsClient" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ISessionsClient" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -1927,7 +1939,6 @@ export interface OptionedValueProp { // // @public (undocumented) export class PainlessError extends EsError { - // Warning: (ae-forgotten-export) The symbol "IEsError" needs to be exported by the entry point index.d.ts constructor(err: IEsError, indexPattern?: IndexPattern); // (undocumented) getErrorMessage(application: ApplicationStart): JSX.Element; @@ -2210,6 +2221,33 @@ export interface RangeFilterParams { to?: number | string; } +// Warning: (ae-missing-release-tag) "Reason" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface Reason { + // (undocumented) + caused_by?: { + type: string; + reason: string; + }; + // (undocumented) + lang?: string; + // (undocumented) + position?: { + offset: number; + start: number; + end: number; + }; + // (undocumented) + reason: string; + // (undocumented) + script?: string; + // (undocumented) + script_stack?: string[]; + // (undocumented) + type: string; +} + // Warning: (ae-missing-release-tag) "RefreshInterval" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -2366,7 +2404,6 @@ export class SearchInterceptor { protected getSerializableOptions(options?: ISearchOptions): Pick; // (undocumented) protected getTimeoutMode(): TimeoutErrorMode; - // Warning: (ae-forgotten-export) The symbol "KibanaServerError" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "AbortError" needs to be exported by the entry point index.d.ts // // (undocumented) @@ -2726,20 +2763,20 @@ export interface WaitUntilNextSessionCompletesOptions { // src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:404:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:404:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:404:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:406:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:407:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:416:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:417:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:418:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:419:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:423:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:424:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:427:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:428:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:431:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:407:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:407:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:407:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:409:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:410:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:419:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:420:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:421:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:422:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:426:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:427:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:430:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:431:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:434:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/public/query/state_sync/connect_to_query_state.ts:34:5 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts // src/plugins/data/public/search/session/session_service.ts:56:5 - (ae-forgotten-export) The symbol "UrlGeneratorStateMapping" needs to be exported by the entry point index.d.ts diff --git a/src/plugins/data/public/search/errors/types.ts b/src/plugins/data/public/search/errors/types.ts index e8760902be636..445293fe47ea3 100644 --- a/src/plugins/data/public/search/errors/types.ts +++ b/src/plugins/data/public/search/errors/types.ts @@ -37,6 +37,7 @@ export interface IEsErrorAttributes { reason: string; root_cause?: Reason[]; failed_shards?: FailedShard[]; + caused_by?: IEsErrorAttributes; } export type IEsError = KibanaServerError; diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx index f9058b48dd1a8..345774684ebf4 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx @@ -52,7 +52,7 @@ import { import { VIS_EVENT_TO_TRIGGER } from '../../../../../../../src/plugins/visualizations/public'; import { WorkspacePanelWrapper } from './workspace_panel_wrapper'; import { DropIllustration } from '../../../assets/drop_illustration'; -import { getOriginalRequestErrorMessage } from '../../error_helper'; +import { getOriginalRequestErrorMessages } from '../../error_helper'; import { getMissingIndexPattern, validateDatasourceAndVisualization } from '../state_helpers'; import { DefaultInspectorAdapters } from '../../../../../../../src/plugins/expressions/common'; @@ -432,7 +432,7 @@ export const InnerVisualizationWrapper = ({ .map(({ longMessage }) => (

{longMessage} @@ -465,7 +465,7 @@ export const InnerVisualizationWrapper = ({ actions={showExtraErrorsAction} body={ <> -

+

{localState.configurationValidationError[0].longMessage}

@@ -507,7 +507,7 @@ export const InnerVisualizationWrapper = ({ } body={ <> -

+

{ - const visibleErrorMessage = getOriginalRequestErrorMessage(error) || errorMessage; + const visibleErrorMessages = getOriginalRequestErrorMessages(error) || [errorMessage]; return ( { setLocalState((prevState: WorkspaceState) => ({ @@ -594,9 +594,13 @@ export const InnerVisualizationWrapper = ({ />

- {localState.expandError ? ( -

{visibleErrorMessage}

- ) : null} + {localState.expandError + ? visibleErrorMessages.map((visibleErrorMessage) => ( +

+ {visibleErrorMessage} +

+ )) + : null} } iconColor="danger" diff --git a/x-pack/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx b/x-pack/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx index c749ded2af31e..f4d0c85ecbbce 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx @@ -17,7 +17,7 @@ import { import { ExecutionContextSearch } from 'src/plugins/data/public'; import { DefaultInspectorAdapters, RenderMode } from 'src/plugins/expressions'; import classNames from 'classnames'; -import { getOriginalRequestErrorMessage } from '../error_helper'; +import { getOriginalRequestErrorMessages } from '../error_helper'; import { ErrorMessage } from '../types'; export interface ExpressionWrapperProps { @@ -130,9 +130,9 @@ export function ExpressionWrapper({ - - {getOriginalRequestErrorMessage(error) || errorMessage} - + {(getOriginalRequestErrorMessages(error) || [errorMessage]).map((message) => ( + {message} + ))}
diff --git a/x-pack/plugins/lens/public/editor_frame_service/error_helper.test.ts b/x-pack/plugins/lens/public/editor_frame_service/error_helper.test.ts new file mode 100644 index 0000000000000..41974149b9c03 --- /dev/null +++ b/x-pack/plugins/lens/public/editor_frame_service/error_helper.test.ts @@ -0,0 +1,179 @@ +/* + * 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 { getOriginalRequestErrorMessages } from './error_helper'; + +const runtimeFieldError = { + stack: 'Error: EsError\n...', + message: '[lens_merge_tables] > [esaggs] > EsError', + name: 'Error', + original: { + name: 'Error', + message: 'Something', + err: { + message: 'status_exception', + statusCode: 400, + attributes: { + type: 'status_exception', + reason: 'error while executing search', + caused_by: { + type: 'search_phase_execution_exception', + reason: 'all shards failed', + phase: 'query', + grouped: true, + failed_shards: [ + { + shard: 0, + index: 'indexpattern_source', + node: 'jtqB1-UhQluyjeXIpQFqAA', + reason: { + type: 'script_exception', + reason: 'runtime error', + script_stack: [ + 'java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)', + 'java.base/java.lang.Integer.parseInt(Integer.java:652)', + 'java.base/java.lang.Integer.parseInt(Integer.java:770)', + "emit(Integer.parseInt('hello'))", + ' ^---- HERE', + ], + script: "emit(Integer.parseInt('hello'))", + lang: 'painless', + position: { offset: 12, start: 0, end: 31 }, + caused_by: { type: 'number_format_exception', reason: 'For input string: "hello"' }, + }, + }, + ], + }, + }, + }, + attributes: { + type: 'status_exception', + reason: 'error while executing search', + caused_by: { + type: 'search_phase_execution_exception', + reason: 'all shards failed', + phase: 'query', + grouped: true, + failed_shards: [ + { + shard: 0, + index: 'indexpattern_source', + node: 'jtqB1-UhQluyjeXIpQFqAA', + reason: { + type: 'script_exception', + reason: 'runtime error', + script_stack: [ + 'java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)', + 'java.base/java.lang.Integer.parseInt(Integer.java:652)', + 'java.base/java.lang.Integer.parseInt(Integer.java:770)', + "emit(Integer.parseInt('hello'))", + ' ^---- HERE', + ], + script: "emit(Integer.parseInt('hello'))", + lang: 'painless', + position: { offset: 12, start: 0, end: 31 }, + caused_by: { type: 'number_format_exception', reason: 'For input string: "hello"' }, + }, + }, + ], + }, + }, + }, +}; + +const scriptedFieldError = { + stack: 'Error: EsError\n...', + message: '[lens_merge_tables] > [esaggs] > EsError', + name: 'Error', + original: { + name: 'Error', + message: 'Some description', + err: { + message: 'status_exception', + statusCode: 500, + attributes: { + type: 'status_exception', + reason: 'error while executing search', + caused_by: { + type: 'search_phase_execution_exception', + reason: 'all shards failed', + phase: 'query', + grouped: true, + failed_shards: [ + { + shard: 0, + index: 'indexpattern_source', + node: 'jtqB1-UhQluyjeXIpQFqAA', + reason: { + type: 'aggregation_execution_exception', + reason: 'Unsupported script value [hello], expected a number, date, or boolean', + }, + }, + ], + }, + }, + }, + attributes: { + type: 'status_exception', + reason: 'error while executing search', + caused_by: { + type: 'search_phase_execution_exception', + reason: 'all shards failed', + phase: 'query', + grouped: true, + failed_shards: [ + { + shard: 0, + index: 'indexpattern_source', + node: 'jtqB1-UhQluyjeXIpQFqAA', + reason: { + type: 'aggregation_execution_exception', + reason: 'Unsupported script value [hello], expected a number, date, or boolean', + }, + }, + ], + }, + }, + }, +}; + +// EsAggs will report an internal error when user attempts to use a runtime field on an indexpattern he has no access to +const indexpatternAccessError = { + stack: "TypeError: Cannot read property 'values' of undefined\n", + message: "[lens_merge_tables] > [esaggs] > Cannot read property 'values' of undefined", + name: 'TypeError', + original: { + message: "[lens_merge_tables] > [esaggs] > Cannot read property 'values' of undefined", + stack: "[lens_merge_tables] > [esaggs] > Cannot read property 'values' of undefined", + }, +}; + +describe('lens_error_helpers', () => { + describe('getOriginalRequestErrorMessages', () => { + it('should report no errors if not parsable', () => { + expect(getOriginalRequestErrorMessages(null)).toEqual([]); + }); + + it('should report an error for a runtime field error', () => { + expect(getOriginalRequestErrorMessages(runtimeFieldError)).toEqual([ + 'Request error: number_format_exception, For input string: "hello" in "emit(Integer.parseInt(\'hello\'))" (Painless script)', + ]); + }); + + it('should report an error for a scripted field error', () => { + expect(getOriginalRequestErrorMessages(scriptedFieldError)).toEqual([ + 'Request error: aggregation_execution_exception, Unsupported script value [hello], expected a number, date, or boolean in Painless script', + ]); + }); + + it('should report the original es aggs error for runtime fields for indexpattern not accessible', () => { + expect(getOriginalRequestErrorMessages(indexpatternAccessError as Error)).toEqual([ + indexpatternAccessError.message, + ]); + }); + }); +}); diff --git a/x-pack/plugins/lens/public/editor_frame_service/error_helper.ts b/x-pack/plugins/lens/public/editor_frame_service/error_helper.ts index 67ebd6355de41..42470e5cb6162 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/error_helper.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/error_helper.ts @@ -6,17 +6,26 @@ */ import { i18n } from '@kbn/i18n'; +import { isEqual, uniqWith } from 'lodash'; +import { ExpressionRenderError } from '../../../../../src/plugins/expressions/public'; +import { isEsError } from '../../../../../src/plugins/data/public'; +import type { IEsError, Reason } from '../../../../../src/plugins/data/public'; -import { ExpressionRenderError } from 'src/plugins/expressions/public'; +type ErrorCause = Required['attributes']; -interface ElasticsearchErrorClause { +interface RequestError extends Error { + body?: { attributes?: { error: { caused_by: ErrorCause } } }; +} + +interface ReasonDescription { type: string; reason: string; - caused_by?: ElasticsearchErrorClause; + context?: ReasonDescription; } -interface RequestError extends Error { - body?: { attributes?: { error: ElasticsearchErrorClause } }; +interface EsAggError { + message: string; + stack: string; } const isRequestError = (e: Error | RequestError): e is RequestError => { @@ -26,54 +35,104 @@ const isRequestError = (e: Error | RequestError): e is RequestError => { return false; }; -interface ESError extends Error { - attributes?: { caused_by?: ElasticsearchErrorClause }; -} - -const isEsError = (e: Error | ESError): e is ESError => { - if ('attributes' in e) { - return e.attributes?.caused_by?.caused_by !== undefined; - } - return false; +// what happens for runtime field used on indexpatterns not accessible to the user? +// they will throw on the kibana side as data will be undefined +const isEsAggError = (e: Error | EsAggError): e is EsAggError => { + return 'message' in e && 'stack' in e && !isRequestError(e as Error) && !isEsError(e); }; -function getNestedErrorClause({ +function getNestedErrorClauseWithContext({ type, reason, caused_by: causedBy, -}: ElasticsearchErrorClause): { type: string; reason: string } { + lang, + script, +}: Reason): ReasonDescription[] { + if (!causedBy) { + // scripted fields error has changed with no particular hint about painless in it, + // so it tries to lookup in the message for the script word + if (/script/.test(reason)) { + return [{ type, reason, context: { type: 'Painless script', reason: '' } }]; + } + return [{ type, reason }]; + } + const [payload] = getNestedErrorClause(causedBy); + if (lang === 'painless') { + return [ + { + ...payload, + context: { type: 'Painless script', reason: `"${script}"` || reason }, + }, + ]; + } + return [{ ...payload, context: { type, reason } }]; +} + +function getNestedErrorClause(e: ErrorCause | Reason): ReasonDescription[] { + const { type, reason, caused_by: causedBy } = e; + // Painless scripts errors are nested within the failed_shards property + if ('failed_shards' in e) { + if (e.failed_shards) { + return e.failed_shards.flatMap((shardCause) => + getNestedErrorClauseWithContext(shardCause.reason) + ); + } + } if (causedBy) { return getNestedErrorClause(causedBy); } - return { type, reason }; + return [{ type, reason }]; } -function getErrorSource(e: Error | RequestError | ESError) { +function getErrorSources(e: Error) { if (isRequestError(e)) { - return e.body!.attributes!.error; + return getNestedErrorClause(e.body!.attributes!.error as ErrorCause); } if (isEsError(e)) { - return e.attributes!.caused_by; + if (e.attributes?.reason) { + return getNestedErrorClause(e.attributes); + } + return getNestedErrorClause(e.attributes?.caused_by as ErrorCause); } + return []; } -export function getOriginalRequestErrorMessage(error?: ExpressionRenderError | null) { +export function getOriginalRequestErrorMessages(error?: ExpressionRenderError | null): string[] { + const errorMessages = []; if (error && 'original' in error && error.original) { - const errorSource = getErrorSource(error.original); - if (errorSource == null) { - return; - } - const rootError = getNestedErrorClause(errorSource); - if (rootError.reason && rootError.type) { - return i18n.translate('xpack.lens.editorFrame.expressionFailureMessage', { - defaultMessage: 'Request error: {type}, {reason}', - values: { - reason: rootError.reason, - type: rootError.type, - }, - }); + if (isEsAggError(error.original)) { + errorMessages.push(error.message); + } else { + const rootErrors = uniqWith(getErrorSources(error.original), isEqual); + for (const rootError of rootErrors) { + if (rootError.context) { + errorMessages.push( + i18n.translate('xpack.lens.editorFrame.expressionFailureMessageWithContext', { + defaultMessage: 'Request error: {type}, {reason} in {context}', + values: { + reason: rootError.reason, + type: rootError.type, + context: rootError.context.reason + ? `${rootError.context.reason} (${rootError.context.type})` + : rootError.context.type, + }, + }) + ); + } else { + errorMessages.push( + i18n.translate('xpack.lens.editorFrame.expressionFailureMessage', { + defaultMessage: 'Request error: {type}, {reason}', + values: { + reason: rootError.reason, + type: rootError.type, + }, + }) + ); + } + } } } + return errorMessages; } export function getMissingVisualizationTypeError() { From 51f737f884a7af1d4c02a7281c46ae4ed3a68ffd Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Wed, 21 Apr 2021 13:59:55 +0200 Subject: [PATCH 08/18] [7.x] [APM] Add agent central configuration for PHP agent (#97462) (#97780) * [APM] Add agent central configuration for PHP agent * Fix failing test * Fix "Check Types" test * Undo changes to x-pack\plugins\apm\typings\es_schemas\ui\fields\agent.ts * Undo changes to "x-pack\plugins\apm\common\agent_name.ts" * Fix failing test * updates telemetry mappings * updates jest snapshot Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Oliver Gupte Co-authored-by: Sergey Kleyman Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Oliver Gupte --- docs/apm/agent-configuration.asciidoc | 2 +- .../__snapshots__/apm_telemetry.test.ts.snap | 57 ++++++++++++ .../setting_definitions/general_settings.ts | 12 +-- .../setting_definitions/index.test.ts | 10 ++- .../apm/server/lib/apm_telemetry/schema.ts | 2 + .../apm/typings/es_schemas/ui/fields/agent.ts | 3 +- .../schema/xpack_plugins.json | 87 +++++++++++++++++++ 7 files changed, 164 insertions(+), 9 deletions(-) diff --git a/docs/apm/agent-configuration.asciidoc b/docs/apm/agent-configuration.asciidoc index 86b61ad2c6bdc..0bd52621ee699 100644 --- a/docs/apm/agent-configuration.asciidoc +++ b/docs/apm/agent-configuration.asciidoc @@ -46,7 +46,7 @@ Go Agent:: {apm-go-ref}/configuration.html[Configuration reference] Java Agent:: {apm-java-ref}/configuration.html[Configuration reference] .NET Agent:: {apm-dotnet-ref}/configuration.html[Configuration reference] Node.js Agent:: {apm-node-ref}/configuration.html[Configuration reference] -PHP Agent:: _Not yet supported_ +PHP Agent:: {apm-php-ref}/configuration.html[Configuration reference] Python Agent:: {apm-py-ref}/configuration.html[Configuration reference] Ruby Agent:: {apm-ruby-ref}/configuration.html[Configuration reference] Real User Monitoring (RUM) Agent:: {apm-rum-ref}/configuration.html[Configuration reference] diff --git a/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap b/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap index 14343bd8d52c4..d7fc8e6442f12 100644 --- a/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap +++ b/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap @@ -28,6 +28,9 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the "nodejs": { "type": "long" }, + "php": { + "type": "long" + }, "python": { "type": "long" }, @@ -344,6 +347,60 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the } } }, + "php": { + "properties": { + "agent": { + "properties": { + "version": { + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "name": { + "type": "keyword" + }, + "version": { + "type": "keyword" + }, + "composite": { + "type": "keyword" + } + } + }, + "language": { + "properties": { + "name": { + "type": "keyword" + }, + "version": { + "type": "keyword" + }, + "composite": { + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "name": { + "type": "keyword" + }, + "version": { + "type": "keyword" + }, + "composite": { + "type": "keyword" + } + } + } + } + } + } + }, "python": { "properties": { "agent": { diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts index 1e18fe663ef20..0e565e1d88030 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts @@ -26,7 +26,7 @@ export const generalSettings: RawSettingDefinition[] = [ 'The maximum total compressed size of the request body which is sent to the APM Server intake api via a chunked encoding (HTTP streaming).\nNote that a small overshoot is possible.\n\nAllowed byte units are `b`, `kb` and `mb`. `1kb` is equal to `1024b`.', } ), - excludeAgents: ['js-base', 'rum-js', 'dotnet', 'go', 'nodejs'], + excludeAgents: ['js-base', 'rum-js', 'dotnet', 'go', 'nodejs', 'php'], }, // API Request Time @@ -44,7 +44,7 @@ export const generalSettings: RawSettingDefinition[] = [ "Maximum time to keep an HTTP request to the APM Server open for.\n\nNOTE: This value has to be lower than the APM Server's `read_timeout` setting.", } ), - excludeAgents: ['js-base', 'rum-js', 'dotnet', 'go', 'nodejs'], + excludeAgents: ['js-base', 'rum-js', 'dotnet', 'go', 'nodejs', 'php'], }, // Capture body @@ -69,7 +69,7 @@ export const generalSettings: RawSettingDefinition[] = [ { text: 'transactions', value: 'transactions' }, { text: 'all', value: 'all' }, ], - excludeAgents: ['js-base', 'rum-js'], + excludeAgents: ['js-base', 'rum-js', 'php'], }, // Capture headers @@ -87,7 +87,7 @@ export const generalSettings: RawSettingDefinition[] = [ 'If set to `true`, the agent will capture HTTP request and response headers (including cookies), as well as message headers/properties when using messaging frameworks (like Kafka).\n\nNOTE: Setting this to `false` reduces network bandwidth, disk space and object allocations.', } ), - excludeAgents: ['js-base', 'rum-js', 'nodejs'], + excludeAgents: ['js-base', 'rum-js', 'nodejs', 'php'], }, // LOG_LEVEL @@ -111,7 +111,7 @@ export const generalSettings: RawSettingDefinition[] = [ { text: 'critical', value: 'critical' }, { text: 'off', value: 'off' }, ], - includeAgents: ['dotnet', 'ruby', 'java', 'python', 'nodejs', 'go'], + includeAgents: ['dotnet', 'ruby', 'java', 'python', 'nodejs', 'go', 'php'], }, // Recording @@ -163,7 +163,7 @@ export const generalSettings: RawSettingDefinition[] = [ 'In its default settings, the APM agent will collect a stack trace with every recorded span.\nWhile this is very helpful to find the exact place in your code that causes the span, collecting this stack trace does have some overhead. \nWhen setting this option to a negative value, like `-1ms`, stack traces will be collected for all spans. Setting it to a positive value, e.g. `5ms`, will limit stack trace collection to spans with durations equal to or longer than the given value, e.g. 5 milliseconds.\n\nTo disable stack trace collection for spans completely, set the value to `0ms`.', } ), - excludeAgents: ['js-base', 'rum-js', 'nodejs'], + excludeAgents: ['js-base', 'rum-js', 'nodejs', 'php'], }, // STACK_TRACE_LIMIT diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts index a4560eb2ae17d..0ffa21cbd4a4d 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/index.test.ts @@ -157,9 +157,17 @@ describe('filterByAgent', () => { ]); }); + it('php', () => { + expect(getSettingKeysForAgent('php')).toEqual([ + 'log_level', + 'recording', + 'transaction_max_spans', + 'transaction_sample_rate', + ]); + }); + it('"All" services (no agent name)', () => { expect(getSettingKeysForAgent(undefined)).toEqual([ - 'capture_body', 'transaction_max_spans', 'transaction_sample_rate', ]); diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/schema.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/schema.ts index 565e437504ee5..0b1bc3d50d4c1 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/schema.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/schema.ts @@ -78,6 +78,7 @@ const apmPerAgentSchema: Pick< java: long, 'js-base': long, nodejs: long, + php: long, python: long, ruby: long, 'rum-js': long, @@ -99,6 +100,7 @@ const apmPerAgentSchema: Pick< java: agentSchema, 'js-base': agentSchema, nodejs: agentSchema, + php: agentSchema, python: agentSchema, ruby: agentSchema, 'rum-js': agentSchema, diff --git a/x-pack/plugins/apm/typings/es_schemas/ui/fields/agent.ts b/x-pack/plugins/apm/typings/es_schemas/ui/fields/agent.ts index 29f11e638f195..6bc18ed8b1575 100644 --- a/x-pack/plugins/apm/typings/es_schemas/ui/fields/agent.ts +++ b/x-pack/plugins/apm/typings/es_schemas/ui/fields/agent.ts @@ -13,7 +13,8 @@ export type ElasticAgentName = | 'nodejs' | 'python' | 'dotnet' - | 'ruby'; + | 'ruby' + | 'php'; export type OpenTelemetryAgentName = | 'otlp' diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 7ae77b1148e1c..a6bbf076a5b04 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -325,6 +325,9 @@ "nodejs": { "type": "long" }, + "php": { + "type": "long" + }, "python": { "type": "long" }, @@ -791,6 +794,90 @@ } } }, + "php": { + "properties": { + "agent": { + "properties": { + "version": { + "type": "array", + "items": { + "type": "keyword" + } + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "name": { + "type": "array", + "items": { + "type": "keyword" + } + }, + "version": { + "type": "array", + "items": { + "type": "keyword" + } + }, + "composite": { + "type": "array", + "items": { + "type": "keyword" + } + } + } + }, + "language": { + "properties": { + "name": { + "type": "array", + "items": { + "type": "keyword" + } + }, + "version": { + "type": "array", + "items": { + "type": "keyword" + } + }, + "composite": { + "type": "array", + "items": { + "type": "keyword" + } + } + } + }, + "runtime": { + "properties": { + "name": { + "type": "array", + "items": { + "type": "keyword" + } + }, + "version": { + "type": "array", + "items": { + "type": "keyword" + } + }, + "composite": { + "type": "array", + "items": { + "type": "keyword" + } + } + } + } + } + } + } + }, "python": { "properties": { "agent": { From c90b7ed62f4adb8c22f7932848f3be27b5363e71 Mon Sep 17 00:00:00 2001 From: Marta Bondyra Date: Wed, 21 Apr 2021 14:07:19 +0200 Subject: [PATCH 09/18] [Lens] transfer custom labels when swapping (#97612) (#97794) * [Lens] transfer custom labels when swapping * always to default when incompatible Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../droppable/on_drop_handler.ts | 3 + .../operations/layer_helpers.test.ts | 192 ++++++++++++------ .../operations/layer_helpers.ts | 36 ++-- 3 files changed, 153 insertions(+), 78 deletions(-) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/on_drop_handler.ts b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/on_drop_handler.ts index 17b5cbc661ca3..f0ad797a81b9f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/on_drop_handler.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/on_drop_handler.ts @@ -238,6 +238,7 @@ function onMoveIncompatible( field: sourceField, visualizationGroups: dimensionGroups, targetGroup: groupId, + shouldResetLabel: true, }); trackUiEvent('drop_onto_dimension'); @@ -289,6 +290,7 @@ function onSwapIncompatible({ op: newOperationForSource, field: sourceField, visualizationGroups: dimensionGroups, + shouldResetLabel: true, }), columnId: droppedItem.columnId, indexPattern, @@ -296,6 +298,7 @@ function onSwapIncompatible({ field: targetField, visualizationGroups: dimensionGroups, targetGroup: droppedItem.groupId, + shouldResetLabel: true, }); trackUiEvent('drop_onto_dimension'); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts index d3ca70c086cb5..c506e800d6d01 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts @@ -538,6 +538,41 @@ describe('state_helpers', () => { ); }); }); + + it('should not carry over a label if shouldResetLabel is set', () => { + expect( + insertNewColumn({ + layer: { + indexPatternId: '1', + columnOrder: ['col1'], + columns: { + col1: { + label: 'Date histogram of timestamp', + dataType: 'date', + isBucketed: true, + + // Private + operationType: 'date_histogram', + sourceField: 'timestamp', + params: { + interval: 'h', + }, + }, + }, + }, + columnId: 'col2', + indexPattern, + op: 'terms', + field: indexPattern.fields[2], + visualizationGroups: [], + shouldResetLabel: true, + }).columns.col2 + ).toEqual( + expect.objectContaining({ + label: 'Top values of bytes', + }) + ); + }); }); describe('replaceColumn', () => { @@ -779,76 +814,109 @@ describe('state_helpers', () => { ); }); - it('should carry over label on field switch when customLabel flag is set', () => { - expect( - replaceColumn({ - layer: { - indexPatternId: '1', - columnOrder: ['col1'], - columns: { - col1: { - label: 'My custom label', - customLabel: true, - dataType: 'date', - isBucketed: true, - - // Private - operationType: 'date_histogram', - sourceField: 'timestamp', - params: { - interval: 'h', + describe('labels', () => { + it('should carry over label on field switch when customLabel flag on previousColumn is set', () => { + expect( + replaceColumn({ + layer: { + indexPatternId: '1', + columnOrder: ['col1'], + columns: { + col1: { + label: 'My custom label', + customLabel: true, + dataType: 'date', + isBucketed: true, + + // Private + operationType: 'date_histogram', + sourceField: 'timestamp', + params: { + interval: 'h', + }, }, }, }, - }, - indexPattern, - columnId: 'col1', - op: 'date_histogram', - field: indexPattern.fields[1], - visualizationGroups: [], - }).columns.col1 - ).toEqual( - expect.objectContaining({ - label: 'My custom label', - customLabel: true, - }) - ); - }); + indexPattern, + columnId: 'col1', + op: 'date_histogram', + field: indexPattern.fields[1], + visualizationGroups: [], + }).columns.col1 + ).toEqual( + expect.objectContaining({ + label: 'My custom label', + customLabel: true, + }) + ); + }); - it('should carry over label on operation switch when customLabel flag is set', () => { - expect( - replaceColumn({ - layer: { - indexPatternId: '1', - columnOrder: ['col1'], - columns: { - col1: { - label: 'My custom label', - customLabel: true, - dataType: 'date', - isBucketed: true, + it('should carry over label on operation switch when customLabel flag on previousColumn is set', () => { + expect( + replaceColumn({ + layer: { + indexPatternId: '1', + columnOrder: ['col1'], + columns: { + col1: { + label: 'My custom label', + customLabel: true, + dataType: 'date', + isBucketed: true, + + // Private + operationType: 'date_histogram', + sourceField: 'timestamp', + params: { + interval: 'h', + }, + }, + }, + }, + indexPattern, + columnId: 'col1', + op: 'terms', + field: indexPattern.fields[0], + visualizationGroups: [], + }).columns.col1 + ).toEqual( + expect.objectContaining({ + label: 'My custom label', + customLabel: true, + }) + ); + }); - // Private - operationType: 'date_histogram', - sourceField: 'timestamp', - params: { - interval: 'h', + it('should not carry over a label if shouldResetLabel is set', () => { + expect( + replaceColumn({ + layer: { + indexPatternId: '1', + columnOrder: ['col1', 'col2'], + columns: { + col1: { + label: 'Top values of source', + dataType: 'string', + isBucketed: true, + operationType: 'terms', + sourceField: 'source', + params: { + orderBy: { type: 'alphabetical' }, + orderDirection: 'asc', + size: 5, + }, }, }, }, - }, - indexPattern, - columnId: 'col1', - op: 'terms', - field: indexPattern.fields[0], - visualizationGroups: [], - }).columns.col1 - ).toEqual( - expect.objectContaining({ - label: 'My custom label', - customLabel: true, - }) - ); + indexPattern, + columnId: 'col1', + op: 'average', + field: indexPattern.fields[2], // bytes field + visualizationGroups: [], + shouldResetLabel: true, + }).columns.col1 + ).toEqual(expect.objectContaining({ label: 'Average of bytes' })); + }); }); it('should execute adjustments for other columns', () => { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts index bbe2ca4cd3d61..35f334d5bd743 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts @@ -27,6 +27,7 @@ interface ColumnChange { field?: IndexPatternField; visualizationGroups: VisualizationDimensionGroupConfig[]; targetGroup?: string; + shouldResetLabel?: boolean; } export function insertOrReplaceColumn(args: ColumnChange): IndexPatternLayer { @@ -46,6 +47,7 @@ export function insertNewColumn({ indexPattern, visualizationGroups, targetGroup, + shouldResetLabel, }: ColumnChange): IndexPatternLayer { const operationDefinition = operationDefinitionMap[op]; @@ -208,16 +210,12 @@ export function insertNewColumn({ }, }; } + + const newColumn = operationDefinition.buildColumn({ ...baseOptions, layer, field }); const isBucketed = Boolean(possibleOperation.isBucketed); const addOperationFn = isBucketed ? addBucket : addMetric; return updateDefaultLabels( - addOperationFn( - layer, - operationDefinition.buildColumn({ ...baseOptions, layer, field }), - columnId, - visualizationGroups, - targetGroup - ), + addOperationFn(layer, newColumn, columnId, visualizationGroups, targetGroup), indexPattern ); } @@ -229,6 +227,7 @@ export function replaceColumn({ op, field, visualizationGroups, + shouldResetLabel, }: ColumnChange): IndexPatternLayer { const previousColumn = layer.columns[columnId]; if (!previousColumn) { @@ -366,9 +365,11 @@ export function replaceColumn({ }, }; } - let newColumn = operationDefinition.buildColumn({ ...baseOptions, layer: tempLayer, field }); - newColumn = copyCustomLabel(newColumn, previousColumn); + let newColumn = operationDefinition.buildColumn({ ...baseOptions, layer: tempLayer, field }); + if (!shouldResetLabel) { + newColumn = copyCustomLabel(newColumn, previousColumn); + } const newLayer = { ...tempLayer, columns: { ...tempLayer.columns, [columnId]: newColumn } }; return updateDefaultLabels( { @@ -385,10 +386,10 @@ export function replaceColumn({ previousColumn.sourceField !== field.name ) { // Same operation, new field - const newColumn = copyCustomLabel( - operationDefinition.onFieldChange(previousColumn, field), - previousColumn - ); + let newColumn = operationDefinition.onFieldChange(previousColumn, field); + if (!shouldResetLabel) { + newColumn = copyCustomLabel(newColumn, previousColumn); + } const newLayer = resetIncomplete( { ...layer, columns: { ...layer.columns, [columnId]: newColumn } }, @@ -671,11 +672,14 @@ function applyReferenceTransition({ ); } -function copyCustomLabel(newColumn: IndexPatternColumn, previousColumn: IndexPatternColumn) { +function copyCustomLabel( + newColumn: IndexPatternColumn, + previousOptions: { customLabel?: boolean; label: string } +) { const adjustedColumn = { ...newColumn }; - if (previousColumn.customLabel) { + if (previousOptions.customLabel) { adjustedColumn.customLabel = true; - adjustedColumn.label = previousColumn.label; + adjustedColumn.label = previousOptions.label; } return adjustedColumn; } From 950936eb75ef46b9bc31c0cde84b478f40117c12 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 21 Apr 2021 08:27:46 -0400 Subject: [PATCH 10/18] [Fleet] Update text in Fleet Settings flyout / confirm modals (#97648) (#97715) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove "Global Output" heading from the flyout * Tweak flyout description * Tweak fleet server hosts input description * Tweak ES hosts input description * Tweak modal button * Tweak confirmation modal callout title * Tweak callout when fleet server hosts are modified * Tweak callout when ES hosts are modified * Fix i18n * Remove period from title Co-authored-by: Alejandro Fernández Gómez --- .../settings_flyout/confirm_modal.tsx | 20 +++++++++---------- .../components/settings_flyout/index.tsx | 15 +++----------- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 4 files changed, 13 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/settings_flyout/confirm_modal.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/settings_flyout/confirm_modal.tsx index 8bef32916452f..ae9863e84d605 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/components/settings_flyout/confirm_modal.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/components/settings_flyout/confirm_modal.tsx @@ -113,7 +113,7 @@ export const SettingsConfirmModal = React.memo( title={ } color="warning" @@ -124,13 +124,13 @@ export const SettingsConfirmModal = React.memo(

), @@ -143,13 +143,13 @@ export const SettingsConfirmModal = React.memo(

), @@ -178,7 +178,7 @@ export const SettingsConfirmModal = React.memo( diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/settings_flyout/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/settings_flyout/index.tsx index 30e1aedc3e5a5..f3c353fd75dba 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/components/settings_flyout/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/components/settings_flyout/index.tsx @@ -251,19 +251,10 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => { const body = settings && ( - -

- -

- - outputs, }} @@ -279,7 +270,7 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => { helpText={ = ({ onClose }) => { defaultMessage: 'Elasticsearch hosts', })} helpText={i18n.translate('xpack.fleet.settings.elasticsearchUrlsHelpTect', { - defaultMessage: 'Specify the Elasticsearch URLs where agents will send data.', + defaultMessage: 'Specify the Elasticsearch URLs where agents send data.', })} {...inputs.elasticsearchUrl.formRowProps} > diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 1369b79313093..88bd7cc482a6b 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -8638,7 +8638,6 @@ "xpack.fleet.settings.elasticHostError": "無効なURL", "xpack.fleet.settings.elasticsearchUrlLabel": "Elasticsearch URL", "xpack.fleet.settings.flyoutTitle": "Fleet 設定", - "xpack.fleet.settings.globalOutputTitle": "グローバル出力", "xpack.fleet.settings.invalidYamlFormatErrorMessage": "無効なYAML形式:{reason}", "xpack.fleet.settings.saveButtonLabel": "設定を保存", "xpack.fleet.settings.success.message": "設定が保存されました", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 482924f50f5de..493354bd06ab9 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -8723,7 +8723,6 @@ "xpack.fleet.settings.elasticHostError": "URL 无效", "xpack.fleet.settings.elasticsearchUrlLabel": "Elasticsearch URL", "xpack.fleet.settings.flyoutTitle": "Fleet 设置", - "xpack.fleet.settings.globalOutputTitle": "全局输出", "xpack.fleet.settings.invalidYamlFormatErrorMessage": "YAML 无效:{reason}", "xpack.fleet.settings.saveButtonLabel": "保存设置", "xpack.fleet.settings.success.message": "设置已保存", From 634479ffdb04e9749dae8c132cc8cd54dae7b5a4 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 21 Apr 2021 13:33:15 +0100 Subject: [PATCH 11/18] skip flaky suite (#97403) --- x-pack/test/functional/apps/dashboard/sync_colors.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/dashboard/sync_colors.ts b/x-pack/test/functional/apps/dashboard/sync_colors.ts index 09575c355913e..3a135fb41a58d 100644 --- a/x-pack/test/functional/apps/dashboard/sync_colors.ts +++ b/x-pack/test/functional/apps/dashboard/sync_colors.ts @@ -33,7 +33,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { return colorMapping; } - describe('sync colors', function () { + // FLAKY: https://github.com/elastic/kibana/issues/97403 + describe.skip('sync colors', function () { before(async function () { await esArchiver.loadIfNeeded('logstash_functional'); await esArchiver.loadIfNeeded('lens/basic'); From bdb61c0c3b1200c597d08231e7364d43f7223723 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 21 Apr 2021 08:59:13 -0400 Subject: [PATCH 12/18] [7.x] [Exploratory view] use synthetics and rum indices settings (#97425) (#97734) * [Exploratory view] use synthetics and rum indices settings (#97425) * fix test Co-authored-by: Shahzad Co-authored-by: Shahzad --- .../apm/server/lib/rum_client/has_rum_data.ts | 7 +- .../components/app/section/uptime/index.tsx | 4 +- .../hooks/use_app_index_pattern.tsx | 12 +- .../observability_index_patterns.test.ts | 17 ++- .../utils/observability_index_patterns.ts | 41 +++++-- .../public/context/has_data_context.test.tsx | 111 ++++++++++++++---- .../public/context/has_data_context.tsx | 2 +- .../observability/public/data_handler.test.ts | 14 ++- .../public/pages/home/section.ts | 2 +- .../public/pages/overview/empty_section.ts | 2 +- .../pages/overview/overview.stories.tsx | 46 ++++---- .../typings/fetch_overview_data/index.ts | 12 +- .../utils/observability_index_patterns.ts | 64 ---------- .../uptime/common/runtime_types/common.ts | 1 + x-pack/plugins/uptime/public/apps/plugin.ts | 4 +- .../overview/empty_state/empty_state.test.tsx | 2 + .../public/state/effects/fetch_effect.test.ts | 8 +- x-pack/plugins/uptime/server/lib/lib.ts | 19 +-- .../server/lib/requests/get_index_status.ts | 10 +- .../lib/requests/search/query_context.ts | 4 +- .../apis/uptime/rest/fixtures/doc_count.json | 3 +- .../api_integration/apis/uptime/rest/index.ts | 2 +- .../rest/{doc_count.ts => index_status.ts} | 0 .../tests/csm/has_rum_data.ts | 2 + 24 files changed, 220 insertions(+), 169 deletions(-) delete mode 100644 x-pack/plugins/observability/public/utils/observability_index_patterns.ts rename x-pack/test/api_integration/apis/uptime/rest/{doc_count.ts => index_status.ts} (100%) diff --git a/x-pack/plugins/apm/server/lib/rum_client/has_rum_data.ts b/x-pack/plugins/apm/server/lib/rum_client/has_rum_data.ts index ec96b5225d617..8de2e4e1cca42 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/has_rum_data.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/has_rum_data.ts @@ -49,11 +49,16 @@ export async function hasRumData({ setup }: { setup: Setup & SetupTimeRange }) { const response = await apmEventClient.search(params); return { + indices: setup.indices['apm_oss.transactionIndices']!, hasData: response.hits.total.value > 0, serviceName: response.aggregations?.services?.mostTraffic?.buckets?.[0]?.key, }; } catch (e) { - return { hasData: false, serviceName: undefined }; + return { + hasData: false, + serviceName: undefined, + indices: setup.indices['apm_oss.transactionIndices']!, + }; } } diff --git a/x-pack/plugins/observability/public/components/app/section/uptime/index.tsx b/x-pack/plugins/observability/public/components/app/section/uptime/index.tsx index b81e5b5616d7b..1dbcdeaee800a 100644 --- a/x-pack/plugins/observability/public/components/app/section/uptime/index.tsx +++ b/x-pack/plugins/observability/public/components/app/section/uptime/index.tsx @@ -46,7 +46,7 @@ export function UptimeSection({ bucketSize }: Props) { const { data, status } = useFetcher( () => { if (bucketSize) { - return getDataHandler('uptime')?.fetchData({ + return getDataHandler('synthetics')?.fetchData({ absoluteTime: { start: absoluteStart, end: absoluteEnd }, relativeTime: { start: relativeStart, end: relativeEnd }, bucketSize, @@ -58,7 +58,7 @@ export function UptimeSection({ bucketSize }: Props) { [bucketSize, relativeStart, relativeEnd, forceUpdate] ); - if (!hasData.uptime?.hasData) { + if (!hasData.synthetics?.hasData) { return null; } diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_app_index_pattern.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_app_index_pattern.tsx index 77d0d54ec5a7a..4f13cf6a1f9ca 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_app_index_pattern.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_app_index_pattern.tsx @@ -12,7 +12,7 @@ import { useKibana } from '../../../../../../../../src/plugins/kibana_react/publ import { ObservabilityPublicPluginsStart } from '../../../../plugin'; import { ObservabilityIndexPatterns } from '../utils/observability_index_patterns'; import { getDataHandler } from '../../../../data_handler'; -import { UXHasDataResponse } from '../../../../typings/fetch_overview_data'; +import { HasDataResponse } from '../../../../typings/fetch_overview_data'; export interface IIndexPatternContext { loading: boolean; @@ -48,7 +48,7 @@ export function IndexPatternContextProvider({ children }: ProviderProps) { } = useKibana(); const checkIfAppHasData = async (dataType: AppDataType) => { - const handler = getDataHandler(dataType === 'synthetics' ? 'uptime' : dataType); + const handler = getDataHandler(dataType); return handler?.hasData(); }; @@ -59,17 +59,15 @@ export function IndexPatternContextProvider({ children }: ProviderProps) { if (hasAppData[dataType] === null) { setLoading(true); try { - let hasDataT = await checkIfAppHasData(dataType); + const hasDataResponse = (await checkIfAppHasData(dataType)) as HasDataResponse; - if (dataType === 'ux') { - hasDataT = (hasDataT as UXHasDataResponse).hasData as boolean; - } + const hasDataT = hasDataResponse.hasData; setHasAppData((prevState) => ({ ...prevState, [dataType]: hasDataT })); if (hasDataT || hasAppData?.[dataType]) { const obsvIndexP = new ObservabilityIndexPatterns(data); - const indPattern = await obsvIndexP.getIndexPattern(dataType); + const indPattern = await obsvIndexP.getIndexPattern(dataType, hasDataResponse.indices); setIndexPatterns((prevState) => ({ ...prevState, [dataType]: indPattern })); } diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.test.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.test.ts index f1347e1d21cc3..ade74e7c6744e 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.test.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.test.ts @@ -46,11 +46,13 @@ describe('ObservabilityIndexPatterns', function () { it('should return index pattern for app', async function () { const obsv = new ObservabilityIndexPatterns(data!); - const indexP = await obsv.getIndexPattern('ux'); + const indexP = await obsv.getIndexPattern('ux', 'heartbeat-8*,synthetics-*'); - expect(indexP).toEqual({ title: 'index-*' }); + expect(indexP).toEqual({ id: 'rum_static_index_pattern_id' }); - expect(data?.indexPatterns.get).toHaveBeenCalledWith(indexPatternList.ux); + expect(data?.indexPatterns.get).toHaveBeenCalledWith( + 'rum_static_index_pattern_id_heartbeat_8_synthetics_' + ); expect(data?.indexPatterns.get).toHaveBeenCalledTimes(1); }); @@ -59,18 +61,21 @@ describe('ObservabilityIndexPatterns', function () { throw new SavedObjectNotFound('index_pattern'); }); + data!.indexPatterns.createAndSave = jest.fn().mockReturnValue({ id: indexPatternList.ux }); + const obsv = new ObservabilityIndexPatterns(data!); - const indexP = await obsv.getIndexPattern('ux'); + const indexP = await obsv.getIndexPattern('ux', 'trace-*,apm-*'); expect(indexP).toEqual({ id: indexPatternList.ux }); expect(data?.indexPatterns.createAndSave).toHaveBeenCalledWith({ fieldFormats, - id: 'rum_static_index_pattern_id', + id: 'rum_static_index_pattern_id_trace_apm_', timeFieldName: '@timestamp', - title: '(rum-data-view)*,apm-*', + title: '(rum-data-view)*,trace-*,apm-*', }); + expect(data?.indexPatterns.createAndSave).toHaveBeenCalledTimes(1); }); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.ts index b890df69d9936..c265bad56e864 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/observability_index_patterns.ts @@ -38,11 +38,22 @@ export const indexPatternList: Record = { }; const appToPatternMap: Record = { - synthetics: '(synthetics-data-view)*,heartbeat-*,synthetics-*', + synthetics: '(synthetics-data-view)*', apm: 'apm-*', - ux: '(rum-data-view)*,apm-*', - infra_logs: 'logs-*,filebeat-*', - infra_metrics: 'metrics-*,metricbeat-*', + ux: '(rum-data-view)*', + infra_logs: '', + infra_metrics: '', +}; + +const getAppIndicesWithPattern = (app: AppDataType, indices: string) => { + return `${appToPatternMap[app]},${indices}`; +}; + +const getAppIndexPatternId = (app: AppDataType, indices: string) => { + // Replace characters / ? , " < > | * with _ + const postfix = indices.replace(/[^A-Z0-9]+/gi, '_').toLowerCase(); + + return `${indexPatternList[app]}_${postfix}`; }; export function isParamsSame(param1: IFieldFormat['_params'], param2: FieldFormatParams) { @@ -65,16 +76,16 @@ export class ObservabilityIndexPatterns { this.data = data; } - async createIndexPattern(app: AppDataType) { + async createIndexPattern(app: AppDataType, indices: string) { if (!this.data) { throw new Error('data is not defined'); } - const pattern = appToPatternMap[app]; + const appIndicesPattern = getAppIndicesWithPattern(app, indices); return await this.data.indexPatterns.createAndSave({ - title: pattern, - id: indexPatternList[app], + title: appIndicesPattern, + id: getAppIndexPatternId(app, indices), timeFieldName: '@timestamp', fieldFormats: this.getFieldFormats(app), }); @@ -108,19 +119,27 @@ export class ObservabilityIndexPatterns { return fieldFormatMap; } - async getIndexPattern(app: AppDataType): Promise { + async getIndexPattern(app: AppDataType, indices: string): Promise { if (!this.data) { throw new Error('data is not defined'); } try { - const indexPattern = await this.data?.indexPatterns.get(indexPatternList[app]); + const indexPatternId = getAppIndexPatternId(app, indices); + const indexPatternTitle = getAppIndicesWithPattern(app, indices); + // we will get index pattern by id + const indexPattern = await this.data?.indexPatterns.get(indexPatternId); + + // and make sure title matches, otherwise, we will need to create it + if (indexPattern.title !== indexPatternTitle) { + return await this.createIndexPattern(app, indices); + } // this is intentional a non blocking call, so no await clause this.validateFieldFormats(app, indexPattern); return indexPattern; } catch (e: unknown) { if (e instanceof SavedObjectNotFound) { - return await this.createIndexPattern(app || 'apm'); + return await this.createIndexPattern(app, indices); } } } diff --git a/x-pack/plugins/observability/public/context/has_data_context.test.tsx b/x-pack/plugins/observability/public/context/has_data_context.test.tsx index 01655c0d7b2d7..b5a0806306461 100644 --- a/x-pack/plugins/observability/public/context/has_data_context.test.tsx +++ b/x-pack/plugins/observability/public/context/has_data_context.test.tsx @@ -36,7 +36,7 @@ function unregisterAll() { unregisterDataHandler({ appName: 'apm' }); unregisterDataHandler({ appName: 'infra_logs' }); unregisterDataHandler({ appName: 'infra_metrics' }); - unregisterDataHandler({ appName: 'uptime' }); + unregisterDataHandler({ appName: 'synthetics' }); unregisterDataHandler({ appName: 'ux' }); } @@ -88,7 +88,7 @@ describe('HasDataContextProvider', () => { expect(result.current).toEqual({ hasData: { apm: { hasData: undefined, status: 'success' }, - uptime: { hasData: undefined, status: 'success' }, + synthetics: { hasData: undefined, status: 'success' }, infra_logs: { hasData: undefined, status: 'success' }, infra_metrics: { hasData: undefined, status: 'success' }, ux: { hasData: undefined, status: 'success' }, @@ -108,8 +108,14 @@ describe('HasDataContextProvider', () => { { appName: 'apm', hasData: async () => false }, { appName: 'infra_logs', hasData: async () => false }, { appName: 'infra_metrics', hasData: async () => false }, - { appName: 'uptime', hasData: async () => false }, - { appName: 'ux', hasData: async () => ({ hasData: false, serviceName: undefined }) }, + { + appName: 'synthetics', + hasData: async () => ({ hasData: false, indices: 'heartbeat-*, synthetics-*' }), + }, + { + appName: 'ux', + hasData: async () => ({ hasData: false, serviceName: undefined, indices: 'apm-*' }), + }, ]); }); @@ -130,10 +136,19 @@ describe('HasDataContextProvider', () => { expect(result.current).toEqual({ hasData: { apm: { hasData: false, status: 'success' }, - uptime: { hasData: false, status: 'success' }, + synthetics: { + hasData: { + hasData: false, + indices: 'heartbeat-*, synthetics-*', + }, + status: 'success', + }, infra_logs: { hasData: false, status: 'success' }, infra_metrics: { hasData: false, status: 'success' }, - ux: { hasData: { hasData: false, serviceName: undefined }, status: 'success' }, + ux: { + hasData: { hasData: false, serviceName: undefined, indices: 'apm-*' }, + status: 'success', + }, alert: { hasData: [], status: 'success' }, }, hasAnyData: false, @@ -150,8 +165,14 @@ describe('HasDataContextProvider', () => { { appName: 'apm', hasData: async () => true }, { appName: 'infra_logs', hasData: async () => false }, { appName: 'infra_metrics', hasData: async () => false }, - { appName: 'uptime', hasData: async () => false }, - { appName: 'ux', hasData: async () => ({ hasData: false, serviceName: undefined }) }, + { + appName: 'synthetics', + hasData: async () => ({ hasData: false, indices: 'heartbeat-*, synthetics-*' }), + }, + { + appName: 'ux', + hasData: async () => ({ hasData: false, serviceName: undefined, indices: 'apm-*' }), + }, ]); }); @@ -172,10 +193,19 @@ describe('HasDataContextProvider', () => { expect(result.current).toEqual({ hasData: { apm: { hasData: true, status: 'success' }, - uptime: { hasData: false, status: 'success' }, + synthetics: { + hasData: { + hasData: false, + indices: 'heartbeat-*, synthetics-*', + }, + status: 'success', + }, infra_logs: { hasData: false, status: 'success' }, infra_metrics: { hasData: false, status: 'success' }, - ux: { hasData: { hasData: false, serviceName: undefined }, status: 'success' }, + ux: { + hasData: { hasData: false, serviceName: undefined, indices: 'apm-*' }, + status: 'success', + }, alert: { hasData: [], status: 'success' }, }, hasAnyData: true, @@ -192,8 +222,14 @@ describe('HasDataContextProvider', () => { { appName: 'apm', hasData: async () => true }, { appName: 'infra_logs', hasData: async () => true }, { appName: 'infra_metrics', hasData: async () => true }, - { appName: 'uptime', hasData: async () => true }, - { appName: 'ux', hasData: async () => ({ hasData: true, serviceName: 'ux' }) }, + { + appName: 'synthetics', + hasData: async () => ({ hasData: true, indices: 'heartbeat-*, synthetics-*' }), + }, + { + appName: 'ux', + hasData: async () => ({ hasData: true, serviceName: 'ux', indices: 'apm-*' }), + }, ]); }); @@ -213,11 +249,23 @@ describe('HasDataContextProvider', () => { expect(result.current).toEqual({ hasData: { - apm: { hasData: true, status: 'success' }, - uptime: { hasData: true, status: 'success' }, + apm: { + hasData: true, + status: 'success', + }, + synthetics: { + hasData: { + hasData: true, + indices: 'heartbeat-*, synthetics-*', + }, + status: 'success', + }, infra_logs: { hasData: true, status: 'success' }, infra_metrics: { hasData: true, status: 'success' }, - ux: { hasData: { hasData: true, serviceName: 'ux' }, status: 'success' }, + ux: { + hasData: { hasData: true, serviceName: 'ux', indices: 'apm-*' }, + status: 'success', + }, alert: { hasData: [], status: 'success' }, }, hasAnyData: true, @@ -253,7 +301,7 @@ describe('HasDataContextProvider', () => { expect(result.current).toEqual({ hasData: { apm: { hasData: true, status: 'success' }, - uptime: { hasData: undefined, status: 'success' }, + synthetics: { hasData: undefined, status: 'success' }, infra_logs: { hasData: undefined, status: 'success' }, infra_metrics: { hasData: undefined, status: 'success' }, ux: { hasData: undefined, status: 'success' }, @@ -291,7 +339,7 @@ describe('HasDataContextProvider', () => { expect(result.current).toEqual({ hasData: { apm: { hasData: false, status: 'success' }, - uptime: { hasData: undefined, status: 'success' }, + synthetics: { hasData: undefined, status: 'success' }, infra_logs: { hasData: undefined, status: 'success' }, infra_metrics: { hasData: undefined, status: 'success' }, ux: { hasData: undefined, status: 'success' }, @@ -317,8 +365,14 @@ describe('HasDataContextProvider', () => { }, { appName: 'infra_logs', hasData: async () => true }, { appName: 'infra_metrics', hasData: async () => true }, - { appName: 'uptime', hasData: async () => true }, - { appName: 'ux', hasData: async () => ({ hasData: true, serviceName: 'ux' }) }, + { + appName: 'synthetics', + hasData: async () => ({ hasData: true, indices: 'heartbeat-*, synthetics-*' }), + }, + { + appName: 'ux', + hasData: async () => ({ hasData: true, serviceName: 'ux', indices: 'apm-*' }), + }, ]); }); @@ -339,10 +393,19 @@ describe('HasDataContextProvider', () => { expect(result.current).toEqual({ hasData: { apm: { hasData: undefined, status: 'failure' }, - uptime: { hasData: true, status: 'success' }, + synthetics: { + hasData: { + hasData: true, + indices: 'heartbeat-*, synthetics-*', + }, + status: 'success', + }, infra_logs: { hasData: true, status: 'success' }, infra_metrics: { hasData: true, status: 'success' }, - ux: { hasData: { hasData: true, serviceName: 'ux' }, status: 'success' }, + ux: { + hasData: { hasData: true, serviceName: 'ux', indices: 'apm-*' }, + status: 'success', + }, alert: { hasData: [], status: 'success' }, }, hasAnyData: true, @@ -375,7 +438,7 @@ describe('HasDataContextProvider', () => { }, }, { - appName: 'uptime', + appName: 'synthetics', hasData: async () => { throw new Error('BOOMMMMM'); }, @@ -406,7 +469,7 @@ describe('HasDataContextProvider', () => { expect(result.current).toEqual({ hasData: { apm: { hasData: undefined, status: 'failure' }, - uptime: { hasData: undefined, status: 'failure' }, + synthetics: { hasData: undefined, status: 'failure' }, infra_logs: { hasData: undefined, status: 'failure' }, infra_metrics: { hasData: undefined, status: 'failure' }, ux: { hasData: undefined, status: 'failure' }, @@ -454,7 +517,7 @@ describe('HasDataContextProvider', () => { expect(result.current).toEqual({ hasData: { apm: { hasData: undefined, status: 'success' }, - uptime: { hasData: undefined, status: 'success' }, + synthetics: { hasData: undefined, status: 'success' }, infra_logs: { hasData: undefined, status: 'success' }, infra_metrics: { hasData: undefined, status: 'success' }, ux: { hasData: undefined, status: 'success' }, diff --git a/x-pack/plugins/observability/public/context/has_data_context.tsx b/x-pack/plugins/observability/public/context/has_data_context.tsx index a2628d37828a4..0b8b2b5d80a17 100644 --- a/x-pack/plugins/observability/public/context/has_data_context.tsx +++ b/x-pack/plugins/observability/public/context/has_data_context.tsx @@ -33,7 +33,7 @@ export interface HasDataContextValue { export const HasDataContext = createContext({} as HasDataContextValue); -const apps: DataContextApps[] = ['apm', 'uptime', 'infra_logs', 'infra_metrics', 'ux', 'alert']; +const apps: DataContextApps[] = ['apm', 'synthetics', 'infra_logs', 'infra_metrics', 'ux', 'alert']; export function HasDataContextProvider({ children }: { children: React.ReactNode }) { const { core } = usePluginContext(); diff --git a/x-pack/plugins/observability/public/data_handler.test.ts b/x-pack/plugins/observability/public/data_handler.test.ts index bba2083aceb80..385a0c7d40c20 100644 --- a/x-pack/plugins/observability/public/data_handler.test.ts +++ b/x-pack/plugins/observability/public/data_handler.test.ts @@ -179,7 +179,7 @@ describe('registerDataHandler', () => { }); describe('Uptime', () => { registerDataHandler({ - appName: 'uptime', + appName: 'synthetics', fetchData: async () => { return { title: 'uptime', @@ -213,17 +213,17 @@ describe('registerDataHandler', () => { }, }; }, - hasData: async () => true, + hasData: async () => ({ hasData: true, indices: 'heartbeat-*,synthetics-*' }), }); it('registered data handler', () => { - const dataHandler = getDataHandler('uptime'); + const dataHandler = getDataHandler('synthetics'); expect(dataHandler?.fetchData).toBeDefined(); expect(dataHandler?.hasData).toBeDefined(); }); it('returns data when fetchData is called', async () => { - const dataHandler = getDataHandler('uptime'); + const dataHandler = getDataHandler('synthetics'); const response = await dataHandler?.fetchData(params); expect(response).toEqual({ title: 'uptime', @@ -284,7 +284,11 @@ describe('registerDataHandler', () => { }, }; }, - hasData: async () => ({ hasData: true, serviceName: 'elastic-co-frontend' }), + hasData: async () => ({ + hasData: true, + serviceName: 'elastic-co-frontend', + indices: 'apm-*', + }), }); it('registered data handler', () => { diff --git a/x-pack/plugins/observability/public/pages/home/section.ts b/x-pack/plugins/observability/public/pages/home/section.ts index e374f1d3cc2a9..31c70823127e0 100644 --- a/x-pack/plugins/observability/public/pages/home/section.ts +++ b/x-pack/plugins/observability/public/pages/home/section.ts @@ -46,7 +46,7 @@ export const appsSection: ISection[] = [ href: 'https://www.elastic.co', }, { - id: 'uptime', + id: 'synthetics', title: i18n.translate('xpack.observability.section.apps.uptime.title', { defaultMessage: 'Uptime', }), diff --git a/x-pack/plugins/observability/public/pages/overview/empty_section.ts b/x-pack/plugins/observability/public/pages/overview/empty_section.ts index 077978b7ad0e7..40b1157b29e35 100644 --- a/x-pack/plugins/observability/public/pages/overview/empty_section.ts +++ b/x-pack/plugins/observability/public/pages/overview/empty_section.ts @@ -57,7 +57,7 @@ export const getEmptySections = ({ core }: { core: CoreStart }): ISection[] => { href: core.http.basePath.prepend('/app/home#/tutorial_directory/metrics'), }, { - id: 'uptime', + id: 'synthetics', title: i18n.translate('xpack.observability.emptySection.apps.uptime.title', { defaultMessage: 'Uptime', }), diff --git a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx index 68c39a888692b..559aa8d5884a9 100644 --- a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx +++ b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx @@ -29,7 +29,7 @@ function unregisterAll() { unregisterDataHandler({ appName: 'apm' }); unregisterDataHandler({ appName: 'infra_logs' }); unregisterDataHandler({ appName: 'infra_metrics' }); - unregisterDataHandler({ appName: 'uptime' }); + unregisterDataHandler({ appName: 'synthetics' }); } const withCore = makeDecorator({ @@ -188,9 +188,9 @@ storiesOf('app/Overview', module) hasData: async () => false, }); registerDataHandler({ - appName: 'uptime', + appName: 'synthetics', fetchData: fetchUptimeData, - hasData: async () => false, + hasData: async () => ({ hasData: false, indices: 'heartbeat-*,synthetics-*' }), }); return ; @@ -300,9 +300,9 @@ storiesOf('app/Overview', module) hasData: async () => true, }); registerDataHandler({ - appName: 'uptime', + appName: 'synthetics', fetchData: fetchUptimeData, - hasData: async () => true, + hasData: async () => ({ hasData: true, indices: 'heartbeat-*,synthetics-*' }), }); return ( @@ -332,9 +332,9 @@ storiesOf('app/Overview', module) hasData: async () => true, }); registerDataHandler({ - appName: 'uptime', + appName: 'synthetics', fetchData: fetchUptimeData, - hasData: async () => true, + hasData: async () => ({ hasData: true, indices: 'heartbeat-*,synthetics-*' }), }); return ( @@ -366,9 +366,9 @@ storiesOf('app/Overview', module) hasData: async () => true, }); registerDataHandler({ - appName: 'uptime', + appName: 'synthetics', fetchData: fetchUptimeData, - hasData: async () => true, + hasData: async () => ({ hasData: true, indices: 'heartbeat-*,synthetics-*' }), }); return ( true, }); registerDataHandler({ - appName: 'uptime', + appName: 'synthetics', fetchData: async () => emptyUptimeResponse, - hasData: async () => true, + hasData: async () => ({ hasData: true, indices: 'heartbeat-*,synthetics-*' }), }); return ( @@ -435,11 +435,11 @@ storiesOf('app/Overview', module) hasData: async () => true, }); registerDataHandler({ - appName: 'uptime', + appName: 'synthetics', fetchData: async () => { throw new Error('Error fetching Uptime data'); }, - hasData: async () => true, + hasData: async () => ({ hasData: true, indices: 'heartbeat-*,synthetics-*' }), }); return ( { throw new Error('Error has data'); }, @@ -465,7 +465,7 @@ storiesOf('app/Overview', module) registerDataHandler({ appName: 'infra_logs', fetchData: fetchLogsData, - // @ts-ignore thows an error instead + // @ts-ignore throws an error instead hasData: async () => { throw new Error('Error has data'); }, @@ -473,15 +473,15 @@ storiesOf('app/Overview', module) registerDataHandler({ appName: 'infra_metrics', fetchData: fetchMetricsData, - // @ts-ignore thows an error instead + // @ts-ignore throws an error instead hasData: async () => { throw new Error('Error has data'); }, }); registerDataHandler({ - appName: 'uptime', + appName: 'synthetics', fetchData: fetchUptimeData, - // @ts-ignore thows an error instead + // @ts-ignore throws an error instead hasData: async () => { throw new Error('Error has data'); }, @@ -500,7 +500,7 @@ storiesOf('app/Overview', module) registerDataHandler({ appName: 'apm', fetchData: fetchApmData, - // @ts-ignore thows an error instead + // @ts-ignore throws an error instead hasData: async () => { throw new Error('Error has data'); }, @@ -508,7 +508,7 @@ storiesOf('app/Overview', module) registerDataHandler({ appName: 'infra_logs', fetchData: fetchLogsData, - // @ts-ignore thows an error instead + // @ts-ignore throws an error instead hasData: async () => { throw new Error('Error has data'); }, @@ -516,15 +516,15 @@ storiesOf('app/Overview', module) registerDataHandler({ appName: 'infra_metrics', fetchData: fetchMetricsData, - // @ts-ignore thows an error instead + // @ts-ignore throws an error instead hasData: async () => { throw new Error('Error has data'); }, }); registerDataHandler({ - appName: 'uptime', + appName: 'synthetics', fetchData: fetchUptimeData, - // @ts-ignore thows an error instead + // @ts-ignore throws an error instead hasData: async () => { throw new Error('Error has data'); }, diff --git a/x-pack/plugins/observability/public/typings/fetch_overview_data/index.ts b/x-pack/plugins/observability/public/typings/fetch_overview_data/index.ts index 528db7f4dec53..6b69aa9888cf6 100644 --- a/x-pack/plugins/observability/public/typings/fetch_overview_data/index.ts +++ b/x-pack/plugins/observability/public/typings/fetch_overview_data/index.ts @@ -32,8 +32,12 @@ export interface HasDataParams { absoluteTime: { start: number; end: number }; } -export interface UXHasDataResponse { +export interface HasDataResponse { hasData: boolean; + indices: string; +} + +export interface UXHasDataResponse extends HasDataResponse { serviceName: string | number | undefined; } @@ -47,7 +51,7 @@ export type HasData = ( export type ObservabilityFetchDataPlugins = Exclude< ObservabilityApp, - 'observability-overview' | 'stack_monitoring' | 'fleet' + 'observability-overview' | 'stack_monitoring' | 'uptime' | 'fleet' >; export interface DataHandler< @@ -126,7 +130,6 @@ export interface ObservabilityFetchDataResponse { infra_metrics: MetricsFetchDataResponse; infra_logs: LogsFetchDataResponse; synthetics: UptimeFetchDataResponse; - uptime: UptimeFetchDataResponse; ux: UxFetchDataResponse; } @@ -134,7 +137,6 @@ export interface ObservabilityHasDataResponse { apm: boolean; infra_metrics: boolean; infra_logs: boolean; - uptime: boolean; - synthetics: boolean; + synthetics: HasDataResponse; ux: UXHasDataResponse; } diff --git a/x-pack/plugins/observability/public/utils/observability_index_patterns.ts b/x-pack/plugins/observability/public/utils/observability_index_patterns.ts deleted file mode 100644 index b23a246105544..0000000000000 --- a/x-pack/plugins/observability/public/utils/observability_index_patterns.ts +++ /dev/null @@ -1,64 +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 { DataPublicPluginStart, IndexPattern } from '../../../../../src/plugins/data/public'; - -export type DataType = 'synthetics' | 'apm' | 'logs' | 'metrics' | 'rum'; - -const indexPatternList: Record = { - synthetics: 'synthetics_static_index_pattern_id', - apm: 'apm_static_index_pattern_id', - rum: 'apm_static_index_pattern_id', - logs: 'logs_static_index_pattern_id', - metrics: 'metrics_static_index_pattern_id', -}; - -const appToPatternMap: Record = { - synthetics: 'heartbeat-*', - apm: 'apm-*', - rum: 'apm-*', - logs: 'logs-*,filebeat-*', - metrics: 'metrics-*,metricbeat-*', -}; - -export class ObservabilityIndexPatterns { - data?: DataPublicPluginStart; - - constructor(data: DataPublicPluginStart) { - this.data = data; - } - - async createIndexPattern(app: DataType) { - if (!this.data) { - throw new Error('data is not defined'); - } - - const pattern = appToPatternMap[app]; - - const fields = await this.data.indexPatterns.getFieldsForWildcard({ - pattern, - }); - - return await this.data.indexPatterns.createAndSave({ - fields, - title: pattern, - id: indexPatternList[app], - timeFieldName: '@timestamp', - }); - } - - async getIndexPattern(app: DataType): Promise { - if (!this.data) { - throw new Error('data is not defined'); - } - try { - return await this.data?.indexPatterns.get(indexPatternList[app]); - } catch (e) { - return await this.createIndexPattern(app || 'apm'); - } - } -} diff --git a/x-pack/plugins/uptime/common/runtime_types/common.ts b/x-pack/plugins/uptime/common/runtime_types/common.ts index de738158cee45..4262a1a244568 100644 --- a/x-pack/plugins/uptime/common/runtime_types/common.ts +++ b/x-pack/plugins/uptime/common/runtime_types/common.ts @@ -30,6 +30,7 @@ export const SummaryType = t.partial({ export const StatesIndexStatusType = t.type({ indexExists: t.boolean, docCount: t.number, + indices: t.string, }); export const DateRangeType = t.type({ diff --git a/x-pack/plugins/uptime/public/apps/plugin.ts b/x-pack/plugins/uptime/public/apps/plugin.ts index c6a08e84c6da9..0832274f0785a 100644 --- a/x-pack/plugins/uptime/public/apps/plugin.ts +++ b/x-pack/plugins/uptime/public/apps/plugin.ts @@ -85,11 +85,11 @@ export class UptimePlugin if (plugins.observability) { plugins.observability.dashboard.register({ - appName: 'uptime', + appName: 'synthetics', hasData: async () => { const dataHelper = await getUptimeDataHelper(); const status = await dataHelper.indexStatus(); - return status.docCount > 0; + return { hasData: status.docCount > 0, indices: status.indices }; }, fetchData: async (params: FetchDataParams) => { const dataHelper = await getUptimeDataHelper(); diff --git a/x-pack/plugins/uptime/public/components/overview/empty_state/empty_state.test.tsx b/x-pack/plugins/uptime/public/components/overview/empty_state/empty_state.test.tsx index d6a64e6511024..45b107928d79a 100644 --- a/x-pack/plugins/uptime/public/components/overview/empty_state/empty_state.test.tsx +++ b/x-pack/plugins/uptime/public/components/overview/empty_state/empty_state.test.tsx @@ -19,6 +19,7 @@ describe('EmptyState component', () => { statesIndexStatus = { indexExists: true, docCount: 1, + indices: 'heartbeat-*,synthetics-*', }; }); @@ -72,6 +73,7 @@ describe('EmptyState component', () => { statesIndexStatus = { docCount: 0, indexExists: true, + indices: 'heartbeat-*,synthetics-*', }; const text = 'If this is in the snapshot the test should fail'; render( diff --git a/x-pack/plugins/uptime/public/state/effects/fetch_effect.test.ts b/x-pack/plugins/uptime/public/state/effects/fetch_effect.test.ts index 620b85b1c3233..d02ba142b907a 100644 --- a/x-pack/plugins/uptime/public/state/effects/fetch_effect.test.ts +++ b/x-pack/plugins/uptime/public/state/effects/fetch_effect.test.ts @@ -18,9 +18,13 @@ describe('fetch saga effect factory', () => { let fetchEffect; it('works with success workflow', () => { - const indexStatusResult = { indexExists: true, docCount: 2712532 }; + const indexStatusResult = { + indexExists: true, + docCount: 2712532, + indices: 'heartbeat-*,synthetics-*', + }; const fetchStatus = async (): Promise => { - return { indexExists: true, docCount: 2712532 }; + return { indexExists: true, docCount: 2712532, indices: 'heartbeat-*,synthetics-*' }; }; fetchEffect = fetchEffectFactory( fetchStatus, diff --git a/x-pack/plugins/uptime/server/lib/lib.ts b/x-pack/plugins/uptime/server/lib/lib.ts index a91ff3d3b0faf..e79d3c28a7d3a 100644 --- a/x-pack/plugins/uptime/server/lib/lib.ts +++ b/x-pack/plugins/uptime/server/lib/lib.ts @@ -29,15 +29,18 @@ export interface UMServerLibs extends UMDomainLibs { } export interface CountResponse { - body: { - count: number; - _shards: { - total: number; - successful: number; - skipped: number; - failed: number; + result: { + body: { + count: number; + _shards: { + total: number; + successful: number; + skipped: number; + failed: number; + }; }; }; + indices: string; } export type UptimeESClient = ReturnType; @@ -107,7 +110,7 @@ export function createUptimeESClient({ throw esError; } - return res; + return { result: res, indices: dynamicSettings.heartbeatIndices }; }, getSavedObjectsClient() { return savedObjectsClient; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_index_status.ts b/x-pack/plugins/uptime/server/lib/requests/get_index_status.ts index 6a00e586ffb17..dcd61d5331aa4 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_index_status.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_index_status.ts @@ -12,12 +12,16 @@ export const getIndexStatus: UMElasticsearchQueryFn<{}, StatesIndexStatus> = asy uptimeEsClient, }) => { const { - body: { - _shards: { total }, - count, + indices, + result: { + body: { + _shards: { total }, + count, + }, }, } = await uptimeEsClient.count({ terminateAfter: 1 }); return { + indices, indexExists: total > 0, docCount: count, }; diff --git a/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts b/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts index 3e410a0608094..b54515e84289a 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts @@ -48,7 +48,9 @@ export class QueryContext { } async count(params: any): Promise { - const { body } = await this.callES.count(params); + const { + result: { body }, + } = await this.callES.count(params); return body; } diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/doc_count.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/doc_count.json index 6ff7ea58c30f0..a630e968582ad 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/doc_count.json +++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/doc_count.json @@ -1,4 +1,5 @@ { "indexExists": true, - "docCount": 1 + "docCount": 1, + "indices": "heartbeat-7*,synthetics-*" } diff --git a/x-pack/test/api_integration/apis/uptime/rest/index.ts b/x-pack/test/api_integration/apis/uptime/rest/index.ts index 33fff4fb232d7..a46aa653b6f2b 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/index.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/index.ts @@ -55,7 +55,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./ping_histogram')); loadTestFile(require.resolve('./ping_list')); loadTestFile(require.resolve('./monitor_duration')); - loadTestFile(require.resolve('./doc_count')); + loadTestFile(require.resolve('./index_status')); loadTestFile(require.resolve('./monitor_states_real_data')); }); }); diff --git a/x-pack/test/api_integration/apis/uptime/rest/doc_count.ts b/x-pack/test/api_integration/apis/uptime/rest/index_status.ts similarity index 100% rename from x-pack/test/api_integration/apis/uptime/rest/doc_count.ts rename to x-pack/test/api_integration/apis/uptime/rest/index_status.ts diff --git a/x-pack/test/apm_api_integration/tests/csm/has_rum_data.ts b/x-pack/test/apm_api_integration/tests/csm/has_rum_data.ts index 4474d0996175b..15ddc04e2414d 100644 --- a/x-pack/test/apm_api_integration/tests/csm/has_rum_data.ts +++ b/x-pack/test/apm_api_integration/tests/csm/has_rum_data.ts @@ -22,6 +22,7 @@ export default function rumHasDataApiTests({ getService }: FtrProviderContext) { expectSnapshot(response.body).toMatchInline(` Object { "hasData": false, + "indices": "traces-apm*,apm-*", } `); }); @@ -41,6 +42,7 @@ export default function rumHasDataApiTests({ getService }: FtrProviderContext) { expectSnapshot(response.body).toMatchInline(` Object { "hasData": true, + "indices": "traces-apm*,apm-*", "serviceName": "client", } `); From dc1d64fe50717f62a7be75d8e49502326315eb2f Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 21 Apr 2021 09:37:56 -0400 Subject: [PATCH 13/18] [ML] Add telemetry for Anomaly detection alert rules (#97727) (#97800) * [ML] register usage collection * [ML] fix telemetry * [ML] fix definition schema for collector * [ML] get kibana config synchronously Co-authored-by: Dima Arnautov --- x-pack/plugins/ml/kibana.json | 3 +- x-pack/plugins/ml/server/plugin.ts | 9 ++ x-pack/plugins/ml/server/types.ts | 2 + x-pack/plugins/ml/server/usage/collector.ts | 100 ++++++++++++++++++ x-pack/plugins/ml/server/usage/index.ts | 8 ++ .../schema/xpack_plugins.json | 34 ++++++ 6 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/ml/server/usage/collector.ts create mode 100644 x-pack/plugins/ml/server/usage/index.ts diff --git a/x-pack/plugins/ml/kibana.json b/x-pack/plugins/ml/kibana.json index f61ab17646b65..6804b3f52b52a 100644 --- a/x-pack/plugins/ml/kibana.json +++ b/x-pack/plugins/ml/kibana.json @@ -28,7 +28,8 @@ "management", "licenseManagement", "maps", - "lens" + "lens", + "usageCollection" ], "server": true, "ui": true, diff --git a/x-pack/plugins/ml/server/plugin.ts b/x-pack/plugins/ml/server/plugin.ts index 173b30716c6b6..746d290950704 100644 --- a/x-pack/plugins/ml/server/plugin.ts +++ b/x-pack/plugins/ml/server/plugin.ts @@ -16,6 +16,7 @@ import { CapabilitiesStart, IClusterClient, SavedObjectsServiceStart, + SharedGlobalConfig, } from 'kibana/server'; import type { SecurityPluginSetup } from '../../security/server'; import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/server'; @@ -59,6 +60,7 @@ import { RouteGuard } from './lib/route_guard'; import { registerMlAlerts } from './lib/alerts/register_ml_alerts'; import { ML_ALERT_TYPES } from '../common/constants/alerts'; import { alertingRoutes } from './routes/alerting'; +import { registerCollector } from './usage'; export type MlPluginSetup = SharedServices; export type MlPluginStart = void; @@ -74,11 +76,14 @@ export class MlServerPlugin private security: SecurityPluginSetup | undefined; private isMlReady: Promise; private setMlReady: () => void = () => {}; + private readonly kibanaIndexConfig: SharedGlobalConfig; constructor(ctx: PluginInitializerContext) { this.log = ctx.logger.get(); this.mlLicense = new MlLicense(); this.isMlReady = new Promise((resolve) => (this.setMlReady = resolve)); + + this.kibanaIndexConfig = ctx.config.legacy.get(); } public setup(coreSetup: CoreSetup, plugins: PluginsSetup): MlPluginSetup { @@ -212,6 +217,10 @@ export class MlServerPlugin }); } + if (plugins.usageCollection) { + registerCollector(plugins.usageCollection, this.kibanaIndexConfig.kibana.index); + } + return { ...sharedServices }; } diff --git a/x-pack/plugins/ml/server/types.ts b/x-pack/plugins/ml/server/types.ts index 2109685f5dcc2..013feb568ca53 100644 --- a/x-pack/plugins/ml/server/types.ts +++ b/x-pack/plugins/ml/server/types.ts @@ -17,6 +17,7 @@ import type { ResolveMlCapabilities } from '../common/types/capabilities'; import type { RouteGuard } from './lib/route_guard'; import type { AlertingPlugin } from '../../alerting/server'; import type { ActionsPlugin } from '../../actions/server'; +import type { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; export interface LicenseCheckResult { isAvailable: boolean; @@ -47,6 +48,7 @@ export interface PluginsSetup { spaces?: SpacesPluginSetup; alerting?: AlertingPlugin['setup']; actions?: ActionsPlugin['setup']; + usageCollection?: UsageCollectionSetup; } export interface PluginsStart { diff --git a/x-pack/plugins/ml/server/usage/collector.ts b/x-pack/plugins/ml/server/usage/collector.ts new file mode 100644 index 0000000000000..91fa72e3a04cc --- /dev/null +++ b/x-pack/plugins/ml/server/usage/collector.ts @@ -0,0 +1,100 @@ +/* + * 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 { UsageCollectionSetup } from '../../../../../src/plugins/usage_collection/server'; +import { ML_ALERT_TYPES } from '../../common/constants/alerts'; +import { AnomalyResultType } from '../../common/types/anomalies'; + +export interface MlUsageData { + alertRules: { + 'xpack.ml.anomaly_detection_alert': { + count_by_result_type: { + record: number; + bucket: number; + influencer: number; + }; + }; + }; +} + +export function registerCollector(usageCollection: UsageCollectionSetup, kibanaIndex: string) { + const collector = usageCollection.makeUsageCollector({ + type: 'ml', + schema: { + alertRules: { + 'xpack.ml.anomaly_detection_alert': { + count_by_result_type: { + record: { + type: 'long', + _meta: { description: 'total number of alerting rules using record result type' }, + }, + influencer: { + type: 'long', + _meta: { description: 'total number of alerting rules using influencer result type' }, + }, + bucket: { + type: 'long', + _meta: { description: 'total number of alerting rules using bucket result type' }, + }, + }, + }, + }, + }, + isReady: () => !!kibanaIndex, + fetch: async ({ esClient }) => { + const result = await esClient.search({ + index: kibanaIndex, + size: 0, + body: { + query: { + bool: { + filter: [ + { term: { type: 'alert' } }, + { + term: { + 'alert.alertTypeId': ML_ALERT_TYPES.ANOMALY_DETECTION, + }, + }, + ], + }, + }, + aggs: { + count_by_result_type: { + terms: { + field: 'alert.params.resultType', + size: 3, + }, + }, + }, + }, + }); + + const aggResponse = result.body.aggregations as { + count_by_result_type: { + buckets: Array<{ + key: AnomalyResultType; + doc_count: number; + }>; + }; + }; + const countByResultType = aggResponse.count_by_result_type.buckets.reduce((acc, curr) => { + acc[curr.key] = curr.doc_count; + return acc; + }, {} as MlUsageData['alertRules'][typeof ML_ALERT_TYPES.ANOMALY_DETECTION]['count_by_result_type']); + + return { + alertRules: { + [ML_ALERT_TYPES.ANOMALY_DETECTION]: { + count_by_result_type: countByResultType, + }, + }, + }; + }, + }); + + usageCollection.registerCollector(collector); +} diff --git a/x-pack/plugins/ml/server/usage/index.ts b/x-pack/plugins/ml/server/usage/index.ts new file mode 100644 index 0000000000000..adadedd200fe9 --- /dev/null +++ b/x-pack/plugins/ml/server/usage/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 { registerCollector } from './collector'; diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index a6bbf076a5b04..b8c8c5121d7d7 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -3430,6 +3430,40 @@ } } }, + "ml": { + "properties": { + "alertRules": { + "properties": { + "xpack.ml.anomaly_detection_alert": { + "properties": { + "count_by_result_type": { + "properties": { + "record": { + "type": "long", + "_meta": { + "description": "total number of alerting rules using record result type" + } + }, + "influencer": { + "type": "long", + "_meta": { + "description": "total number of alerting rules using influencer result type" + } + }, + "bucket": { + "type": "long", + "_meta": { + "description": "total number of alerting rules using bucket result type" + } + } + } + } + } + } + } + } + } + }, "kibana_settings": { "properties": { "xpack": { From a825bc0619e8ba09acbb8efb28e1e028e1d37417 Mon Sep 17 00:00:00 2001 From: Zacqary Adam Xeper Date: Wed, 21 Apr 2021 09:21:15 -0500 Subject: [PATCH 14/18] [Fleet] Fix 'Cannot read preconfigurationError of null' on setup (#97743) (#97765) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/fleet/public/applications/fleet/app.tsx | 4 ++-- x-pack/plugins/fleet/server/routes/setup/handlers.ts | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/app.tsx b/x-pack/plugins/fleet/public/applications/fleet/app.tsx index f2eee6228906a..4a47d39b77934 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/app.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/app.tsx @@ -83,14 +83,14 @@ export const WithPermissionsAndSetup: React.FC = memo(({ children }) => { if (setupResponse.error) { setInitializationError(setupResponse.error); } - if (setupResponse.data.preconfigurationError) { + if (setupResponse.data?.preconfigurationError) { notifications.toasts.addError(setupResponse.data.preconfigurationError, { title: i18n.translate('xpack.fleet.setup.uiPreconfigurationErrorTitle', { defaultMessage: 'Configuration error', }), }); } - if (setupResponse.data.nonFatalPackageUpgradeErrors) { + if (setupResponse.data?.nonFatalPackageUpgradeErrors) { notifications.toasts.addError(setupResponse.data.nonFatalPackageUpgradeErrors, { title: i18n.translate('xpack.fleet.setup.nonFatalPackageErrorsTitle', { defaultMessage: 'One or more packages could not be successfully upgraded', diff --git a/x-pack/plugins/fleet/server/routes/setup/handlers.ts b/x-pack/plugins/fleet/server/routes/setup/handlers.ts index a6d7acccfb4fe..627f628f7b9fc 100644 --- a/x-pack/plugins/fleet/server/routes/setup/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/setup/handlers.ts @@ -46,13 +46,10 @@ export const fleetSetupHandler: RequestHandler = async (context, request, respon try { const soClient = context.core.savedObjects.client; const esClient = context.core.elasticsearch.client.asCurrentUser; - const setupStatus = await setupIngestManager(soClient, esClient); - const body: PostIngestSetupResponse = { - isInitialized: true, - }; + const body: PostIngestSetupResponse = await setupIngestManager(soClient, esClient); - if (setupStatus.nonFatalPackageUpgradeErrors.length > 0) { - body.nonFatalPackageUpgradeErrors = setupStatus.nonFatalPackageUpgradeErrors; + if (body.nonFatalPackageUpgradeErrors?.length === 0) { + delete body.nonFatalPackageUpgradeErrors; } return response.ok({ From 22342b47f4a9f45d65627e6932ff3f0125241f9e Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Wed, 21 Apr 2021 16:30:21 +0200 Subject: [PATCH 15/18] [Search] Unify search plugin step 1 (#95811) (#97807) Remove the defaultStrategy override Move async search strategy to data Move EQL search strategy to data Move rest of common/search/session data (Moving whole search/session is blocked by security and taskManager) --- docs/developer/plugin-list.asciidoc | 2 +- ...earchresponse.expiration_time_in_millis.md | 11 ++ ...gins-data-server.asyncsearchresponse.id.md | 11 ++ ...a-server.asyncsearchresponse.is_partial.md | 11 ++ ...a-server.asyncsearchresponse.is_running.md | 11 ++ ...plugins-data-server.asyncsearchresponse.md | 23 ++++ ...ata-server.asyncsearchresponse.response.md | 11 ++ ...syncsearchresponse.start_time_in_millis.md | 11 ++ ...erver.asyncsearchstatusresponse._shards.md | 11 ++ ...csearchstatusresponse.completion_status.md | 11 ++ ...s-data-server.asyncsearchstatusresponse.md | 19 ++++ .../kibana-plugin-plugins-data-server.md | 2 + src/plugins/data/README.mdx | 3 +- src/plugins/data/common/search/index.ts | 5 +- .../data}/common/search/poll_search.test.ts | 5 +- .../data}/common/search/poll_search.ts | 11 +- .../eql_search}/index.ts | 0 .../search/strategies/eql_search}/types.ts | 20 +--- .../search/strategies/es_search/index.ts | 9 ++ .../{ => strategies}/es_search/types.ts | 2 +- .../search/strategies/ese_search/index.ts | 9 ++ .../search/strategies/ese_search/types.ts | 18 +++ src/plugins/data/common/search/types.ts | 3 +- src/plugins/data/config.ts | 59 ++++++++++ src/plugins/data/public/public.api.md | 4 +- .../public/search/search_interceptor.test.ts | 2 +- .../data/public/search/search_interceptor.ts | 6 + src/plugins/data/server/index.ts | 2 + src/plugins/data/server/search/README.md | 9 +- src/plugins/data/server/search/index.ts | 4 +- .../data/server/search/search_service.test.ts | 46 ++++---- .../data/server/search/search_service.ts | 24 +++- .../data/server/search/session/mocks.ts | 8 ++ .../server/search/session/session_service.ts | 3 + .../data/server/search/session/types.ts | 2 + .../eql_search}/eql_search_strategy.test.ts | 9 +- .../eql_search}/eql_search_strategy.ts | 18 +-- .../search/strategies/eql_search/index.ts | 9 ++ .../strategies/eql_search}/response_utils.ts | 23 +--- .../search/strategies/eql_search/types.ts | 15 +++ .../es_search/elasticsearch.ts | 0 .../es_search/es_search_strategy.test.ts | 10 +- .../es_search/es_search_strategy.ts | 8 +- .../{ => strategies}/es_search/index.ts | 2 +- .../es_search/request_utils.test.ts | 0 .../es_search/request_utils.ts | 2 +- .../es_search/response_utils.test.ts | 0 .../es_search/response_utils.ts | 2 +- .../ese_search/ese_search_strategy.test.ts | 104 ++++-------------- .../ese_search/ese_search_strategy.ts | 43 ++++---- .../search/strategies/ese_search/index.ts | 10 ++ .../strategies/ese_search}/request_utils.ts | 19 ++-- .../strategies/ese_search/response_utils.ts | 23 ++++ .../search/strategies/ese_search}/types.ts | 13 +-- src/plugins/data/server/search/types.ts | 4 +- src/plugins/data/server/server.api.md | 54 +++++++-- test/api_integration/apis/search/bsearch.ts | 10 +- x-pack/plugins/data_enhanced/README.md | 23 ++-- x-pack/plugins/data_enhanced/common/index.ts | 14 --- .../data_enhanced/common/search/index.ts | 4 - .../common/search/session/index.ts | 16 --- .../common/search/session/status.ts | 14 --- .../common/search/session/types.ts | 93 ---------------- x-pack/plugins/data_enhanced/config.ts | 57 +--------- x-pack/plugins/data_enhanced/public/index.ts | 5 +- .../public/search/search_interceptor.ts | 10 +- .../sessions_mgmt/components/status.test.tsx | 2 +- .../sessions_mgmt/components/status.tsx | 2 +- .../components/table/table.test.tsx | 2 +- .../sessions_mgmt/components/table/table.tsx | 2 +- .../search/sessions_mgmt/lib/api.test.ts | 2 +- .../public/search/sessions_mgmt/lib/api.ts | 2 +- .../sessions_mgmt/lib/get_columns.test.tsx | 2 +- .../search/sessions_mgmt/lib/get_columns.tsx | 2 +- .../public/search/sessions_mgmt/types.ts | 5 +- .../data_enhanced/server/collectors/fetch.ts | 2 +- x-pack/plugins/data_enhanced/server/index.ts | 5 +- x-pack/plugins/data_enhanced/server/plugin.ts | 26 +---- .../server/saved_objects/search_session.ts | 2 +- .../search_session_migration.test.ts | 3 +- .../saved_objects/search_session_migration.ts | 2 +- .../data_enhanced/server/search/index.ts | 2 - .../session/check_running_sessions.test.ts | 2 +- .../search/session/check_running_sessions.ts | 4 +- .../search/session/get_search_status.ts | 4 +- .../search/session/get_session_status.test.ts | 2 +- .../search/session/get_session_status.ts | 5 +- .../server/search/session/monitoring_task.ts | 2 +- .../search/session/session_service.test.ts | 7 +- .../server/search/session/session_service.ts | 7 +- .../server/search_strategy/osquery/index.ts | 2 +- .../timeline/events/eql/index.ts | 2 +- .../public/common/hooks/eql/api.ts | 4 +- .../hooks/eql/eql_search_response.mock.ts | 2 +- .../public/common/hooks/eql/helpers.test.ts | 2 +- .../public/common/hooks/eql/helpers.ts | 2 +- .../common/hooks/eql/use_eql_preview.test.ts | 2 +- .../common/hooks/eql/use_eql_preview.ts | 6 +- .../security_solution/index.ts | 2 +- .../timeline/eql/__mocks__/index.ts | 2 +- .../search_strategy/timeline/eql/helpers.ts | 2 +- .../search_strategy/timeline/eql/index.ts | 2 +- .../server/search_strategy/timeline/index.ts | 2 +- .../api_integration/apis/search/session.ts | 2 +- .../search_sessions_management_page.ts | 2 +- 105 files changed, 601 insertions(+), 533 deletions(-) create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.expiration_time_in_millis.md create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.id.md create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.is_partial.md create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.is_running.md create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.md create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.response.md create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.start_time_in_millis.md create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchstatusresponse._shards.md create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchstatusresponse.completion_status.md create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchstatusresponse.md rename {x-pack/plugins/data_enhanced => src/plugins/data}/common/search/poll_search.test.ts (95%) rename {x-pack/plugins/data_enhanced => src/plugins/data}/common/search/poll_search.ts (82%) rename src/plugins/data/common/search/{es_search => strategies/eql_search}/index.ts (100%) rename {x-pack/plugins/data_enhanced/common/search => src/plugins/data/common/search/strategies/eql_search}/types.ts (58%) create mode 100644 src/plugins/data/common/search/strategies/es_search/index.ts rename src/plugins/data/common/search/{ => strategies}/es_search/types.ts (98%) create mode 100644 src/plugins/data/common/search/strategies/ese_search/index.ts create mode 100644 src/plugins/data/common/search/strategies/ese_search/types.ts rename {x-pack/plugins/data_enhanced/server/search => src/plugins/data/server/search/strategies/eql_search}/eql_search_strategy.test.ts (95%) rename {x-pack/plugins/data_enhanced/server/search => src/plugins/data/server/search/strategies/eql_search}/eql_search_strategy.ts (84%) create mode 100644 src/plugins/data/server/search/strategies/eql_search/index.ts rename {x-pack/plugins/data_enhanced/server/search => src/plugins/data/server/search/strategies/eql_search}/response_utils.ts (50%) create mode 100644 src/plugins/data/server/search/strategies/eql_search/types.ts rename src/plugins/data/server/search/{ => strategies}/es_search/elasticsearch.ts (100%) rename src/plugins/data/server/search/{ => strategies}/es_search/es_search_strategy.test.ts (95%) rename src/plugins/data/server/search/{ => strategies}/es_search/es_search_strategy.ts (88%) rename src/plugins/data/server/search/{ => strategies}/es_search/index.ts (94%) rename src/plugins/data/server/search/{ => strategies}/es_search/request_utils.test.ts (100%) rename src/plugins/data/server/search/{ => strategies}/es_search/request_utils.ts (97%) rename src/plugins/data/server/search/{ => strategies}/es_search/response_utils.test.ts (100%) rename src/plugins/data/server/search/{ => strategies}/es_search/response_utils.ts (96%) rename x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts => src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.test.ts (81%) rename x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts => src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.ts (87%) create mode 100644 src/plugins/data/server/search/strategies/ese_search/index.ts rename {x-pack/plugins/data_enhanced/server/search => src/plugins/data/server/search/strategies/ese_search}/request_utils.ts (70%) create mode 100644 src/plugins/data/server/search/strategies/ese_search/response_utils.ts rename {x-pack/plugins/data_enhanced/server/search => src/plugins/data/server/search/strategies/ese_search}/types.ts (67%) delete mode 100644 x-pack/plugins/data_enhanced/common/search/session/index.ts delete mode 100644 x-pack/plugins/data_enhanced/common/search/session/status.ts delete mode 100644 x-pack/plugins/data_enhanced/common/search/session/types.ts diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 7ffee75f83d69..5555dc8ac6d7b 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -362,7 +362,7 @@ Failure to have auth enabled in Kibana will make for a broken UI. UI-based error |{kib-repo}blob/{branch}/x-pack/plugins/data_enhanced/README.md[dataEnhanced] -|The data_enhanced plugin is the x-pack counterpart to the OSS data plugin. +|The data_enhanced plugin is the x-pack counterpart to the src/plguins/data plugin. |{kib-repo}blob/{branch}/x-pack/plugins/discover_enhanced/README.md[discoverEnhanced] diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.expiration_time_in_millis.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.expiration_time_in_millis.md new file mode 100644 index 0000000000000..eab2fbc6431c6 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.expiration_time_in_millis.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [AsyncSearchResponse](./kibana-plugin-plugins-data-server.asyncsearchresponse.md) > [expiration\_time\_in\_millis](./kibana-plugin-plugins-data-server.asyncsearchresponse.expiration_time_in_millis.md) + +## AsyncSearchResponse.expiration\_time\_in\_millis property + +Signature: + +```typescript +expiration_time_in_millis: number; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.id.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.id.md new file mode 100644 index 0000000000000..d3b61be9b08b3 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [AsyncSearchResponse](./kibana-plugin-plugins-data-server.asyncsearchresponse.md) > [id](./kibana-plugin-plugins-data-server.asyncsearchresponse.id.md) + +## AsyncSearchResponse.id property + +Signature: + +```typescript +id?: string; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.is_partial.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.is_partial.md new file mode 100644 index 0000000000000..1d1a5ccd1ac69 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.is_partial.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [AsyncSearchResponse](./kibana-plugin-plugins-data-server.asyncsearchresponse.md) > [is\_partial](./kibana-plugin-plugins-data-server.asyncsearchresponse.is_partial.md) + +## AsyncSearchResponse.is\_partial property + +Signature: + +```typescript +is_partial: boolean; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.is_running.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.is_running.md new file mode 100644 index 0000000000000..17af7a39acfe7 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.is_running.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [AsyncSearchResponse](./kibana-plugin-plugins-data-server.asyncsearchresponse.md) > [is\_running](./kibana-plugin-plugins-data-server.asyncsearchresponse.is_running.md) + +## AsyncSearchResponse.is\_running property + +Signature: + +```typescript +is_running: boolean; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.md new file mode 100644 index 0000000000000..2f11e03f82b5f --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [AsyncSearchResponse](./kibana-plugin-plugins-data-server.asyncsearchresponse.md) + +## AsyncSearchResponse interface + +Signature: + +```typescript +export interface AsyncSearchResponse +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [expiration\_time\_in\_millis](./kibana-plugin-plugins-data-server.asyncsearchresponse.expiration_time_in_millis.md) | number | | +| [id](./kibana-plugin-plugins-data-server.asyncsearchresponse.id.md) | string | | +| [is\_partial](./kibana-plugin-plugins-data-server.asyncsearchresponse.is_partial.md) | boolean | | +| [is\_running](./kibana-plugin-plugins-data-server.asyncsearchresponse.is_running.md) | boolean | | +| [response](./kibana-plugin-plugins-data-server.asyncsearchresponse.response.md) | estypes.SearchResponse<T> | | +| [start\_time\_in\_millis](./kibana-plugin-plugins-data-server.asyncsearchresponse.start_time_in_millis.md) | number | | + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.response.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.response.md new file mode 100644 index 0000000000000..9370e21542e37 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.response.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [AsyncSearchResponse](./kibana-plugin-plugins-data-server.asyncsearchresponse.md) > [response](./kibana-plugin-plugins-data-server.asyncsearchresponse.response.md) + +## AsyncSearchResponse.response property + +Signature: + +```typescript +response: estypes.SearchResponse; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.start_time_in_millis.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.start_time_in_millis.md new file mode 100644 index 0000000000000..91db5f06d9b2f --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchresponse.start_time_in_millis.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [AsyncSearchResponse](./kibana-plugin-plugins-data-server.asyncsearchresponse.md) > [start\_time\_in\_millis](./kibana-plugin-plugins-data-server.asyncsearchresponse.start_time_in_millis.md) + +## AsyncSearchResponse.start\_time\_in\_millis property + +Signature: + +```typescript +start_time_in_millis: number; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchstatusresponse._shards.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchstatusresponse._shards.md new file mode 100644 index 0000000000000..5cb7e7135aecf --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchstatusresponse._shards.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [AsyncSearchStatusResponse](./kibana-plugin-plugins-data-server.asyncsearchstatusresponse.md) > [\_shards](./kibana-plugin-plugins-data-server.asyncsearchstatusresponse._shards.md) + +## AsyncSearchStatusResponse.\_shards property + +Signature: + +```typescript +_shards: ShardsResponse; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchstatusresponse.completion_status.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchstatusresponse.completion_status.md new file mode 100644 index 0000000000000..16cd3af3f8d49 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchstatusresponse.completion_status.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [AsyncSearchStatusResponse](./kibana-plugin-plugins-data-server.asyncsearchstatusresponse.md) > [completion\_status](./kibana-plugin-plugins-data-server.asyncsearchstatusresponse.completion_status.md) + +## AsyncSearchStatusResponse.completion\_status property + +Signature: + +```typescript +completion_status: number; +``` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchstatusresponse.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchstatusresponse.md new file mode 100644 index 0000000000000..5d7ea57939269 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.asyncsearchstatusresponse.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [AsyncSearchStatusResponse](./kibana-plugin-plugins-data-server.asyncsearchstatusresponse.md) + +## AsyncSearchStatusResponse interface + +Signature: + +```typescript +export interface AsyncSearchStatusResponse extends Omit +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [\_shards](./kibana-plugin-plugins-data-server.asyncsearchstatusresponse._shards.md) | ShardsResponse | | +| [completion\_status](./kibana-plugin-plugins-data-server.asyncsearchstatusresponse.completion_status.md) | number | | + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md index e0734bc017f4f..b1745b298e27e 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md @@ -45,6 +45,8 @@ | --- | --- | | [AggFunctionsMapping](./kibana-plugin-plugins-data-server.aggfunctionsmapping.md) | A global list of the expression function definitions for each agg type function. | | [AggParamOption](./kibana-plugin-plugins-data-server.aggparamoption.md) | | +| [AsyncSearchResponse](./kibana-plugin-plugins-data-server.asyncsearchresponse.md) | | +| [AsyncSearchStatusResponse](./kibana-plugin-plugins-data-server.asyncsearchstatusresponse.md) | | | [EsQueryConfig](./kibana-plugin-plugins-data-server.esqueryconfig.md) | | | [FieldDescriptor](./kibana-plugin-plugins-data-server.fielddescriptor.md) | | | [FieldFormatConfig](./kibana-plugin-plugins-data-server.fieldformatconfig.md) | | diff --git a/src/plugins/data/README.mdx b/src/plugins/data/README.mdx index 30006e2b497bd..fba5cbd6d48e1 100644 --- a/src/plugins/data/README.mdx +++ b/src/plugins/data/README.mdx @@ -623,8 +623,7 @@ The `SearchSource` API is a convenient way to construct and run an Elasticsearch #### Default Search Strategy -One benefit of using the low-level search API, is partial response support in X-Pack, allowing for a better and more responsive user experience. -In OSS only the final result is returned. +One benefit of using the low-level search API, is partial response support, allowing for a better and more responsive user experience. ```.ts import { isCompleteResponse } from '../plugins/data/public'; diff --git a/src/plugins/data/common/search/index.ts b/src/plugins/data/common/search/index.ts index 1b74cec2fc847..badbb94e9752f 100644 --- a/src/plugins/data/common/search/index.ts +++ b/src/plugins/data/common/search/index.ts @@ -7,10 +7,13 @@ */ export * from './aggs'; -export * from './es_search'; export * from './expressions'; export * from './search_source'; export * from './tabify'; export * from './types'; export * from './utils'; export * from './session'; +export * from './poll_search'; +export * from './strategies/es_search'; +export * from './strategies/eql_search'; +export * from './strategies/ese_search'; diff --git a/x-pack/plugins/data_enhanced/common/search/poll_search.test.ts b/src/plugins/data/common/search/poll_search.test.ts similarity index 95% rename from x-pack/plugins/data_enhanced/common/search/poll_search.test.ts rename to src/plugins/data/common/search/poll_search.test.ts index 36fd326e39672..037fd0fc059d1 100644 --- a/x-pack/plugins/data_enhanced/common/search/poll_search.test.ts +++ b/src/plugins/data/common/search/poll_search.test.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 { pollSearch } from './poll_search'; diff --git a/x-pack/plugins/data_enhanced/common/search/poll_search.ts b/src/plugins/data/common/search/poll_search.ts similarity index 82% rename from x-pack/plugins/data_enhanced/common/search/poll_search.ts rename to src/plugins/data/common/search/poll_search.ts index a6946b4dfde7c..fa31f2cb208a6 100644 --- a/x-pack/plugins/data_enhanced/common/search/poll_search.ts +++ b/src/plugins/data/common/search/poll_search.ts @@ -1,16 +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. + * 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 { from, Observable, timer, defer, fromEvent, EMPTY } from 'rxjs'; import { expand, map, switchMap, takeUntil, takeWhile, tap } from 'rxjs/operators'; -import type { IKibanaSearchResponse } from '../../../../../src/plugins/data/common'; +import type { + IAsyncSearchOptions, + IKibanaSearchResponse, +} from '../../../../../src/plugins/data/common'; import { isErrorResponse, isPartialResponse } from '../../../../../src/plugins/data/common'; import { AbortError } from '../../../../../src/plugins/kibana_utils/common'; -import type { IAsyncSearchOptions } from './types'; export const pollSearch = ( search: () => Promise, diff --git a/src/plugins/data/common/search/es_search/index.ts b/src/plugins/data/common/search/strategies/eql_search/index.ts similarity index 100% rename from src/plugins/data/common/search/es_search/index.ts rename to src/plugins/data/common/search/strategies/eql_search/index.ts diff --git a/x-pack/plugins/data_enhanced/common/search/types.ts b/src/plugins/data/common/search/strategies/eql_search/types.ts similarity index 58% rename from x-pack/plugins/data_enhanced/common/search/types.ts rename to src/plugins/data/common/search/strategies/eql_search/types.ts index 0692371155ce3..a30adbaf47c60 100644 --- a/x-pack/plugins/data_enhanced/common/search/types.ts +++ b/src/plugins/data/common/search/strategies/eql_search/types.ts @@ -1,20 +1,15 @@ /* * 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 { EqlSearch } from '@elastic/elasticsearch/api/requestParams'; import { ApiResponse, TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; -import { - ISearchOptions, - IKibanaSearchRequest, - IKibanaSearchResponse, -} from '../../../../../src/plugins/data/common'; - -export const ENHANCED_ES_SEARCH_STRATEGY = 'ese'; +import { IKibanaSearchRequest, IKibanaSearchResponse } from '../../types'; export const EQL_SEARCH_STRATEGY = 'eql'; @@ -25,10 +20,3 @@ export interface EqlSearchStrategyRequest extends IKibanaSearchRequest = IKibanaSearchResponse>; - -export interface IAsyncSearchOptions extends ISearchOptions { - /** - * The number of milliseconds to wait between receiving a response and sending another request - */ - pollInterval?: number; -} diff --git a/src/plugins/data/common/search/strategies/es_search/index.ts b/src/plugins/data/common/search/strategies/es_search/index.ts new file mode 100644 index 0000000000000..12594660136d8 --- /dev/null +++ b/src/plugins/data/common/search/strategies/es_search/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 './types'; diff --git a/src/plugins/data/common/search/es_search/types.ts b/src/plugins/data/common/search/strategies/es_search/types.ts similarity index 98% rename from src/plugins/data/common/search/es_search/types.ts rename to src/plugins/data/common/search/strategies/es_search/types.ts index 12dc0c1b2599d..05df661d466c8 100644 --- a/src/plugins/data/common/search/es_search/types.ts +++ b/src/plugins/data/common/search/strategies/es_search/types.ts @@ -7,7 +7,7 @@ */ import type { estypes } from '@elastic/elasticsearch'; -import { IKibanaSearchRequest, IKibanaSearchResponse } from '../types'; +import { IKibanaSearchRequest, IKibanaSearchResponse } from '../../types'; export const ES_SEARCH_STRATEGY = 'es'; diff --git a/src/plugins/data/common/search/strategies/ese_search/index.ts b/src/plugins/data/common/search/strategies/ese_search/index.ts new file mode 100644 index 0000000000000..12594660136d8 --- /dev/null +++ b/src/plugins/data/common/search/strategies/ese_search/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 './types'; diff --git a/src/plugins/data/common/search/strategies/ese_search/types.ts b/src/plugins/data/common/search/strategies/ese_search/types.ts new file mode 100644 index 0000000000000..202455b52dc10 --- /dev/null +++ b/src/plugins/data/common/search/strategies/ese_search/types.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { ISearchOptions } from '../../types'; + +export const ENHANCED_ES_SEARCH_STRATEGY = 'ese'; + +export interface IAsyncSearchOptions extends ISearchOptions { + /** + * The number of milliseconds to wait between receiving a response and sending another request + */ + pollInterval?: number; +} diff --git a/src/plugins/data/common/search/types.ts b/src/plugins/data/common/search/types.ts index e3ec499a0020d..d1890ec97df4e 100644 --- a/src/plugins/data/common/search/types.ts +++ b/src/plugins/data/common/search/types.ts @@ -7,8 +7,7 @@ */ import { Observable } from 'rxjs'; -import { IEsSearchRequest, IEsSearchResponse } from './es_search'; -import { IndexPattern } from '..'; +import { IEsSearchRequest, IEsSearchResponse, IndexPattern } from '..'; import type { RequestAdapter } from '../../../inspector/common'; export type ISearchGeneric = < diff --git a/src/plugins/data/config.ts b/src/plugins/data/config.ts index 7a4e79efa2f0a..72fa547f44a77 100644 --- a/src/plugins/data/config.ts +++ b/src/plugins/data/config.ts @@ -30,3 +30,62 @@ export const configSchema = schema.object({ }); export type ConfigSchema = TypeOf; + +export const searchSessionsConfigSchema = schema.object({ + /** + * Turns the feature on \ off (incl. removing indicator and management screens) + */ + enabled: schema.boolean({ defaultValue: true }), + /** + * pageSize controls how many search session objects we load at once while monitoring + * session completion + */ + pageSize: schema.number({ defaultValue: 100 }), + /** + * trackingInterval controls how often we track search session objects progress + */ + trackingInterval: schema.duration({ defaultValue: '10s' }), + + /** + * monitoringTaskTimeout controls for how long task manager waits for search session monitoring task to complete before considering it timed out, + * If tasks timeouts it receives cancel signal and next task starts in "trackingInterval" time + */ + monitoringTaskTimeout: schema.duration({ defaultValue: '5m' }), + + /** + * notTouchedTimeout controls how long do we store unpersisted search session results, + * after the last search in the session has completed + */ + notTouchedTimeout: schema.duration({ defaultValue: '5m' }), + /** + * notTouchedInProgressTimeout controls how long do allow a search session to run after + * a user has navigated away without persisting + */ + notTouchedInProgressTimeout: schema.duration({ defaultValue: '1m' }), + /** + * maxUpdateRetries controls how many retries we perform while attempting to save a search session + */ + maxUpdateRetries: schema.number({ defaultValue: 3 }), + + /** + * defaultExpiration controls how long search sessions are valid for, until they are expired. + */ + defaultExpiration: schema.duration({ defaultValue: '7d' }), + management: schema.object({ + /** + * maxSessions controls how many saved search sessions we display per page on the management screen. + */ + maxSessions: schema.number({ defaultValue: 10000 }), + /** + * refreshInterval controls how often we refresh the management screen. + */ + refreshInterval: schema.duration({ defaultValue: '10s' }), + /** + * refreshTimeout controls how often we refresh the management screen. + */ + refreshTimeout: schema.duration({ defaultValue: '1m' }), + expiresSoonWarning: schema.duration({ defaultValue: '1d' }), + }), +}); + +export type SearchSessionsConfigSchema = TypeOf; diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index ff76f550368f3..c1109170b3ce9 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -2362,8 +2362,8 @@ export const SEARCH_SESSIONS_MANAGEMENT_ID = "search_sessions"; // Warning: (ae-missing-release-tag) "SearchBar" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const SearchBar: React.ComponentClass, "query" | "placeholder" | "isLoading" | "iconType" | "indexPatterns" | "filters" | "dataTestSubj" | "isClearable" | "refreshInterval" | "nonKqlMode" | "nonKqlModeHelpText" | "screenTitle" | "onRefresh" | "onRefreshChange" | "showQueryInput" | "showDatePicker" | "showAutoRefreshOnly" | "dateRangeFrom" | "dateRangeTo" | "isRefreshPaused" | "customSubmitButton" | "timeHistory" | "indicateNoData" | "onFiltersUpdated" | "savedQuery" | "showSaveQuery" | "onClearSavedQuery" | "showQueryBar" | "showFilterBar" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated">, any> & { - WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; +export const SearchBar: React.ComponentClass, "query" | "placeholder" | "isLoading" | "iconType" | "indexPatterns" | "filters" | "dataTestSubj" | "refreshInterval" | "isClearable" | "nonKqlMode" | "nonKqlModeHelpText" | "screenTitle" | "onRefresh" | "onRefreshChange" | "showQueryInput" | "showDatePicker" | "showAutoRefreshOnly" | "dateRangeFrom" | "dateRangeTo" | "isRefreshPaused" | "customSubmitButton" | "timeHistory" | "indicateNoData" | "onFiltersUpdated" | "savedQuery" | "showSaveQuery" | "onClearSavedQuery" | "showQueryBar" | "showFilterBar" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated">, any> & { + WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; }; // Warning: (ae-forgotten-export) The symbol "SearchBarOwnProps" needs to be exported by the entry point index.d.ts diff --git a/src/plugins/data/public/search/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor.test.ts index f890fdc3e30a3..e74581e9a6ffe 100644 --- a/src/plugins/data/public/search/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor.test.ts @@ -136,7 +136,7 @@ describe('SearchInterceptor', () => { await searchInterceptor.search(mockRequest, { sessionId }).toPromise(); expect(fetchMock.mock.calls[0][0]).toEqual( expect.objectContaining({ - options: { sessionId, isStored: true, isRestore: true }, + options: { sessionId, isStored: true, isRestore: true, strategy: 'es' }, }) ); diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index e3fb31c9179fd..f0df6f9216c0f 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -14,6 +14,7 @@ import { CoreStart, CoreSetup, ToastsSetup } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { BatchedFunc, BfetchPublicSetup } from 'src/plugins/bfetch/public'; import { + ES_SEARCH_STRATEGY, IKibanaSearchRequest, IKibanaSearchResponse, ISearchOptions, @@ -189,6 +190,11 @@ export class SearchInterceptor { request: IKibanaSearchRequest, options: ISearchOptions = {} ): Observable { + options = { + strategy: ES_SEARCH_STRATEGY, + ...options, + }; + // Defer the following logic until `subscribe` is actually called return defer(() => { if (options.abortSignal?.aborted) { diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index fa54f45d2feb2..c4e132e33fc3b 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -235,6 +235,8 @@ export { ISearchSessionService, SearchRequestHandlerContext, DataRequestHandlerContext, + AsyncSearchResponse, + AsyncSearchStatusResponse, } from './search'; // Search namespace diff --git a/src/plugins/data/server/search/README.md b/src/plugins/data/server/search/README.md index 33e6d9ab0bd1a..b564c34a7f8b3 100644 --- a/src/plugins/data/server/search/README.md +++ b/src/plugins/data/server/search/README.md @@ -5,9 +5,8 @@ object, and return a response object, of a given shape. Both client side search strategies can be registered, as well as server side search strategies. -The `search` plugin includes two one concrete client side implementations - - `SYNC_SEARCH_STRATEGY` and `ES_SEARCH_STRATEGY` which uses `SYNC_SEARCH_STRATEGY`. There is also one - default server side search strategy, `ES_SEARCH_STRATEGY`. +The `search` plugin includes: - Includes the `esSearch` plugin in order to search for data from Elasticsearch using Elasticsearch -DSL. +- ES_SEARCH_STRATEGY - hitting regular es `_search` endpoint using query DSL +- (default) ESE_SEARCH_STRATEGY (Enhanced ES) - hitting `_async_search` endpoint and works with search sessions +- EQL_SEARCH_STRATEGY diff --git a/src/plugins/data/server/search/index.ts b/src/plugins/data/server/search/index.ts index 0e09595f76a86..812f3171aef99 100644 --- a/src/plugins/data/server/search/index.ts +++ b/src/plugins/data/server/search/index.ts @@ -7,7 +7,9 @@ */ export * from './types'; -export * from './es_search'; +export * from './strategies/es_search'; +export * from './strategies/ese_search'; +export * from './strategies/eql_search'; export { usageProvider, SearchUsage, searchUsageObserver } from './collectors'; export * from './aggs'; export * from './session'; diff --git a/src/plugins/data/server/search/search_service.test.ts b/src/plugins/data/server/search/search_service.test.ts index d5a83efcc215f..52ee8e60a5b26 100644 --- a/src/plugins/data/server/search/search_service.test.ts +++ b/src/plugins/data/server/search/search_service.test.ts @@ -29,6 +29,7 @@ import { // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { expressionsPluginMock } from '../../../expressions/public/mocks'; import { createSearchSessionsClientMock } from './mocks'; +import { ENHANCED_ES_SEARCH_STRATEGY } from '../../common'; describe('Search service', () => { let plugin: SearchService; @@ -85,7 +86,7 @@ describe('Search service', () => { describe('asScopedProvider', () => { let mockScopedClient: IScopedSearchClient; - let searcPluginStart: ISearchStart>; + let searchPluginStart: ISearchStart>; let mockStrategy: any; let mockStrategyNoCancel: jest.Mocked; let mockSessionService: ISearchSessionService; @@ -112,21 +113,20 @@ describe('Search service', () => { bfetch: bfetchPluginMock.createSetupContract(), expressions: expressionsPluginMock.createSetupContract(), }); - pluginSetup.registerSearchStrategy('es', mockStrategy); + pluginSetup.registerSearchStrategy(ENHANCED_ES_SEARCH_STRATEGY, mockStrategy); pluginSetup.registerSearchStrategy('nocancel', mockStrategyNoCancel); pluginSetup.__enhance({ - defaultStrategy: 'es', sessionService: mockSessionService, }); - searcPluginStart = plugin.start(mockCoreStart, { + searchPluginStart = plugin.start(mockCoreStart, { fieldFormats: createFieldFormatsStartMock(), indexPatterns: createIndexPatternsStartMock(), }); const r: any = {}; - mockScopedClient = searcPluginStart.asScoped(r); + mockScopedClient = searchPluginStart.asScoped(r); }); describe('search', () => { @@ -269,7 +269,7 @@ describe('Search service', () => { it('cancels a saved object and search ids', async () => { const mockMap = new Map(); - mockMap.set('abc', 'es'); + mockMap.set('abc', ENHANCED_ES_SEARCH_STRATEGY); mockSessionClient.getSearchIdMapping = jest.fn().mockResolvedValue(mockMap); mockStrategy.cancel = jest.fn(); mockSessionClient.cancel = jest.fn().mockResolvedValue(mockSavedObject); @@ -281,13 +281,13 @@ describe('Search service', () => { const [searchId, options] = mockStrategy.cancel.mock.calls[0]; expect(mockStrategy.cancel).toHaveBeenCalledTimes(1); expect(searchId).toBe('abc'); - expect(options).toHaveProperty('strategy', 'es'); + expect(options).toHaveProperty('strategy', ENHANCED_ES_SEARCH_STRATEGY); }); it('cancels a saved object with some strategies that dont support cancellation, dont throw an error', async () => { const mockMap = new Map(); mockMap.set('abc', 'nocancel'); - mockMap.set('def', 'es'); + mockMap.set('def', ENHANCED_ES_SEARCH_STRATEGY); mockSessionClient.getSearchIdMapping = jest.fn().mockResolvedValue(mockMap); mockStrategy.cancel = jest.fn(); mockSessionClient.cancel = jest.fn().mockResolvedValue(mockSavedObject); @@ -299,13 +299,13 @@ describe('Search service', () => { const [searchId, options] = mockStrategy.cancel.mock.calls[0]; expect(mockStrategy.cancel).toHaveBeenCalledTimes(1); expect(searchId).toBe('def'); - expect(options).toHaveProperty('strategy', 'es'); + expect(options).toHaveProperty('strategy', ENHANCED_ES_SEARCH_STRATEGY); }); it('cancels a saved object with some strategies that dont exist, dont throw an error', async () => { const mockMap = new Map(); mockMap.set('abc', 'notsupported'); - mockMap.set('def', 'es'); + mockMap.set('def', ENHANCED_ES_SEARCH_STRATEGY); mockSessionClient.getSearchIdMapping = jest.fn().mockResolvedValue(mockMap); mockStrategy.cancel = jest.fn(); mockSessionClient.cancel = jest.fn().mockResolvedValue(mockSavedObject); @@ -317,7 +317,7 @@ describe('Search service', () => { const [searchId, options] = mockStrategy.cancel.mock.calls[0]; expect(mockStrategy.cancel).toHaveBeenCalledTimes(1); expect(searchId).toBe('def'); - expect(options).toHaveProperty('strategy', 'es'); + expect(options).toHaveProperty('strategy', ENHANCED_ES_SEARCH_STRATEGY); }); }); @@ -349,7 +349,7 @@ describe('Search service', () => { it('deletes a saved object and search ids', async () => { const mockMap = new Map(); - mockMap.set('abc', 'es'); + mockMap.set('abc', ENHANCED_ES_SEARCH_STRATEGY); mockSessionClient.getSearchIdMapping = jest.fn().mockResolvedValue(mockMap); mockSessionClient.delete = jest.fn().mockResolvedValue(mockSavedObject); mockStrategy.cancel = jest.fn(); @@ -361,13 +361,13 @@ describe('Search service', () => { const [searchId, options] = mockStrategy.cancel.mock.calls[0]; expect(mockStrategy.cancel).toHaveBeenCalledTimes(1); expect(searchId).toBe('abc'); - expect(options).toHaveProperty('strategy', 'es'); + expect(options).toHaveProperty('strategy', ENHANCED_ES_SEARCH_STRATEGY); }); it('deletes a saved object with some strategies that dont support cancellation, dont throw an error', async () => { const mockMap = new Map(); mockMap.set('abc', 'nocancel'); - mockMap.set('def', 'es'); + mockMap.set('def', ENHANCED_ES_SEARCH_STRATEGY); mockSessionClient.getSearchIdMapping = jest.fn().mockResolvedValue(mockMap); mockSessionClient.delete = jest.fn().mockResolvedValue(mockSavedObject); mockStrategy.cancel = jest.fn(); @@ -379,13 +379,13 @@ describe('Search service', () => { const [searchId, options] = mockStrategy.cancel.mock.calls[0]; expect(mockStrategy.cancel).toHaveBeenCalledTimes(1); expect(searchId).toBe('def'); - expect(options).toHaveProperty('strategy', 'es'); + expect(options).toHaveProperty('strategy', ENHANCED_ES_SEARCH_STRATEGY); }); it('deletes a saved object with some strategies that dont exist, dont throw an error', async () => { const mockMap = new Map(); mockMap.set('abc', 'notsupported'); - mockMap.set('def', 'es'); + mockMap.set('def', ENHANCED_ES_SEARCH_STRATEGY); mockSessionClient.getSearchIdMapping = jest.fn().mockResolvedValue(mockMap); mockStrategy.cancel = jest.fn(); mockSessionClient.delete = jest.fn().mockResolvedValue(mockSavedObject); @@ -397,7 +397,7 @@ describe('Search service', () => { const [searchId, options] = mockStrategy.cancel.mock.calls[0]; expect(mockStrategy.cancel).toHaveBeenCalledTimes(1); expect(searchId).toBe('def'); - expect(options).toHaveProperty('strategy', 'es'); + expect(options).toHaveProperty('strategy', ENHANCED_ES_SEARCH_STRATEGY); }); }); @@ -429,7 +429,7 @@ describe('Search service', () => { it('extends a saved object and search ids', async () => { const mockMap = new Map(); - mockMap.set('abc', 'es'); + mockMap.set('abc', ENHANCED_ES_SEARCH_STRATEGY); mockSessionClient.getSearchIdMapping = jest.fn().mockResolvedValue(mockMap); mockSessionClient.extend = jest.fn().mockResolvedValue(mockSavedObject); mockStrategy.extend = jest.fn(); @@ -441,13 +441,13 @@ describe('Search service', () => { const [searchId, keepAlive, options] = mockStrategy.extend.mock.calls[0]; expect(searchId).toBe('abc'); expect(keepAlive).toContain('ms'); - expect(options).toHaveProperty('strategy', 'es'); + expect(options).toHaveProperty('strategy', ENHANCED_ES_SEARCH_STRATEGY); }); it('doesnt extend the saved object with some strategies that dont support cancellation, throws an error', async () => { const mockMap = new Map(); mockMap.set('abc', 'nocancel'); - mockMap.set('def', 'es'); + mockMap.set('def', ENHANCED_ES_SEARCH_STRATEGY); mockSessionClient.getSearchIdMapping = jest.fn().mockResolvedValue(mockMap); mockSessionClient.extend = jest.fn().mockResolvedValue(mockSavedObject); mockStrategy.extend = jest.fn().mockResolvedValue({}); @@ -462,13 +462,13 @@ describe('Search service', () => { const [searchId, keepAlive, options] = mockStrategy.extend.mock.calls[0]; expect(searchId).toBe('def'); expect(keepAlive).toContain('ms'); - expect(options).toHaveProperty('strategy', 'es'); + expect(options).toHaveProperty('strategy', ENHANCED_ES_SEARCH_STRATEGY); }); it('doesnt extend the saved object with some strategies that dont exist, throws an error', async () => { const mockMap = new Map(); mockMap.set('abc', 'notsupported'); - mockMap.set('def', 'es'); + mockMap.set('def', ENHANCED_ES_SEARCH_STRATEGY); mockSessionClient.getSearchIdMapping = jest.fn().mockResolvedValue(mockMap); mockSessionClient.extend = jest.fn().mockResolvedValue(mockSavedObject); mockStrategy.extend = jest.fn().mockResolvedValue({}); @@ -483,7 +483,7 @@ describe('Search service', () => { const [searchId, keepAlive, options] = mockStrategy.extend.mock.calls[0]; expect(searchId).toBe('def'); expect(keepAlive).toContain('ms'); - expect(options).toHaveProperty('strategy', 'es'); + expect(options).toHaveProperty('strategy', ENHANCED_ES_SEARCH_STRATEGY); }); }); }); diff --git a/src/plugins/data/server/search/search_service.ts b/src/plugins/data/server/search/search_service.ts index e53244fa7ff26..0201f3226fd38 100644 --- a/src/plugins/data/server/search/search_service.ts +++ b/src/plugins/data/server/search/search_service.ts @@ -37,7 +37,7 @@ import { AggsService } from './aggs'; import { FieldFormatsStart } from '../field_formats'; import { IndexPatternsServiceStart } from '../index_patterns'; import { getCallMsearch, registerMsearchRoute, registerSearchRoute } from './routes'; -import { ES_SEARCH_STRATEGY, esSearchStrategyProvider } from './es_search'; +import { ES_SEARCH_STRATEGY, esSearchStrategyProvider } from './strategies/es_search'; import { DataPluginStart, DataPluginStartDependencies } from '../plugin'; import { UsageCollectionSetup } from '../../../usage_collection/server'; import { registerUsageCollector } from './collectors/register'; @@ -64,6 +64,8 @@ import { SearchSourceService, phraseFilterFunction, esRawResponse, + ENHANCED_ES_SEARCH_STRATEGY, + EQL_SEARCH_STRATEGY, } from '../../common/search'; import { getEsaggs, getEsdsl } from './expressions'; import { @@ -76,6 +78,8 @@ import { ISearchSessionService, SearchSessionService } from './session'; import { KbnServerError } from '../../../kibana_utils/server'; import { registerBsearchRoute } from './routes/bsearch'; import { getKibanaContext } from './expressions/kibana_context'; +import { enhancedEsSearchStrategyProvider } from './strategies/ese_search'; +import { eqlSearchStrategyProvider } from './strategies/eql_search'; type StrategyMap = Record>; @@ -101,7 +105,6 @@ export interface SearchRouteDependencies { export class SearchService implements Plugin { private readonly aggsService = new AggsService(); private readonly searchSourceService = new SearchSourceService(); - private defaultSearchStrategyName: string = ES_SEARCH_STRATEGY; private searchStrategies: StrategyMap = {}; private sessionService: ISearchSessionService; private asScoped!: ISearchStart['asScoped']; @@ -143,6 +146,17 @@ export class SearchService implements Plugin { ) ); + this.registerSearchStrategy( + ENHANCED_ES_SEARCH_STRATEGY, + enhancedEsSearchStrategyProvider( + this.initializerContext.config.legacy.globalConfig$, + this.logger, + usage + ) + ); + + this.registerSearchStrategy(EQL_SEARCH_STRATEGY, eqlSearchStrategyProvider(this.logger)); + registerBsearchRoute(bfetch, (request: KibanaRequest) => this.asScoped(request)); core.savedObjects.registerType(searchTelemetry); @@ -181,9 +195,6 @@ export class SearchService implements Plugin { return { __enhance: (enhancements: SearchEnhancements) => { - if (this.searchStrategies.hasOwnProperty(enhancements.defaultStrategy)) { - this.defaultSearchStrategyName = enhancements.defaultStrategy; - } this.sessionService = enhancements.sessionService; }, aggs, @@ -261,7 +272,7 @@ export class SearchService implements Plugin { SearchStrategyRequest extends IKibanaSearchRequest = IEsSearchRequest, SearchStrategyResponse extends IKibanaSearchResponse = IEsSearchResponse >( - name: string = this.defaultSearchStrategyName + name: string = ENHANCED_ES_SEARCH_STRATEGY ): ISearchStrategy => { this.logger.debug(`Get strategy ${name}`); const strategy = this.searchStrategies[name]; @@ -344,6 +355,7 @@ export class SearchService implements Plugin { strategy: strategyName, isStored: true, }; + return this.cancel(deps, searchId, searchOptions); }) ); diff --git a/src/plugins/data/server/search/session/mocks.ts b/src/plugins/data/server/search/session/mocks.ts index c173e1a1290ea..4deaecbf8056d 100644 --- a/src/plugins/data/server/search/session/mocks.ts +++ b/src/plugins/data/server/search/session/mocks.ts @@ -6,7 +6,9 @@ * Side Public License, v 1. */ +import moment from 'moment'; import { IScopedSearchSessionsClient } from './types'; +import { SearchSessionsConfigSchema } from '../../../config'; export function createSearchSessionsClientMock(): jest.Mocked< IScopedSearchSessionsClient @@ -22,5 +24,11 @@ export function createSearchSessionsClientMock(): jest.Mocked< cancel: jest.fn(), extend: jest.fn(), delete: jest.fn(), + getConfig: jest.fn( + () => + (({ + defaultExpiration: moment.duration('1', 'm'), + } as unknown) as SearchSessionsConfigSchema) + ), }; } diff --git a/src/plugins/data/server/search/session/session_service.ts b/src/plugins/data/server/search/session/session_service.ts index 2ed44b4e57d94..a23b315e47211 100644 --- a/src/plugins/data/server/search/session/session_service.ts +++ b/src/plugins/data/server/search/session/session_service.ts @@ -44,6 +44,9 @@ export class SearchSessionService implements ISearchSessionService { delete: async () => { throw new Error('delete not implemented in OSS search session service'); }, + getConfig: () => { + return null; + }, }); } } diff --git a/src/plugins/data/server/search/session/types.ts b/src/plugins/data/server/search/session/types.ts index 816716360415d..3083cc7d335e8 100644 --- a/src/plugins/data/server/search/session/types.ts +++ b/src/plugins/data/server/search/session/types.ts @@ -15,6 +15,7 @@ import { SavedObjectsUpdateResponse, } from 'kibana/server'; import { IKibanaSearchRequest, ISearchOptions } from '../../../common/search'; +import { SearchSessionsConfigSchema } from '../../../config'; export interface IScopedSearchSessionsClient { getId: (request: IKibanaSearchRequest, options: ISearchOptions) => Promise; @@ -31,6 +32,7 @@ export interface IScopedSearchSessionsClient { cancel: (sessionId: string) => Promise<{}>; delete: (sessionId: string) => Promise<{}>; extend: (sessionId: string, expires: Date) => Promise>; + getConfig: () => SearchSessionsConfigSchema | null; } export interface ISearchSessionService { diff --git a/x-pack/plugins/data_enhanced/server/search/eql_search_strategy.test.ts b/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.test.ts similarity index 95% rename from x-pack/plugins/data_enhanced/server/search/eql_search_strategy.test.ts rename to src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.test.ts index b7f10f0a5388c..85ac5d8d17992 100644 --- a/x-pack/plugins/data_enhanced/server/search/eql_search_strategy.test.ts +++ b/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.test.ts @@ -1,14 +1,15 @@ /* * 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 type { Logger } from 'kibana/server'; -import { EqlSearchStrategyRequest } from '../../common/search/types'; import { eqlSearchStrategyProvider } from './eql_search_strategy'; -import { SearchStrategyDependencies } from '../../../../../src/plugins/data/server'; +import { SearchStrategyDependencies } from '../../types'; +import { EqlSearchStrategyRequest } from '../../../../common'; const getMockEqlResponse = () => ({ body: { diff --git a/x-pack/plugins/data_enhanced/server/search/eql_search_strategy.ts b/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.ts similarity index 84% rename from x-pack/plugins/data_enhanced/server/search/eql_search_strategy.ts rename to src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.ts index 9c1bedc4d5f1c..0e3acedfe12f6 100644 --- a/x-pack/plugins/data_enhanced/server/search/eql_search_strategy.ts +++ b/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.ts @@ -1,23 +1,25 @@ /* * 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 type { ApiResponse } from '@elastic/elasticsearch'; import { tap } from 'rxjs/operators'; import type { IScopedClusterClient, Logger } from 'kibana/server'; -import type { ISearchStrategy } from '../../../../../src/plugins/data/server'; -import type { +import { EqlSearchStrategyRequest, EqlSearchStrategyResponse, IAsyncSearchOptions, -} from '../../common'; -import { getDefaultSearchParams, shimAbortSignal } from '../../../../../src/plugins/data/server'; -import { pollSearch } from '../../common'; -import { getDefaultAsyncGetParams, getIgnoreThrottled } from './request_utils'; + pollSearch, +} from '../../../../common'; import { toEqlKibanaSearchResponse } from './response_utils'; import { EqlSearchResponse } from './types'; +import { ISearchStrategy } from '../../types'; +import { getDefaultSearchParams, shimAbortSignal } from '../es_search'; +import { getDefaultAsyncGetParams, getIgnoreThrottled } from '../ese_search/request_utils'; export const eqlSearchStrategyProvider = ( logger: Logger diff --git a/src/plugins/data/server/search/strategies/eql_search/index.ts b/src/plugins/data/server/search/strategies/eql_search/index.ts new file mode 100644 index 0000000000000..ee7b8cb7eaeb4 --- /dev/null +++ b/src/plugins/data/server/search/strategies/eql_search/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 { eqlSearchStrategyProvider } from './eql_search_strategy'; diff --git a/x-pack/plugins/data_enhanced/server/search/response_utils.ts b/src/plugins/data/server/search/strategies/eql_search/response_utils.ts similarity index 50% rename from x-pack/plugins/data_enhanced/server/search/response_utils.ts rename to src/plugins/data/server/search/strategies/eql_search/response_utils.ts index c601109b3da27..11b5a286e709d 100644 --- a/x-pack/plugins/data_enhanced/server/search/response_utils.ts +++ b/src/plugins/data/server/search/strategies/eql_search/response_utils.ts @@ -1,27 +1,14 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 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 { ApiResponse } from '@elastic/elasticsearch'; -import { getTotalLoaded } from '../../../../../src/plugins/data/server'; -import { AsyncSearchResponse, EqlSearchResponse } from './types'; -import { EqlSearchStrategyResponse } from '../../common/search'; - -/** - * Get the Kibana representation of an async search response (see `IKibanaSearchResponse`). - */ -export function toAsyncKibanaSearchResponse(response: AsyncSearchResponse) { - return { - id: response.id, - rawResponse: response.response, - isPartial: response.is_partial, - isRunning: response.is_running, - ...getTotalLoaded(response.response), - }; -} +import { EqlSearchResponse } from './types'; +import { EqlSearchStrategyResponse } from '../../../../common'; /** * Get the Kibana representation of an EQL search response (see `IKibanaSearchResponse`). diff --git a/src/plugins/data/server/search/strategies/eql_search/types.ts b/src/plugins/data/server/search/strategies/eql_search/types.ts new file mode 100644 index 0000000000000..4b3c19fda78ea --- /dev/null +++ b/src/plugins/data/server/search/strategies/eql_search/types.ts @@ -0,0 +1,15 @@ +/* + * 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 type { estypes } from '@elastic/elasticsearch'; + +export interface EqlSearchResponse extends estypes.SearchResponse { + id?: string; + is_partial: boolean; + is_running: boolean; +} diff --git a/src/plugins/data/server/search/es_search/elasticsearch.ts b/src/plugins/data/server/search/strategies/es_search/elasticsearch.ts similarity index 100% rename from src/plugins/data/server/search/es_search/elasticsearch.ts rename to src/plugins/data/server/search/strategies/es_search/elasticsearch.ts diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.test.ts b/src/plugins/data/server/search/strategies/es_search/es_search_strategy.test.ts similarity index 95% rename from src/plugins/data/server/search/es_search/es_search_strategy.test.ts rename to src/plugins/data/server/search/strategies/es_search/es_search_strategy.test.ts index db21d67a33737..c2280737d2496 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.test.ts +++ b/src/plugins/data/server/search/strategies/es_search/es_search_strategy.test.ts @@ -10,14 +10,14 @@ import { elasticsearchClientMock, MockedTransportRequestPromise, // eslint-disable-next-line @kbn/eslint/no-restricted-paths -} from '../../../../../core/server/elasticsearch/client/mocks'; -import { pluginInitializerContextConfigMock } from '../../../../../core/server/mocks'; +} from '../../../../../../core/server/elasticsearch/client/mocks'; +import { pluginInitializerContextConfigMock } from '../../../../../../core/server/mocks'; import { esSearchStrategyProvider } from './es_search_strategy'; -import { SearchStrategyDependencies } from '../types'; +import { SearchStrategyDependencies } from '../../types'; -import * as indexNotFoundException from '../../../common/search/test_data/index_not_found_exception.json'; +import * as indexNotFoundException from '../../../../common/search/test_data/index_not_found_exception.json'; import { ElasticsearchClientError, ResponseError } from '@elastic/elasticsearch/lib/errors'; -import { KbnServerError } from '../../../../kibana_utils/server'; +import { KbnServerError } from '../../../../../kibana_utils/server'; describe('ES search strategy', () => { const successBody = { diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.ts b/src/plugins/data/server/search/strategies/es_search/es_search_strategy.ts similarity index 88% rename from src/plugins/data/server/search/es_search/es_search_strategy.ts rename to src/plugins/data/server/search/strategies/es_search/es_search_strategy.ts index 1afe627545248..c24aa37082bd8 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.ts +++ b/src/plugins/data/server/search/strategies/es_search/es_search_strategy.ts @@ -9,12 +9,12 @@ import { from, Observable } from 'rxjs'; import { first, tap } from 'rxjs/operators'; import type { Logger, SharedGlobalConfig } from 'kibana/server'; -import type { ISearchStrategy } from '../types'; -import type { SearchUsage } from '../collectors'; +import type { ISearchStrategy } from '../../types'; +import type { SearchUsage } from '../../collectors'; import { getDefaultSearchParams, getShardTimeout, shimAbortSignal } from './request_utils'; import { shimHitsTotal, toKibanaSearchResponse } from './response_utils'; -import { searchUsageObserver } from '../collectors/usage'; -import { getKbnServerError, KbnServerError } from '../../../../kibana_utils/server'; +import { searchUsageObserver } from '../../collectors/usage'; +import { getKbnServerError, KbnServerError } from '../../../../../kibana_utils/server'; export const esSearchStrategyProvider = ( config$: Observable, diff --git a/src/plugins/data/server/search/es_search/index.ts b/src/plugins/data/server/search/strategies/es_search/index.ts similarity index 94% rename from src/plugins/data/server/search/es_search/index.ts rename to src/plugins/data/server/search/strategies/es_search/index.ts index 6c1a88ad48431..d43fab0a86e69 100644 --- a/src/plugins/data/server/search/es_search/index.ts +++ b/src/plugins/data/server/search/strategies/es_search/index.ts @@ -9,4 +9,4 @@ export { esSearchStrategyProvider } from './es_search_strategy'; export * from './request_utils'; export * from './response_utils'; -export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common'; +export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../../common'; diff --git a/src/plugins/data/server/search/es_search/request_utils.test.ts b/src/plugins/data/server/search/strategies/es_search/request_utils.test.ts similarity index 100% rename from src/plugins/data/server/search/es_search/request_utils.test.ts rename to src/plugins/data/server/search/strategies/es_search/request_utils.test.ts diff --git a/src/plugins/data/server/search/es_search/request_utils.ts b/src/plugins/data/server/search/strategies/es_search/request_utils.ts similarity index 97% rename from src/plugins/data/server/search/es_search/request_utils.ts rename to src/plugins/data/server/search/strategies/es_search/request_utils.ts index 30f1d15fbf91b..829497929c20f 100644 --- a/src/plugins/data/server/search/es_search/request_utils.ts +++ b/src/plugins/data/server/search/strategies/es_search/request_utils.ts @@ -9,7 +9,7 @@ import type { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; import type { Search } from '@elastic/elasticsearch/api/requestParams'; import type { IUiSettingsClient, SharedGlobalConfig } from 'kibana/server'; -import { UI_SETTINGS } from '../../../common'; +import { UI_SETTINGS } from '../../../../common'; export function getShardTimeout(config: SharedGlobalConfig): Pick { const timeout = config.elasticsearch.shardTimeout.asMilliseconds(); diff --git a/src/plugins/data/server/search/es_search/response_utils.test.ts b/src/plugins/data/server/search/strategies/es_search/response_utils.test.ts similarity index 100% rename from src/plugins/data/server/search/es_search/response_utils.test.ts rename to src/plugins/data/server/search/strategies/es_search/response_utils.test.ts diff --git a/src/plugins/data/server/search/es_search/response_utils.ts b/src/plugins/data/server/search/strategies/es_search/response_utils.ts similarity index 96% rename from src/plugins/data/server/search/es_search/response_utils.ts rename to src/plugins/data/server/search/strategies/es_search/response_utils.ts index 3bee63624ef67..0553c015fb2da 100644 --- a/src/plugins/data/server/search/es_search/response_utils.ts +++ b/src/plugins/data/server/search/strategies/es_search/response_utils.ts @@ -7,7 +7,7 @@ */ import type { estypes } from '@elastic/elasticsearch'; -import { ISearchOptions } from '../../../common'; +import { ISearchOptions } from '../../../../common'; /** * Get the `total`/`loaded` for this response (see `IKibanaSearchResponse`). Note that `skipped` is diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts b/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.test.ts similarity index 81% rename from x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts rename to src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.test.ts index 2ae79f4e144e0..216318339622f 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts +++ b/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.test.ts @@ -1,18 +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. + * 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 { enhancedEsSearchStrategyProvider } from './es_search_strategy'; import { BehaviorSubject } from 'rxjs'; -import { SearchStrategyDependencies } from '../../../../../src/plugins/data/server/search'; -import moment from 'moment'; -import { KbnServerError } from '../../../../../src/plugins/kibana_utils/server'; +import { KbnServerError } from '../../../../../kibana_utils/server'; import { ElasticsearchClientError, ResponseError } from '@elastic/elasticsearch/lib/errors'; -import * as indexNotFoundException from '../../../../../src/plugins/data/common/search/test_data/index_not_found_exception.json'; -import * as xContentParseException from '../../../../../src/plugins/data/common/search/test_data/x_content_parse_exception.json'; +import * as indexNotFoundException from '../../../../common/search/test_data/index_not_found_exception.json'; +import * as xContentParseException from '../../../../common/search/test_data/x_content_parse_exception.json'; +import { SearchStrategyDependencies } from '../../types'; +import { enhancedEsSearchStrategyProvider } from './ese_search_strategy'; +import { createSearchSessionsClientMock } from '../../mocks'; const mockAsyncResponse = { body: { @@ -61,6 +62,7 @@ describe('ES search strategy', () => { transport: { request: mockApiCaller }, }, }, + searchSessionsClient: createSearchSessionsClientMock(), } as unknown) as SearchStrategyDependencies; const mockLegacyConfig$ = new BehaviorSubject({ elasticsearch: { @@ -72,14 +74,6 @@ describe('ES search strategy', () => { }, }); - const mockConfig: any = { - search: { - sessions: { - defaultExpiration: moment.duration('1', 'm'), - }, - }, - }; - beforeEach(() => { mockApiCaller.mockClear(); mockGetCaller.mockClear(); @@ -88,11 +82,7 @@ describe('ES search strategy', () => { }); it('returns a strategy with `search and `cancel`', async () => { - const esSearch = await enhancedEsSearchStrategyProvider( - mockConfig, - mockLegacyConfig$, - mockLogger - ); + const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); expect(typeof esSearch.search).toBe('function'); }); @@ -103,11 +93,7 @@ describe('ES search strategy', () => { mockSubmitCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider( - mockConfig, - mockLegacyConfig$, - mockLogger - ); + const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); await esSearch.search({ params }, {}, mockDeps).toPromise(); @@ -122,11 +108,7 @@ describe('ES search strategy', () => { mockGetCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider( - mockConfig, - mockLegacyConfig$, - mockLogger - ); + const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); await esSearch.search({ id: 'foo', params }, {}, mockDeps).toPromise(); @@ -141,11 +123,7 @@ describe('ES search strategy', () => { mockSubmitCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'foo-*', body: {} }; - const esSearch = await enhancedEsSearchStrategyProvider( - mockConfig, - mockLegacyConfig$, - mockLogger - ); + const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); await esSearch.search({ params }, {}, mockDeps).toPromise(); @@ -159,11 +137,7 @@ describe('ES search strategy', () => { mockApiCaller.mockResolvedValueOnce(mockRollupResponse); const params = { index: 'foo-程', body: {} }; - const esSearch = await enhancedEsSearchStrategyProvider( - mockConfig, - mockLegacyConfig$, - mockLogger - ); + const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); await esSearch .search( @@ -188,11 +162,7 @@ describe('ES search strategy', () => { mockSubmitCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider( - mockConfig, - mockLegacyConfig$, - mockLogger - ); + const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); await esSearch.search({ params }, { sessionId: '1' }, mockDeps).toPromise(); @@ -208,11 +178,7 @@ describe('ES search strategy', () => { mockGetCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider( - mockConfig, - mockLegacyConfig$, - mockLogger - ); + const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); await esSearch.search({ id: 'foo', params }, { sessionId: '1' }, mockDeps).toPromise(); @@ -236,11 +202,7 @@ describe('ES search strategy', () => { mockSubmitCaller.mockRejectedValue(errResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider( - mockConfig, - mockLegacyConfig$, - mockLogger - ); + const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); let err: KbnServerError | undefined; try { @@ -261,11 +223,7 @@ describe('ES search strategy', () => { mockSubmitCaller.mockRejectedValue(errResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider( - mockConfig, - mockLegacyConfig$, - mockLogger - ); + const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); let err: KbnServerError | undefined; try { @@ -286,11 +244,7 @@ describe('ES search strategy', () => { mockDeleteCaller.mockResolvedValueOnce(200); const id = 'some_id'; - const esSearch = await enhancedEsSearchStrategyProvider( - mockConfig, - mockLegacyConfig$, - mockLogger - ); + const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); await esSearch.cancel!(id, {}, mockDeps); @@ -310,11 +264,7 @@ describe('ES search strategy', () => { mockDeleteCaller.mockRejectedValue(errResponse); const id = 'some_id'; - const esSearch = await enhancedEsSearchStrategyProvider( - mockConfig, - mockLegacyConfig$, - mockLogger - ); + const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); let err: KbnServerError | undefined; try { @@ -337,11 +287,7 @@ describe('ES search strategy', () => { const id = 'some_other_id'; const keepAlive = '1d'; - const esSearch = await enhancedEsSearchStrategyProvider( - mockConfig, - mockLegacyConfig$, - mockLogger - ); + const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); await esSearch.extend!(id, keepAlive, {}, mockDeps); @@ -356,11 +302,7 @@ describe('ES search strategy', () => { const id = 'some_other_id'; const keepAlive = '1d'; - const esSearch = await enhancedEsSearchStrategyProvider( - mockConfig, - mockLegacyConfig$, - mockLogger - ); + const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); let err: KbnServerError | undefined; try { diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts b/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.ts similarity index 87% rename from x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts rename to src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.ts index aec2e7bd533ec..e7f5005e7e837 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts +++ b/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.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 type { Observable } from 'rxjs'; @@ -10,35 +11,31 @@ import type { IScopedClusterClient, Logger, SharedGlobalConfig } from 'kibana/se import { catchError, first, tap } from 'rxjs/operators'; import { SearchResponse } from 'elasticsearch'; import { from } from 'rxjs'; +import type { ISearchStrategy, SearchStrategyDependencies } from '../../types'; import type { + IAsyncSearchOptions, IEsSearchRequest, IEsSearchResponse, ISearchOptions, - ISearchStrategy, - SearchStrategyDependencies, - SearchUsage, -} from '../../../../../src/plugins/data/server'; -import { - getDefaultSearchParams, - getShardTimeout, - getTotalLoaded, - searchUsageObserver, - shimAbortSignal, - shimHitsTotal, -} from '../../../../../src/plugins/data/server'; -import type { IAsyncSearchOptions } from '../../common'; -import { pollSearch } from '../../common'; +} from '../../../../common'; +import { pollSearch } from '../../../../common'; import { getDefaultAsyncGetParams, getDefaultAsyncSubmitParams, getIgnoreThrottled, } from './request_utils'; import { toAsyncKibanaSearchResponse } from './response_utils'; -import { ConfigSchema } from '../../config'; -import { getKbnServerError, KbnServerError } from '../../../../../src/plugins/kibana_utils/server'; +import { getKbnServerError, KbnServerError } from '../../../../../kibana_utils/server'; +import { SearchUsage, searchUsageObserver } from '../../collectors'; +import { + getDefaultSearchParams, + getShardTimeout, + getTotalLoaded, + shimAbortSignal, + shimHitsTotal, +} from '../es_search'; export const enhancedEsSearchStrategyProvider = ( - config: ConfigSchema, legacyConfig$: Observable, logger: Logger, usage?: SearchUsage @@ -54,7 +51,7 @@ export const enhancedEsSearchStrategyProvider = ( function asyncSearch( { id, ...request }: IEsSearchRequest, options: IAsyncSearchOptions, - { esClient, uiSettingsClient }: SearchStrategyDependencies + { esClient, uiSettingsClient, searchSessionsClient }: SearchStrategyDependencies ) { const client = esClient.asCurrentUser.asyncSearch; @@ -62,7 +59,11 @@ export const enhancedEsSearchStrategyProvider = ( const params = id ? getDefaultAsyncGetParams(options) : { - ...(await getDefaultAsyncSubmitParams(uiSettingsClient, config, options)), + ...(await getDefaultAsyncSubmitParams( + uiSettingsClient, + searchSessionsClient.getConfig(), + options + )), ...request.params, }; const promise = id ? client.get({ ...params, id }) : client.submit(params); diff --git a/src/plugins/data/server/search/strategies/ese_search/index.ts b/src/plugins/data/server/search/strategies/ese_search/index.ts new file mode 100644 index 0000000000000..3129b53f6c9ca --- /dev/null +++ b/src/plugins/data/server/search/strategies/ese_search/index.ts @@ -0,0 +1,10 @@ +/* + * 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 { enhancedEsSearchStrategyProvider } from './ese_search_strategy'; +export * from './types'; diff --git a/x-pack/plugins/data_enhanced/server/search/request_utils.ts b/src/plugins/data/server/search/strategies/ese_search/request_utils.ts similarity index 70% rename from x-pack/plugins/data_enhanced/server/search/request_utils.ts rename to src/plugins/data/server/search/strategies/ese_search/request_utils.ts index 7a4e912fa0672..70da0ba2edcc3 100644 --- a/x-pack/plugins/data_enhanced/server/search/request_utils.ts +++ b/src/plugins/data/server/search/strategies/ese_search/request_utils.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 { IUiSettingsClient } from 'kibana/server'; @@ -11,9 +12,9 @@ import { AsyncSearchSubmit, Search, } from '@elastic/elasticsearch/api/requestParams'; -import { ISearchOptions, UI_SETTINGS } from '../../../../../src/plugins/data/common'; -import { getDefaultSearchParams } from '../../../../../src/plugins/data/server'; -import { ConfigSchema } from '../../config'; +import { ISearchOptions, UI_SETTINGS } from '../../../../common'; +import { getDefaultSearchParams } from '../es_search'; +import { SearchSessionsConfigSchema } from '../../../../config'; /** * @internal @@ -30,7 +31,7 @@ export async function getIgnoreThrottled( */ export async function getDefaultAsyncSubmitParams( uiSettingsClient: IUiSettingsClient, - config: ConfigSchema, + searchSessionsConfig: SearchSessionsConfigSchema | null, options: ISearchOptions ): Promise< Pick< @@ -53,7 +54,11 @@ export async function getDefaultAsyncSubmitParams( ...(await getDefaultSearchParams(uiSettingsClient)), ...(options.sessionId ? { - keep_alive: `${config.search.sessions.defaultExpiration.asMilliseconds()}ms`, + // TODO: searchSessionsConfig could be "null" if we are running without x-pack which happens only in tests. + // This can be cleaned up when we completely stop separating basic and oss + keep_alive: searchSessionsConfig + ? `${searchSessionsConfig.defaultExpiration.asMilliseconds()}ms` + : '1m', } : {}), }; diff --git a/src/plugins/data/server/search/strategies/ese_search/response_utils.ts b/src/plugins/data/server/search/strategies/ese_search/response_utils.ts new file mode 100644 index 0000000000000..ae3d258e2205d --- /dev/null +++ b/src/plugins/data/server/search/strategies/ese_search/response_utils.ts @@ -0,0 +1,23 @@ +/* + * 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 { AsyncSearchResponse } from './types'; +import { getTotalLoaded } from '../es_search'; + +/** + * Get the Kibana representation of an async search response (see `IKibanaSearchResponse`). + */ +export function toAsyncKibanaSearchResponse(response: AsyncSearchResponse) { + return { + id: response.id, + rawResponse: response.response, + isPartial: response.is_partial, + isRunning: response.is_running, + ...getTotalLoaded(response.response), + }; +} diff --git a/x-pack/plugins/data_enhanced/server/search/types.ts b/src/plugins/data/server/search/strategies/ese_search/types.ts similarity index 67% rename from x-pack/plugins/data_enhanced/server/search/types.ts rename to src/plugins/data/server/search/strategies/ese_search/types.ts index e2a4e2ce74f15..069004b0287cd 100644 --- a/x-pack/plugins/data_enhanced/server/search/types.ts +++ b/src/plugins/data/server/search/strategies/ese_search/types.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 type { estypes } from '@elastic/elasticsearch'; -import { SearchResponse, ShardsResponse } from 'elasticsearch'; +import { ShardsResponse } from 'elasticsearch'; export interface AsyncSearchResponse { id?: string; @@ -20,9 +21,3 @@ export interface AsyncSearchStatusResponse extends Omit extends SearchResponse { - id?: string; - is_partial: boolean; - is_running: boolean; -} diff --git a/src/plugins/data/server/search/types.ts b/src/plugins/data/server/search/types.ts index e8548257c0167..229c581bf09f1 100644 --- a/src/plugins/data/server/search/types.ts +++ b/src/plugins/data/server/search/types.ts @@ -21,14 +21,14 @@ import { IKibanaSearchRequest, IKibanaSearchResponse, ISearchClient, + IEsSearchResponse, + IEsSearchRequest, } from '../../common/search'; import { AggsSetup, AggsStart } from './aggs'; import { SearchUsage } from './collectors'; -import { IEsSearchRequest, IEsSearchResponse } from './es_search'; import { IScopedSearchSessionsClient, ISearchSessionService } from './session'; export interface SearchEnhancements { - defaultStrategy: string; sessionService: ISearchSessionService; } diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 09cc6fca4f4a7..7e840be2c87d8 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -68,6 +68,7 @@ import { SavedObjectsFindResponse } from 'kibana/server'; import { SavedObjectsUpdateResponse } from 'kibana/server'; import { Search } from '@elastic/elasticsearch/api/requestParams'; import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/common'; +import { ShardsResponse } from 'elasticsearch'; import { SharedGlobalConfig as SharedGlobalConfig_2 } from 'kibana/server'; import { ToastInputFields } from 'src/core/public/notifications'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; @@ -281,6 +282,34 @@ export class AggParamType extends Ba makeAgg: (agg: TAggConfig, state?: AggConfigSerialized) => TAggConfig; } +// Warning: (ae-missing-release-tag) "AsyncSearchResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface AsyncSearchResponse { + // (undocumented) + expiration_time_in_millis: number; + // (undocumented) + id?: string; + // (undocumented) + is_partial: boolean; + // (undocumented) + is_running: boolean; + // (undocumented) + response: estypes.SearchResponse; + // (undocumented) + start_time_in_millis: number; +} + +// Warning: (ae-missing-release-tag) "AsyncSearchStatusResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface AsyncSearchStatusResponse extends Omit { + // (undocumented) + completion_status: number; + // (undocumented) + _shards: ShardsResponse; +} + // Warning: (ae-missing-release-tag) "BUCKET_TYPES" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1361,6 +1390,7 @@ export class SearchSessionService implements ISearchSessionService { extend: () => Promise; cancel: () => Promise; delete: () => Promise; + getConfig: () => null; }; } @@ -1518,18 +1548,18 @@ export function usageProvider(core: CoreSetup_2): SearchUsage; // src/plugins/data/server/index.ts:101:26 - (ae-forgotten-export) The symbol "HistogramFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:128:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:128:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:241:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:241:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:243:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:244:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:253:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:254:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:255:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:259:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:260:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:264:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:267:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:268:1 - (ae-forgotten-export) The symbol "calcAutoIntervalLessThan" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:243:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:243:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:245:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:246:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:255:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:256:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:257:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:261:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:262:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:266:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:269:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:270:1 - (ae-forgotten-export) The symbol "calcAutoIntervalLessThan" needs to be exported by the entry point index.d.ts // src/plugins/data/server/plugin.ts:81:74 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts // src/plugins/data/server/search/types.ts:114:5 - (ae-forgotten-export) The symbol "ISearchStartSearchSource" needs to be exported by the entry point index.d.ts diff --git a/test/api_integration/apis/search/bsearch.ts b/test/api_integration/apis/search/bsearch.ts index 89fe606857c1c..d0322624778ae 100644 --- a/test/api_integration/apis/search/bsearch.ts +++ b/test/api_integration/apis/search/bsearch.ts @@ -116,7 +116,7 @@ export default function ({ getService }: FtrProviderContext) { }); }); - it('should return 400 when index type is provided in OSS', async () => { + it('should return 400 when index type is provided in "es" strategy', async () => { const resp = await supertest.post(`/internal/bsearch`).send({ batch: [ { @@ -130,6 +130,9 @@ export default function ({ getService }: FtrProviderContext) { }, }, }, + options: { + strategy: 'es', + }, }, ], }); @@ -151,11 +154,14 @@ export default function ({ getService }: FtrProviderContext) { after(async () => { await esArchiver.unload('../../../functional/fixtures/es_archiver/logstash_functional'); }); - it('should return 400 for Painless error', async () => { + it('should return 400 "search_phase_execution_exception" for Painless error in "es" strategy', async () => { const resp = await supertest.post(`/internal/bsearch`).send({ batch: [ { request: painlessErrReq, + options: { + strategy: 'es', + }, }, ], }); diff --git a/x-pack/plugins/data_enhanced/README.md b/x-pack/plugins/data_enhanced/README.md index 8f3ae7ac3cd13..fba484261fea2 100644 --- a/x-pack/plugins/data_enhanced/README.md +++ b/x-pack/plugins/data_enhanced/README.md @@ -1,25 +1,16 @@ # data_enhanced -The `data_enhanced` plugin is the x-pack counterpart to the OSS `data` plugin. +The `data_enhanced` plugin is the x-pack counterpart to the `src/plguins/data` plugin. -It exists to provide Elastic-licensed services, or parts of services, which -enhance existing OSS functionality from `data`. +It exists to provide services, or parts of services, which +enhance existing functionality from `src/plugins/data`. -Currently the `data_enhanced` plugin doesn't return any APIs which you can +Currently, the `data_enhanced` plugin doesn't return any APIs which you can consume directly, however it is possible that you are indirectly relying on the -enhanced functionality that it provides via the OSS `data` plugin. +enhanced functionality that it provides via the `data` plugin from `src/`. Here is the functionality it adds: -## KQL Autocomplete - -The OSS autocomplete service provides suggestions for field names and values -based on suggestion providers which are registered to the service. This plugin -registers the autocomplete provider for KQL to the OSS service. - -## Async, Rollup, and EQL Search Strategies - -This plugin enhances the OSS search service with an ES search strategy that -uses async search (or rollups) behind the scenes. It also registers an EQL -search strategy. +## Search Sessions +Search sessions are handy when you want to enable a user to run something asynchronously (for example, a dashboard over a long period of time), and then quickly restore the results at a later time. The Search Service transparently fetches results from the .async-search index, instead of running each request again. diff --git a/x-pack/plugins/data_enhanced/common/index.ts b/x-pack/plugins/data_enhanced/common/index.ts index 22dd62914b57f..1fec1c76430eb 100644 --- a/x-pack/plugins/data_enhanced/common/index.ts +++ b/x-pack/plugins/data_enhanced/common/index.ts @@ -4,17 +4,3 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -export { - SEARCH_SESSION_TYPE, - ENHANCED_ES_SEARCH_STRATEGY, - EQL_SEARCH_STRATEGY, - EqlRequestParams, - EqlSearchStrategyRequest, - EqlSearchStrategyResponse, - IAsyncSearchOptions, - pollSearch, - SearchSessionSavedObjectAttributes, - SearchSessionStatus, - SearchSessionRequestInfo, -} from './search'; diff --git a/x-pack/plugins/data_enhanced/common/search/index.ts b/x-pack/plugins/data_enhanced/common/search/index.ts index f69d66e64dc2f..1fec1c76430eb 100644 --- a/x-pack/plugins/data_enhanced/common/search/index.ts +++ b/x-pack/plugins/data_enhanced/common/search/index.ts @@ -4,7 +4,3 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -export * from './types'; -export * from './poll_search'; -export * from './session'; diff --git a/x-pack/plugins/data_enhanced/common/search/session/index.ts b/x-pack/plugins/data_enhanced/common/search/session/index.ts deleted file mode 100644 index bc09a1e0351e3..0000000000000 --- a/x-pack/plugins/data_enhanced/common/search/session/index.ts +++ /dev/null @@ -1,16 +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. - */ - -// TODO https://github.com/elastic/kibana/issues/92802 -export { - SEARCH_SESSION_TYPE, - SearchSessionSavedObjectAttributes, - SearchSessionFindOptions, - SearchSessionRequestInfo, - SearchSessionStatus, - SEARCH_SESSIONS_TABLE_ID, -} from '../../../../../../src/plugins/data/common/'; diff --git a/x-pack/plugins/data_enhanced/common/search/session/status.ts b/x-pack/plugins/data_enhanced/common/search/session/status.ts deleted file mode 100644 index 97582338646e7..0000000000000 --- a/x-pack/plugins/data_enhanced/common/search/session/status.ts +++ /dev/null @@ -1,14 +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 enum SearchSessionStatus { - IN_PROGRESS = 'in_progress', - ERROR = 'error', - COMPLETE = 'complete', - CANCELLED = 'cancelled', - EXPIRED = 'expired', -} diff --git a/x-pack/plugins/data_enhanced/common/search/session/types.ts b/x-pack/plugins/data_enhanced/common/search/session/types.ts deleted file mode 100644 index 788ab30756e1c..0000000000000 --- a/x-pack/plugins/data_enhanced/common/search/session/types.ts +++ /dev/null @@ -1,93 +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 { SearchSessionStatus } from './'; - -export const SEARCH_SESSION_TYPE = 'search-session'; -export interface SearchSessionSavedObjectAttributes { - sessionId: string; - /** - * User-facing session name to be displayed in session management - */ - name?: string; - /** - * App that created the session. e.g 'discover' - */ - appId?: string; - /** - * Creation time of the session - */ - created: string; - /** - * Last touch time of the session - */ - touched: string; - /** - * Expiration time of the session. Expiration itself is managed by Elasticsearch. - */ - expires: string; - /** - * status - */ - status: SearchSessionStatus; - /** - * urlGeneratorId - */ - urlGeneratorId?: string; - /** - * The application state that was used to create the session. - * Should be used, for example, to re-load an expired search session. - */ - initialState?: Record; - /** - * Application state that should be used to restore the session. - * For example, relative dates are conveted to absolute ones. - */ - restoreState?: Record; - /** - * Mapping of search request hashes to their corresponsing info (async search id, etc.) - */ - idMapping: Record; - - /** - * This value is true if the session was actively stored by the user. If it is false, the session may be purged by the system. - */ - persisted: boolean; - /** - * The realm type/name & username uniquely identifies the user who created this search session - */ - realmType?: string; - realmName?: string; - username?: string; -} - -export interface SearchSessionRequestInfo { - /** - * ID of the async search request - */ - id: string; - /** - * Search strategy used to submit the search request - */ - strategy: string; - /** - * status - */ - status: string; - /** - * An optional error. Set if status is set to error. - */ - error?: string; -} - -export interface SearchSessionFindOptions { - page?: number; - perPage?: number; - sortField?: string; - sortOrder?: string; - filter?: string; -} diff --git a/x-pack/plugins/data_enhanced/config.ts b/x-pack/plugins/data_enhanced/config.ts index c895e586a6931..e08381316a29c 100644 --- a/x-pack/plugins/data_enhanced/config.ts +++ b/x-pack/plugins/data_enhanced/config.ts @@ -6,64 +6,11 @@ */ import { schema, TypeOf } from '@kbn/config-schema'; +import { searchSessionsConfigSchema } from '../../../src/plugins/data/config'; export const configSchema = schema.object({ search: schema.object({ - sessions: schema.object({ - /** - * Turns the feature on \ off (incl. removing indicator and management screens) - */ - enabled: schema.boolean({ defaultValue: true }), - /** - * pageSize controls how many search session objects we load at once while monitoring - * session completion - */ - pageSize: schema.number({ defaultValue: 100 }), - /** - * trackingInterval controls how often we track search session objects progress - */ - trackingInterval: schema.duration({ defaultValue: '10s' }), - - /** - * monitoringTaskTimeout controls for how long task manager waits for search session monitoring task to complete before considering it timed out, - * If tasks timeouts it receives cancel signal and next task starts in "trackingInterval" time - */ - monitoringTaskTimeout: schema.duration({ defaultValue: '5m' }), - - /** - * notTouchedTimeout controls how long do we store unpersisted search session results, - * after the last search in the session has completed - */ - notTouchedTimeout: schema.duration({ defaultValue: '5m' }), - /** - * notTouchedInProgressTimeout controls how long do allow a search session to run after - * a user has navigated away without persisting - */ - notTouchedInProgressTimeout: schema.duration({ defaultValue: '1m' }), - /** - * maxUpdateRetries controls how many retries we perform while attempting to save a search session - */ - maxUpdateRetries: schema.number({ defaultValue: 3 }), - /** - * defaultExpiration controls how long search sessions are valid for, until they are expired. - */ - defaultExpiration: schema.duration({ defaultValue: '7d' }), - management: schema.object({ - /** - * maxSessions controls how many saved search sessions we display per page on the management screen. - */ - maxSessions: schema.number({ defaultValue: 10000 }), - /** - * refreshInterval controls how often we refresh the management screen. - */ - refreshInterval: schema.duration({ defaultValue: '10s' }), - /** - * refreshTimeout controls how often we refresh the management screen. - */ - refreshTimeout: schema.duration({ defaultValue: '1m' }), - expiresSoonWarning: schema.duration({ defaultValue: '1d' }), - }), - }), + sessions: searchSessionsConfigSchema, }), }); diff --git a/x-pack/plugins/data_enhanced/public/index.ts b/x-pack/plugins/data_enhanced/public/index.ts index be3a5c7e858e3..c3adf19fabe13 100644 --- a/x-pack/plugins/data_enhanced/public/index.ts +++ b/x-pack/plugins/data_enhanced/public/index.ts @@ -14,4 +14,7 @@ export const plugin = (initializerContext: PluginInitializerContext { @@ -36,31 +30,13 @@ export class EnhancedDataServerPlugin } public setup(core: CoreSetup, deps: SetupDependencies) { - const usage = deps.usageCollection ? usageProvider(core) : undefined; - core.uiSettings.register(getUiSettings()); core.savedObjects.registerType(searchSessionSavedObjectType); - deps.data.search.registerSearchStrategy( - ENHANCED_ES_SEARCH_STRATEGY, - enhancedEsSearchStrategyProvider( - this.config, - this.initializerContext.config.legacy.globalConfig$, - this.logger, - usage - ) - ); - - deps.data.search.registerSearchStrategy( - EQL_SEARCH_STRATEGY, - eqlSearchStrategyProvider(this.logger) - ); - this.sessionService = new SearchSessionService(this.logger, this.config, deps.security); deps.data.__enhance({ search: { - defaultStrategy: ENHANCED_ES_SEARCH_STRATEGY, sessionService: this.sessionService, }, }); diff --git a/x-pack/plugins/data_enhanced/server/saved_objects/search_session.ts b/x-pack/plugins/data_enhanced/server/saved_objects/search_session.ts index 4e53e951a8dc3..9b5af9a6fa9e8 100644 --- a/x-pack/plugins/data_enhanced/server/saved_objects/search_session.ts +++ b/x-pack/plugins/data_enhanced/server/saved_objects/search_session.ts @@ -6,7 +6,7 @@ */ import { SavedObjectsType } from 'kibana/server'; -import { SEARCH_SESSION_TYPE } from '../../common'; +import { SEARCH_SESSION_TYPE } from '../../../../../src/plugins/data/common'; import { searchSessionSavedObjectMigrations } from './search_session_migration'; export const searchSessionSavedObjectType: SavedObjectsType = { diff --git a/x-pack/plugins/data_enhanced/server/saved_objects/search_session_migration.test.ts b/x-pack/plugins/data_enhanced/server/saved_objects/search_session_migration.test.ts index 53b1b7f52b363..6682122c66f9c 100644 --- a/x-pack/plugins/data_enhanced/server/saved_objects/search_session_migration.test.ts +++ b/x-pack/plugins/data_enhanced/server/saved_objects/search_session_migration.test.ts @@ -10,8 +10,7 @@ import { SearchSessionSavedObjectAttributesPre$7$13$0, } from './search_session_migration'; import { SavedObject } from '../../../../../src/core/types'; -import { SEARCH_SESSION_TYPE } from '../../../../../src/plugins/data/common'; -import { SearchSessionStatus } from '../../common/search/session/status'; +import { SEARCH_SESSION_TYPE, SearchSessionStatus } from '../../../../../src/plugins/data/common'; import { SavedObjectMigrationContext } from 'kibana/server'; const mockCompletedSessionSavedObject: SavedObject = { diff --git a/x-pack/plugins/data_enhanced/server/saved_objects/search_session_migration.ts b/x-pack/plugins/data_enhanced/server/saved_objects/search_session_migration.ts index b9ea85a333da2..0ba8858ef525b 100644 --- a/x-pack/plugins/data_enhanced/server/saved_objects/search_session_migration.ts +++ b/x-pack/plugins/data_enhanced/server/saved_objects/search_session_migration.ts @@ -9,7 +9,7 @@ import { SavedObjectMigrationMap, SavedObjectUnsanitizedDoc } from 'kibana/serve import { SearchSessionSavedObjectAttributes as SearchSessionSavedObjectAttributesLatest, SearchSessionStatus, -} from '../../common'; +} from '../../../../../src/plugins/data/common'; /** * Search sessions were released in 7.12.0 diff --git a/x-pack/plugins/data_enhanced/server/search/index.ts b/x-pack/plugins/data_enhanced/server/search/index.ts index 23edd43fd4799..0430d283667d0 100644 --- a/x-pack/plugins/data_enhanced/server/search/index.ts +++ b/x-pack/plugins/data_enhanced/server/search/index.ts @@ -5,6 +5,4 @@ * 2.0. */ -export { enhancedEsSearchStrategyProvider } from './es_search_strategy'; -export { eqlSearchStrategyProvider } from './eql_search_strategy'; export * from './session'; diff --git a/x-pack/plugins/data_enhanced/server/search/session/check_running_sessions.test.ts b/x-pack/plugins/data_enhanced/server/search/session/check_running_sessions.test.ts index eba463662e26d..c0a48d5d44862 100644 --- a/x-pack/plugins/data_enhanced/server/search/session/check_running_sessions.test.ts +++ b/x-pack/plugins/data_enhanced/server/search/session/check_running_sessions.test.ts @@ -14,7 +14,7 @@ import { SearchSessionSavedObjectAttributes, ENHANCED_ES_SEARCH_STRATEGY, EQL_SEARCH_STRATEGY, -} from '../../../common'; +} from '../../../../../../src/plugins/data/common'; import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; import { SearchSessionsConfig, SearchStatus } from './types'; import moment from 'moment'; diff --git a/x-pack/plugins/data_enhanced/server/search/session/check_running_sessions.ts b/x-pack/plugins/data_enhanced/server/search/session/check_running_sessions.ts index bb1e9643cd0d5..6787d31ed2b74 100644 --- a/x-pack/plugins/data_enhanced/server/search/session/check_running_sessions.ts +++ b/x-pack/plugins/data_enhanced/server/search/session/check_running_sessions.ts @@ -15,14 +15,14 @@ import { import moment from 'moment'; import { EMPTY, from, Observable } from 'rxjs'; import { catchError, concatMap } from 'rxjs/operators'; -import { nodeBuilder } from '../../../../../../src/plugins/data/common'; import { + nodeBuilder, ENHANCED_ES_SEARCH_STRATEGY, SEARCH_SESSION_TYPE, SearchSessionRequestInfo, SearchSessionSavedObjectAttributes, SearchSessionStatus, -} from '../../../common'; +} from '../../../../../../src/plugins/data/common'; import { getSearchStatus } from './get_search_status'; import { getSessionStatus } from './get_session_status'; import { SearchSessionsConfig, SearchStatus } from './types'; diff --git a/x-pack/plugins/data_enhanced/server/search/session/get_search_status.ts b/x-pack/plugins/data_enhanced/server/search/session/get_search_status.ts index dffccbee9db92..e228ba725489c 100644 --- a/x-pack/plugins/data_enhanced/server/search/session/get_search_status.ts +++ b/x-pack/plugins/data_enhanced/server/search/session/get_search_status.ts @@ -9,8 +9,8 @@ import { i18n } from '@kbn/i18n'; import { ApiResponse } from '@elastic/elasticsearch'; import { ElasticsearchClient } from 'src/core/server'; import { SearchStatus } from './types'; -import { AsyncSearchStatusResponse } from '../types'; -import { SearchSessionRequestInfo } from '../../../common'; +import { SearchSessionRequestInfo } from '../../../../../../src/plugins/data/common'; +import { AsyncSearchStatusResponse } from '../../../../../../src/plugins/data/server'; export async function getSearchStatus( client: ElasticsearchClient, diff --git a/x-pack/plugins/data_enhanced/server/search/session/get_session_status.test.ts b/x-pack/plugins/data_enhanced/server/search/session/get_session_status.test.ts index 19e937374882b..fc86e75297393 100644 --- a/x-pack/plugins/data_enhanced/server/search/session/get_session_status.test.ts +++ b/x-pack/plugins/data_enhanced/server/search/session/get_session_status.test.ts @@ -7,7 +7,7 @@ import { SearchStatus } from './types'; import { getSessionStatus } from './get_session_status'; -import { SearchSessionStatus } from '../../../common'; +import { SearchSessionStatus } from '../../../../../../src/plugins/data/common'; describe('getSessionStatus', () => { test("returns an in_progress status if there's nothing inside the session", () => { diff --git a/x-pack/plugins/data_enhanced/server/search/session/get_session_status.ts b/x-pack/plugins/data_enhanced/server/search/session/get_session_status.ts index 09156ae79cf8b..23e02eedc0004 100644 --- a/x-pack/plugins/data_enhanced/server/search/session/get_session_status.ts +++ b/x-pack/plugins/data_enhanced/server/search/session/get_session_status.ts @@ -5,7 +5,10 @@ * 2.0. */ -import { SearchSessionSavedObjectAttributes, SearchSessionStatus } from '../../../common'; +import { + SearchSessionSavedObjectAttributes, + SearchSessionStatus, +} from '../../../../../../src/plugins/data/common/'; import { SearchStatus } from './types'; export function getSessionStatus(session: SearchSessionSavedObjectAttributes): SearchSessionStatus { diff --git a/x-pack/plugins/data_enhanced/server/search/session/monitoring_task.ts b/x-pack/plugins/data_enhanced/server/search/session/monitoring_task.ts index c0dc69dfc307b..7b7b1412987be 100644 --- a/x-pack/plugins/data_enhanced/server/search/session/monitoring_task.ts +++ b/x-pack/plugins/data_enhanced/server/search/session/monitoring_task.ts @@ -17,7 +17,7 @@ import { import { checkRunningSessions } from './check_running_sessions'; import { CoreSetup, SavedObjectsClient, Logger } from '../../../../../../src/core/server'; import { ConfigSchema } from '../../../config'; -import { SEARCH_SESSION_TYPE } from '../../../common'; +import { SEARCH_SESSION_TYPE } from '../../../../../../src/plugins/data/common'; import { DataEnhancedStartDependencies } from '../../type'; export const SEARCH_SESSIONS_TASK_TYPE = 'search_sessions_monitor'; diff --git a/x-pack/plugins/data_enhanced/server/search/session/session_service.test.ts b/x-pack/plugins/data_enhanced/server/search/session/session_service.test.ts index f1f8805a28884..374dbee2384d5 100644 --- a/x-pack/plugins/data_enhanced/server/search/session/session_service.test.ts +++ b/x-pack/plugins/data_enhanced/server/search/session/session_service.test.ts @@ -11,7 +11,6 @@ import { SavedObjectsErrorHelpers, } from '../../../../../../src/core/server'; import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; -import { SearchSessionStatus, SEARCH_SESSION_TYPE } from '../../../common'; import { SearchSessionService } from './session_service'; import { createRequestHash } from './utils'; import moment from 'moment'; @@ -19,7 +18,11 @@ import { coreMock } from '../../../../../../src/core/server/mocks'; import { ConfigSchema } from '../../../config'; import { taskManagerMock } from '../../../../task_manager/server/mocks'; import { AuthenticatedUser } from '../../../../security/common/model'; -import { nodeBuilder } from '../../../../../../src/plugins/data/common'; +import { + nodeBuilder, + SEARCH_SESSION_TYPE, + SearchSessionStatus, +} from '../../../../../../src/plugins/data/common'; import { TaskManagerStartContract } from '../../../../task_manager/server'; const MAX_UPDATE_RETRIES = 3; diff --git a/x-pack/plugins/data_enhanced/server/search/session/session_service.ts b/x-pack/plugins/data_enhanced/server/search/session/session_service.ts index b5f7da594d53b..138f42549a094 100644 --- a/x-pack/plugins/data_enhanced/server/search/session/session_service.ts +++ b/x-pack/plugins/data_enhanced/server/search/session/session_service.ts @@ -21,6 +21,8 @@ import { IKibanaSearchRequest, ISearchOptions, nodeBuilder, + ENHANCED_ES_SEARCH_STRATEGY, + SEARCH_SESSION_TYPE, } from '../../../../../../src/plugins/data/common'; import { esKuery, ISearchSessionService } from '../../../../../../src/plugins/data/server'; import { AuthenticatedUser, SecurityPluginSetup } from '../../../../security/server'; @@ -29,12 +31,10 @@ import { TaskManagerStartContract, } from '../../../../task_manager/server'; import { - ENHANCED_ES_SEARCH_STRATEGY, SearchSessionRequestInfo, SearchSessionSavedObjectAttributes, SearchSessionStatus, - SEARCH_SESSION_TYPE, -} from '../../../common'; +} from '../../../../../../src/plugins/data/common'; import { createRequestHash } from './utils'; import { ConfigSchema } from '../../../config'; import { @@ -461,6 +461,7 @@ export class SearchSessionService extend: this.extend.bind(this, deps, user), cancel: this.cancel.bind(this, deps, user), delete: this.delete.bind(this, deps, user), + getConfig: () => this.config.search.sessions, }; }; }; diff --git a/x-pack/plugins/osquery/server/search_strategy/osquery/index.ts b/x-pack/plugins/osquery/server/search_strategy/osquery/index.ts index e589ab7a3aa06..9fffb0726dce6 100644 --- a/x-pack/plugins/osquery/server/search_strategy/osquery/index.ts +++ b/x-pack/plugins/osquery/server/search_strategy/osquery/index.ts @@ -11,7 +11,7 @@ import { PluginStart, shimHitsTotal, } from '../../../../../../src/plugins/data/server'; -import { ENHANCED_ES_SEARCH_STRATEGY } from '../../../../data_enhanced/common'; +import { ENHANCED_ES_SEARCH_STRATEGY } from '../../../../../../src/plugins/data/common'; import { FactoryQueryTypes, StrategyResponseType, diff --git a/x-pack/plugins/security_solution/common/search_strategy/timeline/events/eql/index.ts b/x-pack/plugins/security_solution/common/search_strategy/timeline/events/eql/index.ts index 6bf01e478a972..c508876032fca 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/timeline/events/eql/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/timeline/events/eql/index.ts @@ -9,7 +9,7 @@ import { EuiComboBoxOptionOption } from '@elastic/eui'; import { EqlSearchStrategyRequest, EqlSearchStrategyResponse, -} from '../../../../../../data_enhanced/common'; +} from '../../../../../../../../src/plugins/data/common'; import { Inspect, Maybe, PaginationInputPaginated } from '../../..'; import { TimelineEdges, TimelineEventsAllRequestOptions } from '../..'; import { EqlSearchResponse } from '../../../../detection_engine/types'; diff --git a/x-pack/plugins/security_solution/public/common/hooks/eql/api.ts b/x-pack/plugins/security_solution/public/common/hooks/eql/api.ts index 6c107ae04c1a3..7e7942317788b 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/eql/api.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/eql/api.ts @@ -9,8 +9,8 @@ import { DataPublicPluginStart } from '../../../../../../../src/plugins/data/pub import { EqlSearchStrategyRequest, EqlSearchStrategyResponse, -} from '../../../../../data_enhanced/common'; -import { EQL_SEARCH_STRATEGY } from '../../../../../data_enhanced/public'; + EQL_SEARCH_STRATEGY, +} from '../../../../../../../src/plugins/data/common'; import { getValidationErrors, isErrorResponse, diff --git a/x-pack/plugins/security_solution/public/common/hooks/eql/eql_search_response.mock.ts b/x-pack/plugins/security_solution/public/common/hooks/eql/eql_search_response.mock.ts index 56000ce4b7bde..513bfc654027d 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/eql/eql_search_response.mock.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/eql/eql_search_response.mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { EqlSearchStrategyResponse } from '../../../../../data_enhanced/common'; +import { EqlSearchStrategyResponse } from '../../../../../../../src/plugins/data/common'; import { Source } from './types'; import { EqlSearchResponse } from '../../../../common/detection_engine/types'; import { Connection } from '@elastic/elasticsearch'; diff --git a/x-pack/plugins/security_solution/public/common/hooks/eql/helpers.test.ts b/x-pack/plugins/security_solution/public/common/hooks/eql/helpers.test.ts index a6cd135e88ec5..2dba3e3af3773 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/eql/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/eql/helpers.test.ts @@ -7,7 +7,7 @@ import moment from 'moment'; -import { EqlSearchStrategyResponse } from '../../../../../data_enhanced/common'; +import { EqlSearchStrategyResponse } from '../../../../../../../src/plugins/data/common'; import { Source } from './types'; import { EqlSearchResponse } from '../../../../common/detection_engine/types'; import { inputsModel } from '../../../common/store'; diff --git a/x-pack/plugins/security_solution/public/common/hooks/eql/helpers.ts b/x-pack/plugins/security_solution/public/common/hooks/eql/helpers.ts index 399bbb08aec5f..68a8cb53b3815 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/eql/helpers.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/eql/helpers.ts @@ -9,7 +9,7 @@ import moment from 'moment'; import { Unit } from '@elastic/datemath'; import { inputsModel } from '../../../common/store'; -import { EqlSearchStrategyResponse } from '../../../../../data_enhanced/common'; +import { EqlSearchStrategyResponse } from '../../../../../../../src/plugins/data/common'; import { InspectResponse } from '../../../types'; import { EqlPreviewResponse, Source } from './types'; import { BaseHit, EqlSearchResponse } from '../../../../common/detection_engine/types'; diff --git a/x-pack/plugins/security_solution/public/common/hooks/eql/use_eql_preview.test.ts b/x-pack/plugins/security_solution/public/common/hooks/eql/use_eql_preview.test.ts index 0245a35ef79b6..2afe14644f5e9 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/eql/use_eql_preview.test.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/eql/use_eql_preview.test.ts @@ -11,7 +11,7 @@ import { of, throwError } from 'rxjs'; import { delay } from 'rxjs/operators'; import * as i18n from '../translations'; -import { EqlSearchStrategyResponse } from '../../../../../data_enhanced/common'; +import { EqlSearchStrategyResponse } from '../../../../../../../src/plugins/data/common'; import { Source } from './types'; import { EqlSearchResponse } from '../../../../common/detection_engine/types'; import { useKibana } from '../../../common/lib/kibana'; diff --git a/x-pack/plugins/security_solution/public/common/hooks/eql/use_eql_preview.ts b/x-pack/plugins/security_solution/public/common/hooks/eql/use_eql_preview.ts index 0c0834fc2a457..5632dd0ed03be 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/eql/use_eql_preview.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/eql/use_eql_preview.ts @@ -16,12 +16,10 @@ import { isCompleteResponse, isErrorResponse, isPartialResponse, -} from '../../../../../../../src/plugins/data/common'; -import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; -import { EqlSearchStrategyRequest, EqlSearchStrategyResponse, -} from '../../../../../data_enhanced/common'; +} from '../../../../../../../src/plugins/data/common'; +import { AbortError } from '../../../../../../../src/plugins/kibana_utils/common'; import { formatInspect, getEqlAggsData } from './helpers'; import { EqlPreviewResponse, EqlPreviewRequest, Source } from './types'; import { hasEqlSequenceQuery } from '../../../../common/detection_engine/utils'; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/index.ts index 358c6591ea66e..2980f63df8a67 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/index.ts @@ -11,7 +11,7 @@ import { PluginStart, shimHitsTotal, } from '../../../../../../src/plugins/data/server'; -import { ENHANCED_ES_SEARCH_STRATEGY } from '../../../../data_enhanced/common'; +import { ENHANCED_ES_SEARCH_STRATEGY } from '../../../../../../src/plugins/data/common'; import { FactoryQueryTypes, StrategyResponseType, diff --git a/x-pack/plugins/security_solution/server/search_strategy/timeline/eql/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/timeline/eql/__mocks__/index.ts index 9f9aa182ca0f7..a3499b5855f50 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/timeline/eql/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/timeline/eql/__mocks__/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { EqlSearchStrategyResponse } from '../../../../../../data_enhanced/common'; +import { EqlSearchStrategyResponse } from '../../../../../../../../src/plugins/data/common'; import { EqlSearchResponse } from '../../../../../common/detection_engine/types'; export const sequenceResponse = ({ diff --git a/x-pack/plugins/security_solution/server/search_strategy/timeline/eql/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/timeline/eql/helpers.ts index ea744d17e1262..65be9a773adb9 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/timeline/eql/helpers.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/timeline/eql/helpers.ts @@ -6,7 +6,7 @@ */ import { isEmpty } from 'lodash/fp'; -import { EqlSearchStrategyResponse } from '../../../../../data_enhanced/common'; +import { EqlSearchStrategyResponse } from '../../../../../../../src/plugins/data/common'; import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../../common/constants'; import { EqlSearchResponse, EqlSequence } from '../../../../common/detection_engine/types'; import { EventHit, TimelineEdges } from '../../../../common/search_strategy'; diff --git a/x-pack/plugins/security_solution/server/search_strategy/timeline/eql/index.ts b/x-pack/plugins/security_solution/server/search_strategy/timeline/eql/index.ts index 249f5582d2a39..56e5bd63d6b23 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/timeline/eql/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/timeline/eql/index.ts @@ -14,7 +14,7 @@ import { import { EqlSearchStrategyResponse, EQL_SEARCH_STRATEGY, -} from '../../../../../data_enhanced/common'; +} from '../../../../../../../src/plugins/data/common'; import { EqlSearchResponse } from '../../../../common/detection_engine/types'; import { TimelineEqlRequestOptions, diff --git a/x-pack/plugins/security_solution/server/search_strategy/timeline/index.ts b/x-pack/plugins/security_solution/server/search_strategy/timeline/index.ts index 438d3dca3bf3f..4dfa9831f9e6e 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/timeline/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/timeline/index.ts @@ -11,7 +11,7 @@ import { PluginStart, shimHitsTotal, } from '../../../../../../src/plugins/data/server'; -import { ENHANCED_ES_SEARCH_STRATEGY } from '../../../../data_enhanced/common'; +import { ENHANCED_ES_SEARCH_STRATEGY } from '../../../../../../src/plugins/data/common'; import { TimelineFactoryQueryTypes, TimelineStrategyResponseType, diff --git a/x-pack/test/api_integration/apis/search/session.ts b/x-pack/test/api_integration/apis/search/session.ts index 63a6a842fd9f7..d47199a0f1c1e 100644 --- a/x-pack/test/api_integration/apis/search/session.ts +++ b/x-pack/test/api_integration/apis/search/session.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; -import { SearchSessionStatus } from '../../../../plugins/data_enhanced/common'; +import { SearchSessionStatus } from '../../../../../src/plugins/data/common'; export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); diff --git a/x-pack/test/functional/page_objects/search_sessions_management_page.ts b/x-pack/test/functional/page_objects/search_sessions_management_page.ts index 402569971691d..3f0e6b80b483a 100644 --- a/x-pack/test/functional/page_objects/search_sessions_management_page.ts +++ b/x-pack/test/functional/page_objects/search_sessions_management_page.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SEARCH_SESSIONS_TABLE_ID } from '../../../plugins/data_enhanced/common/search'; +import { SEARCH_SESSIONS_TABLE_ID } from '../../../../src/plugins/data/common'; import { FtrProviderContext } from '../ftr_provider_context'; export function SearchSessionsPageProvider({ getService, getPageObjects }: FtrProviderContext) { From 533c8bcf8068092241cc33018012b4ab5c77bb16 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 21 Apr 2021 11:06:37 -0400 Subject: [PATCH 16/18] [DOCS] Updates notifications lifetime advanced settings descriptions (#97692) (#97832) Co-authored-by: Christiane (Tina) Heiligers --- docs/management/advanced-options.asciidoc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 5068d17d6e410..ae6801e5672f0 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -323,20 +323,19 @@ https://help.github.com/en/articles/basic-writing-and-formatting-syntax[Markdown [[notifications-lifetime-banner]]`notifications:lifetime:banner`:: The duration, in milliseconds, for banner notification displays. The default -value is 3000000. Set this field to `Infinity` to disable banner notifications. +value is 3000000. [[notificatios-lifetime-error]]`notifications:lifetime:error`:: The duration, in milliseconds, for error notification displays. The default -value is 300000. Set this field to `Infinity` to disable error notifications. +value is 300000. [[notifications-lifetime-info]]`notifications:lifetime:info`:: The duration, in milliseconds, for information notification displays. The -default value is 5000. Set this field to `Infinity` to disable information -notifications. +default value is 5000. [[notifications-lifetime-warning]]`notifications:lifetime:warning`:: The duration, in milliseconds, for warning notification displays. The default -value is 10000. Set this field to `Infinity` to disable warning notifications. +value is 10000. [float] From aa3f1a2c283e341057584974f487eb2b76cccc10 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Wed, 21 Apr 2021 16:12:16 +0100 Subject: [PATCH 17/18] [Discover] Attempt at fixing a failing test (#97790) (#97814) --- test/functional/apps/discover/_data_grid_context.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/functional/apps/discover/_data_grid_context.ts b/test/functional/apps/discover/_data_grid_context.ts index bc259c71b47b4..ab826ec4f985f 100644 --- a/test/functional/apps/discover/_data_grid_context.ts +++ b/test/functional/apps/discover/_data_grid_context.ts @@ -34,8 +34,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const dashboardAddPanel = getService('dashboardAddPanel'); const browser = getService('browser'); - // FLAKY: https://github.com/elastic/kibana/issues/94545 - describe.skip('discover data grid context tests', () => { + describe('discover data grid context tests', () => { before(async () => { await esArchiver.load('discover'); await esArchiver.loadIfNeeded('logstash_functional'); @@ -110,7 +109,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await alert?.accept(); expect(await browser.getCurrentUrl()).to.contain('#/context'); await PageObjects.header.waitUntilLoadingHasFinished(); - expect(await docTable.getBodyRows()).to.have.length(6); + await retry.waitFor('document table has a length of 6', async () => { + const nrOfDocs = (await docTable.getBodyRows()).length; + return nrOfDocs === 6; + }); }); }); } From bdc8663cb22f0f1dd3447074148122881bcea6ff Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 21 Apr 2021 11:23:24 -0400 Subject: [PATCH 18/18] [FTR] Disables GeoIP downloader (#97813) (#97835) A temporary workaround to the increased segment memory issues we have in the new ES snapshots Signed-off-by: Tyler Smalley Co-authored-by: Tyler Smalley --- test/common/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/common/config.js b/test/common/config.js index 9b6bb9c61bcbe..26f6ee1c84e1a 100644 --- a/test/common/config.js +++ b/test/common/config.js @@ -21,7 +21,7 @@ export default function () { servers, esTestCluster: { - serverArgs: ['xpack.security.enabled=false'], + serverArgs: ['xpack.security.enabled=false', 'geoip.downloader.enabled=false'], }, kbnTestServer: {